Android中高级面试(三):架构组件与性能优化实战
🔍 一、ViewModel 的生存周期控制机制
1.1 核心设计思想
// ViewModelProvider 初始化示例
val viewModel = ViewModelProvider(
this,
object : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return MyViewModel(repository) as T
}
}
).get(MyViewModel::class.java)
// ViewModelStore 关键源码(简化版)
public class ViewModelStore {
private final HashMap<String, ViewModel> mMap = new HashMap<>();
public final void put(String key, ViewModel viewModel) {
ViewModel oldViewModel = mMap.put(key, viewModel);
if (oldViewModel != null) {
oldViewModel.onCleared(); // 触发旧ViewModel清理
}
}
}
📌 设计要点:
ViewModelStoreOwner
接口(如Activity/Fragment)持有ViewModelStore
实例- 屏幕旋转时Activity重建但
ViewModelStore
被保留 onCleared()
触发时机:当宿主永久销毁时(非配置变更)
1.2 生命周期感知原理
⚡ 二、LiveData 的响应式编程实践
2.1 事件总线替代方案
class EventLiveData<T> : MutableLiveData<T>() {
private val pendingMap = ConcurrentHashMap<Int, Boolean>()
@MainThread
override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
val wrapper = ObserverWrapper(observer)
super.observe(owner, wrapper)
}
inner class ObserverWrapper(val observer: Observer<in T>) : Observer<T> {
override fun onChanged(t: T?) {
if (pendingMap.hashCode() == false) return
observer.onChanged(t)
}
}
}
🚀 解决痛点:
- 避免粘性事件导致的重复触发
- 线程安全的观察者管理
2.2 结合Kotlin Flow的高级用法
fun <T> LiveData<T>.asFlow(): Flow<T> = callbackFlow {
val observer = Observer<T> { value ->
trySend(value).isSuccess // 将LiveData值发送到Flow
}
observeForever(observer)
awaitClose { removeObserver(observer) }
}
// 使用示例
viewModel.data.asFlow()
.filter { it.isValid() }
.map { it.transform() }
.launchIn(viewModelScope)
💾 三、Room数据库的进阶优化
3.1 索引优化实战
@Entity(indices = [Index(value = ["last_name", "address"], unique = true)])
data class User(
@PrimaryKey val id: Int,
@ColumnInfo(name = "first_name") val firstName: String?,
@ColumnInfo(name = "last_name") val lastName: String?,
@ColumnInfo(name = "address") val address: String?
)
// 多表联合查询优化
@Query("SELECT * FROM user INNER JOIN book ON user.id = book.user_id WHERE book.type = :type")
fun getUsersWithBooks(type: BookType): Flowable<List<UserWithBooks>>
3.2 数据库迁移策略
val MIGRATION_1_2 = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
// 添加新表
database.execSQL("CREATE TABLE IF NOT EXISTS `address` (`id` INTEGER PRIMARY KEY, `street` TEXT)")
// 修改旧表结构
database.execSQL("ALTER TABLE user ADD COLUMN phone TEXT DEFAULT ''")
}
}
Room.databaseBuilder(context, AppDatabase::class.java, "sample.db")
.addMigrations(MIGRATION_1_2)
.addCallback(object : RoomDatabase.Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
// 初始化数据
}
})
.build()
🧪 四、内存泄漏检测与治理
4.1 LeakCanary 2.0定制化
class CustomLeakCanary : AbstractLeakCanary() {
override fun onLeakFound(heapAnalysis: HeapAnalysis) {
// 自定义泄漏上报逻辑
FirebaseCrashlytics.getInstance().log("Memory leak detected: ${heapAnalysis.signature}")
}
}
// 配置示例
LeakCanary.config = LeakCanary.config.copy(
dumpHeap = BuildConfig.DEBUG, // 仅Debug模式检测
retainedVisibleThreshold = 3, // 泄漏阈值
onHeapAnalyzedListener = CustomLeakCanary()
)
4.2 匿名内部类泄漏场景
// 错误示例:匿名Handler导致Activity泄漏
public class MainActivity extends Activity {
private final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// 持有Activity隐式引用
}
};
}
// 修复方案:静态内部类+弱引用
private static class SafeHandler extends Handler {
private final WeakReference<Activity> mActivityRef;
SafeHandler(Activity activity) {
mActivityRef = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
Activity activity = mActivityRef.get();
if (activity == null || activity.isFinishing()) return;
// 安全操作
}
}
🚀 五、Kotlin协程在MVVM中的高阶应用
5.1 结构化并发实践
class ProductViewModel : ViewModel() {
private val _products = MutableStateFlow<List<Product>>(emptyList())
val products: StateFlow<List<Product>> = _products
init {
viewModelScope.launch(Dispatchers.IO + CoroutineExceptionHandler { _, e ->
Log.e("CoroutineError", e.message)
}) {
val productJob = async { fetchProducts() }
val promoJob = async { fetchPromotions() }
// 合并网络请求结果
_products.value = productJob.await()
.combinePromotions(promoJob.await())
}
}
private suspend fun fetchProducts() = withContext(Dispatchers.IO) {
repository.getProducts().map { it.toDomainModel() }
}
}
5.2 Flow状态管理策略
sealed interface UiState<out T> {
object Loading : UiState<Nothing>
data class Success<T>(val data: T) : UiState<T>
data class Error(val exception: Throwable) : UiState<Nothing>
}
fun <T> Flow<T>.asStateFlow(): StateFlow<UiState<T>> {
return this.map<T, UiState<T>> { UiState.Success(it) }
.onStart { emit(UiState.Loading) }
.catch { e -> emit(UiState.Error(e)) }
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), UiState.Loading)
}
📊 六、性能优化监控体系
6.1 帧率监控方案
class FrameMonitor : Choreographer.FrameCallback {
private var lastFrameTime = 0L
private val frameInterval = 1000L / 60 // 16ms/帧
override fun doFrame(frameTimeNanos: Long) {
val currentTime = System.currentTimeMillis()
if (lastFrameTime > 0) {
val duration = currentTime - lastFrameTime
if (duration > frameInterval * 2) {
Log.w("FrameDrop", "丢帧 detected: ${duration - frameInterval}ms")
}
}
lastFrameTime = currentTime
Choreographer.getInstance().postFrameCallback(this)
}
}
// 在Application中启动
Choreographer.getInstance().postFrameCallback(FrameMonitor())
6.2 内存抖动检测
Debug.startAllocCounting(); // 开启分配计数
// 在关键操作后检测
void checkAllocations() {
long allocCount = Debug.getGlobalAllocCount();
long allocSize = Debug.getGlobalAllocSize();
if (allocCount > 1000 || allocSize > 102400) { // 阈值设置
Log.e("MemoryChurn", "内存抖动警告: " + allocCount + "次分配, " + allocSize + "字节");
}
Debug.resetAllocCount(); // 重置计数器
}
🌐 七、跨进程通信优化方案
7.1 Binder连接池设计
public class BinderPool {
private static final String TAG = "BinderPool";
private Context mContext;
private IBinderPool mBinderPool;
private static volatile BinderPool sInstance;
private BinderPool(Context context) {
mContext = context.getApplicationContext();
connectBinderPoolService();
}
private synchronized void connectBinderPoolService() {
Intent service = new Intent(mContext, BinderPoolService.class);
mContext.bindService(service, mConnection, Context.BIND_AUTO_CREATE);
}
public IBinder queryBinder(int binderCode) {
try {
return mBinderPool.queryBinder(binderCode);
} catch (RemoteException e) {
e.printStackTrace();
}
return null;
}
}
7.2 AIDL接口版本兼容方案
// 接口定义时预留扩展方法
interface IRemoteService {
void basicMethod(int param) throws RemoteException;
void apiVersion2() throws RemoteException; // V2新增
void apiVersion3() throws RemoteException; // V3新增
}
// 服务端实现
private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
@Override
public void basicMethod(int param) {
// 基础实现
}
@Override
public void apiVersion2() throws RemoteException {
// V2功能实现
}
@Override
public void apiVersion3() throws RemoteException {
throw new RemoteException("Method not implemented"); // 未实现方法
}
};
📈 八、启动速度优化体系
8.1 异步初始化框架
object AppInitManager {
private val ioDispatcher = Dispatchers.IO.limitedParallelism(4)
private val tasks = mutableListOf<InitTask>()
fun addTask(task: InitTask) {
tasks.add(task)
}
fun start(scope: CoroutineScope) {
tasks.map { task ->
scope.launch(ioDispatcher) {
val start = SystemClock.uptimeMillis()
task.execute()
Log.d("InitTask", "${task.name} took ${SystemClock.uptimeMillis() - start}ms")
}
}
}
}
// 任务定义
abstract class InitTask(val name: String) {
abstract fun execute()
}
8.2 ClassLoader优化策略
// 自定义ClassLoader实现
public class HotClassLoader extends BaseDexClassLoader {
private final Map<String, Class<?>> loadedClasses = new ConcurrentHashMap<>();
public HotClassLoader(String dexPath, ClassLoader parent) {
super(dexPath, null, null, parent);
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
Class<?> clazz = loadedClasses.get(name);
if (clazz != null) return clazz;
// 从Dex文件加载
clazz = super.findClass(name);
loadedClasses.put(name, clazz);
return clazz;
}
}
🧠 九、Jetpack Compose 性能调优
9.1 重组范围控制
@Composable
fun UserProfile(user: User) {
Column {
// 使用derivedStateOf减少重组
val username by remember { derivedStateOf { user.name.uppercase() } }
Text(text = username, modifier = Modifier.clickable { /*...*/ })
// 使用key控制列表项重组
LazyColumn {
items(users, key = { it.id }) { user ->
UserItem(user)
}
}
}
}
9.2 长列表优化技巧
@Composable
fun LargeList(items: List<Item>) {
LazyColumn {
itemsIndexed(
items = items,
key = { _, item -> item.id } // 关键:设置唯一key
) { index, item ->
if (index % 50 == 0) {
// 每50项添加一个StickyHeader
stickyHeader { SectionHeader(item.category) }
}
ItemRow(item)
}
}
}
🧩 十、动态化框架原理剖析
10.1 类加载双亲委派突破
public class HotFixClassLoader extends ClassLoader {
private final ClassLoader originClassLoader;
private final DexClassLoader patchClassLoader;
public HotFixClassLoader(ClassLoader parent, String dexPath) {
super(parent);
this.originClassLoader = parent;
this.patchClassLoader = new DexClassLoader(
dexPath, null, null, parent);
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
try {
// 优先从补丁包加载
return patchClassLoader.loadClass(name);
} catch (ClassNotFoundException e) {
// 回退到原始ClassLoader
return originClassLoader.loadClass(name);
}
}
}
10.2 资源热更新方案
public class HotResource {
public static void inject(Activity activity, String apkPath) {
try {
// 获取AssetManager实例
AssetManager assetManager = AssetManager.class.newInstance();
Method addAssetPath = assetManager.getClass().getMethod("addAssetPath", String.class);
addAssetPath.invoke(assetManager, apkPath);
// 替换Activity的Resources
Resources superRes = activity.getResources();
Resources newResources = new Resources(assetManager,
superRes.getDisplayMetrics(), superRes.getConfiguration());
Field field = activity.getClass().getDeclaredField("mResources");
field.setAccessible(true);
field.set(activity, newResources);
} catch (Exception e) {
e.printStackTrace();
}
}
}
🎯 总结
核心知识体系
面试要点提炼
- 架构设计深度:理解Jetpack组件在MVVM中的角色分工及数据流向
- 性能优化闭环:从问题定位(内存泄漏/卡顿)到解决方案的完整链路
- 跨进程通信本质:掌握Binder机制及AIDL接口的版本演进策略
- 协程高阶应用:结构化并发在复杂业务场景下的最佳实践
- 动态化前沿技术:热修复与资源更新的底层原理及兼容性处理
💡 提示:面试中常考场景——当面试官询问“如何设计一个稳定的长任务管理框架”时,可结合
ViewModel
+CoroutineScope
+SupervisorJob
的设计模式,配合自定义异常处理策略进行阐述。