xDocxDoc
AI
前端
后端
iOS
Android
Flutter
AI
前端
后端
iOS
Android
Flutter
  • Android 面试合集

    • Android面试基础篇(一):基础架构与核心组件深度剖析
    • Android中高级面试(二):架构组件与协程实战精要
    • Android中高级面试(三):架构组件与性能优化实战
    • Android 面试(四): Kotlin 基础
    • Android面试(五):深入Kotlin协程
    • Android面试(六):深入Kotlin Flow
    • Android面试(七):Jetpack Compose 深度解析与高频考点
    • Android架构面试(八):从Jetpack到模块化设计
    • Android架构面试(九):Clean Architecture 终极指南
    • Android面试全栈指南:从Kotlin到Jetpack Compose

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清理
        }
    }
}

📌 设计要点:

  1. ViewModelStoreOwner接口(如Activity/Fragment)持有ViewModelStore实例
  2. 屏幕旋转时Activity重建但ViewModelStore被保留
  3. 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();
        }
    }
}

🎯 总结

核心知识体系

面试要点提炼

  1. 架构设计深度:理解Jetpack组件在MVVM中的角色分工及数据流向
  2. 性能优化闭环:从问题定位(内存泄漏/卡顿)到解决方案的完整链路
  3. 跨进程通信本质:掌握Binder机制及AIDL接口的版本演进策略
  4. 协程高阶应用:结构化并发在复杂业务场景下的最佳实践
  5. 动态化前沿技术:热修复与资源更新的底层原理及兼容性处理

💡 提示:面试中常考场景——当面试官询问“如何设计一个稳定的长任务管理框架”时,可结合ViewModel+CoroutineScope+SupervisorJob的设计模式,配合自定义异常处理策略进行阐述。

最后更新: 2025/9/29 08:41
Prev
Android中高级面试(二):架构组件与协程实战精要
Next
Android 面试(四): Kotlin 基础