面试题 - Android - 第三方框架

150 阅读6分钟

1. LeakCanary 工作原理详解

1.1 核心组件

  1. RefWatcher: 负责监控对象引用
  2. HeapDumper: 负责生成内存快照
  3. HeapAnalyzer: 负责分析内存快照
  4. AndroidHeapDumper: Android平台特定的dump实现

1.2 详细工作流程

graph TD
    A[初始化] --> B[注册Activity生命周期]
    B --> C[Activity.onDestroy]
    C --> D[RefWatcher.watch]
    D --> E[创建KeyedWeakReference]
    E --> F[触发GC]
    F --> G{检查引用是否存在}
    G -->|存在| H[可能存在泄漏]
    G -->|不存在| I[正常回收]
    H --> J[生成heap dump]
    J --> K[分析引用链]
    K --> L[通知用户]

1.3 关键代码实现

class RefWatcher {
    fun watch(watchedReference: Any) {
        // 创建唯一标识
        val key = UUID.randomUUID().toString()
        // 创建弱引用
        val reference = KeyedWeakReference(
            watchedReference,
            key,
            referenceQueue
        )
        
        // 检查是否泄漏
        checkRetainedExecutor.execute {
            removeWeaklyReachableReferences()
            if (gone(reference)) return@execute
            
            // 可能存在泄漏,dump heap
            dumpHeap()
        }
    }
}

2. EventBus 实现原理深度解析

2.1 核心概念

  1. 订阅者(Subscriber): 接收事件的对象
  2. 发布者(Publisher): 发送事件的对象
  3. 事件(Event): 传递的消息对象
  4. 订阅方法(SubscribeMethod): 处理事件的方法

2.2 详细工作流程

graph TD
    A[注册订阅者] --> B[解析订阅方法]
    B --> C[保存订阅信息]
    D[发送事件] --> E[查找订阅者]
    E --> F[事件分发]
    F --> G[调用订阅方法]
    
    H[粘性事件] --> I[保存到内存]
    I --> J[新订阅者注册]
    J --> K[立即接收事件]

2.3 核心实现代码

public class EventBus {
    // 订阅者注册表
    private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
    
    // 事件类型查找表
    private final Map<Object, List<Class<?>>> typesBySubscriber;
    
    // 注册订阅者
    public void register(Object subscriber) {
        Class<?> subscriberClass = subscriber.getClass();
        // 查找订阅方法
        List<SubscriberMethod> subscriberMethods = 
            subscriberMethodFinder.findSubscriberMethods(subscriberClass);
            
        // 遍历订阅方法进行注册
        for (SubscriberMethod method : subscriberMethods) {
            subscribe(subscriber, method);
        }
    }
    
    // 发送事件
    public void post(Object event) {
        // 获取当前线程的PostingThreadState
        PostingThreadState postingState = currentPostingThreadState.get();
        
        // 获取事件队列
        List<Object> eventQueue = postingState.eventQueue;
        eventQueue.add(event);
        
        if (!postingState.isPosting) {
            postingState.isPosting = true;
            try {
                while (!eventQueue.isEmpty()) {
                    postSingleEvent(eventQueue.remove(0), postingState);
                }
            } finally {
                postingState.isPosting = false;
            }
        }
    }
}

3. Interceptor 拦截器深入解析

3.1 拦截器类型

  1. 应用拦截器(Application Interceptor)

    • 不需要担心中间响应比如重定向和重试
    • 只调用一次,即使HTTP响应是从缓存中获取
    • 可以访问应用程序设置的请求
  2. 网络拦截器(Network Interceptor)

    • 可以操作中间响应比如重定向和重试
    • 可以访问网络层的请求
    • 可以访问Connection信息

3.2 责任链模式实现

graph LR
    A[应用拦截器] --> B[网络拦截器]
    B --> C[缓存拦截器]
    C --> D[连接拦截器]
    D --> E[请求服务器]

3.3 详细代码实现

// 拦截器接口
interface Interceptor {
    fun intercept(chain: Chain): Response
    
    interface Chain {
        fun request(): Request
        fun proceed(request: Request): Response
    }
}

// 实际的拦截器链实现
class RealInterceptorChain(
    private val interceptors: List<Interceptor>,
    private val index: Int,
    private val request: Request,
    private val call: Call
) : Interceptor.Chain {
    
    override fun proceed(request: Request): Response {
        // 调用下一个拦截器
        val next = RealInterceptorChain(
            interceptors, index + 1, request, call)
        val interceptor = interceptors[index]
        return interceptor.intercept(next)
    }
}

// 日志拦截器示例
class LoggingInterceptor : Interceptor {
    override fun intercept(chain: Chain): Response {
        val request = chain.request()
        
        println("发送请求: ${request.url}")
        
        val response = chain.proceed(request)
        
        println("收到响应: ${response.code}")
        
        return response
    }
}

3.4 具体方案

让我详细讲解 Android 中 Interceptor 拦截器的应用场景和实现。

1. Interceptor 常见应用场景

1.1 统一请求头管理
class HeaderInterceptor : Interceptor {
    override fun intercept(chain: Chain): Response {
        val originalRequest = chain.request()
        
        // 添加通用 Header
        val newRequest = originalRequest.newBuilder()
            .header("Content-Type", "application/json")
            .header("Accept", "application/json")
            .header("Authorization", "Bearer ${TokenManager.getToken()}")
            .header("platform", "android")
            .header("version", BuildConfig.VERSION_NAME)
            .build()
            
        return chain.proceed(newRequest)
    }
}
1.2 网络日志记录
class LoggingInterceptor : Interceptor {
    override fun intercept(chain: Chain): Response {
        val request = chain.request()
        
        val startTime = System.nanoTime()
        Log.d("HTTP", "发送请求: ${request.url}")
        Log.d("HTTP", "请求头: ${request.headers}")
        
        val response = chain.proceed(request)
        
        val endTime = System.nanoTime()
        Log.d("HTTP", "接收响应: ${response.code}")
        Log.d("HTTP", "响应时间: ${(endTime - startTime) / 1e6}ms")
        
        return response
    }
}
1.3 缓存控制
class CacheInterceptor : Interceptor {
    override fun intercept(chain: Chain): Response {
        val request = chain.request()
        
        if (!NetworkUtils.isNetworkAvailable()) {
            // 无网络时强制使用缓存
            val newRequest = request.newBuilder()
                .cacheControl(CacheControl.FORCE_CACHE)
                .build()
            return chain.proceed(newRequest)
        }
        
        // 有网络时的缓存策略
        val newRequest = request.newBuilder()
            .header("Cache-Control", "public, max-age=60") // 缓存60秒
            .build()
            
        return chain.proceed(newRequest)
    }
}
1.4 请求重试
class RetryInterceptor(private val maxRetries: Int = 3) : Interceptor {
    override fun intercept(chain: Chain): Response {
        val request = chain.request()
        var response: Response? = null
        var retryCount = 0
        
        while (retryCount < maxRetries) {
            try {
                response = chain.proceed(request)
                if (response.isSuccessful) {
                    return response
                }
            } catch (e: IOException) {
                if (retryCount == maxRetries - 1) throw e
            }
            
            retryCount++
            Log.d("HTTP", "重试次数: $retryCount")
        }
        
        return response!!
    }
}
1.5 参数加密
class EncryptInterceptor : Interceptor {
    override fun intercept(chain: Chain): Response {
        val originalRequest = chain.request()
        
        // 获取原始参数
        val originalBody = originalRequest.body
        if (originalBody is FormBody) {
            val builder = FormBody.Builder()
            
            // 遍历并加密参数
            for (i in 0 until originalBody.size) {
                val name = originalBody.name(i)
                val value = originalBody.value(i)
                builder.add(name, EncryptUtils.encrypt(value))
            }
            
            // 添加时间戳和签名
            val timestamp = System.currentTimeMillis()
            builder.add("timestamp", timestamp.toString())
            builder.add("sign", generateSign(timestamp))
            
            // 构建新的请求
            val newRequest = originalRequest.newBuilder()
                .method(originalRequest.method, builder.build())
                .build()
                
            return chain.proceed(newRequest)
        }
        
        return chain.proceed(originalRequest)
    }
}

2. 实际应用示例

2.1 网络请求配置
class NetworkConfig {
    fun createOkHttpClient(): OkHttpClient {
        return OkHttpClient.Builder()
            .addInterceptor(HeaderInterceptor())
            .addInterceptor(LoggingInterceptor())
            .addInterceptor(CacheInterceptor())
            .addInterceptor(RetryInterceptor())
            .addInterceptor(EncryptInterceptor())
            // 缓存配置
            .cache(Cache(
                directory = File(context.cacheDir, "http_cache"),
                maxSize = 10L * 1024L * 1024L // 10 MB
            ))
            .connectTimeout(15, TimeUnit.SECONDS)
            .readTimeout(15, TimeUnit.SECONDS)
            .writeTimeout(15, TimeUnit.SECONDS)
            .build()
    }
}
2.2 错误处理拦截器
class ErrorHandlingInterceptor : Interceptor {
    override fun intercept(chain: Chain): Response {
        try {
            val response = chain.proceed(chain.request())
            
            // 处理业务错误码
            val responseBody = response.body?.string()
            val jsonObject = JSONObject(responseBody)
            
            when (jsonObject.optInt("code")) {
                401 -> { // 未授权
                    EventBus.getDefault().post(TokenExpiredEvent())
                    throw UnauthorizedException()
                }
                500 -> { // 服务器错误
                    throw ServerException(jsonObject.optString("message"))
                }
                200 -> { // 成功
                    return response.newBuilder()
                        .body(ResponseBody.create(
                            response.body?.contentType(),
                            responseBody
                        ))
                        .build()
                }
                else -> {
                    throw ApiException(
                        jsonObject.optInt("code"),
                        jsonObject.optString("message")
                    )
                }
            }
        } catch (e: Exception) {
            throw when (e) {
                is SocketTimeoutException -> TimeoutException()
                is UnknownHostException -> NetworkException()
                else -> e
            }
        }
    }
}
2.3 进度监听拦截器
class ProgressInterceptor(
    private val progressListener: ProgressListener
) : Interceptor {
    override fun intercept(chain: Chain): Response {
        val originalResponse = chain.proceed(chain.request())
        
        return originalResponse.newBuilder()
            .body(ProgressResponseBody(
                originalResponse.body!!,
                progressListener
            ))
            .build()
    }
}

class ProgressResponseBody(
    private val responseBody: ResponseBody,
    private val progressListener: ProgressListener
) : ResponseBody() {
    private var bufferedSource: BufferedSource? = null
    
    override fun contentType() = responseBody.contentType()
    
    override fun contentLength() = responseBody.contentLength()
    
    override fun source(): BufferedSource {
        if (bufferedSource == null) {
            bufferedSource = source(responseBody.source()).buffer()
        }
        return bufferedSource!!
    }
    
    private fun source(source: Source): Source {
        return object : ForwardingSource(source) {
            var totalBytesRead = 0L
            
            override fun read(sink: Buffer, byteCount: Long): Long {
                val bytesRead = super.read(sink, byteCount)
                totalBytesRead += if (bytesRead != -1L) bytesRead else 0
                
                progressListener.onProgress(
                    totalBytesRead,
                    responseBody.contentLength(),
                    bytesRead == -1L
                )
                return bytesRead
            }
        }
    }
}

3. 最佳实践

3.1 拦截器顺序
graph LR
    A[应用拦截器] --> B[Header拦截器]
    B --> C[日志拦截器]
    C --> D[缓存拦截器]
    D --> E[重试拦截器]
    E --> F[错误处理拦截器]
    F --> G[网络拦截器]
3.2 完整网络配置示例
@Module
class NetworkModule {
    @Provides
    @Singleton
    fun provideOkHttpClient(
        context: Context,
        tokenManager: TokenManager
    ): OkHttpClient {
        return OkHttpClient.Builder()
            // 应用拦截器
            .addInterceptor(HeaderInterceptor(tokenManager))
            .addInterceptor(LoggingInterceptor())
            .addInterceptor(CacheInterceptor(context))
            .addInterceptor(RetryInterceptor())
            .addInterceptor(ErrorHandlingInterceptor())
            .addInterceptor(EncryptInterceptor())
            
            // 网络拦截器
            .addNetworkInterceptor(StethoInterceptor()) // 调试工具
            
            // 其他配置
            .cache(Cache(
                directory = context.cacheDir,
                maxSize = 10 * 1024 * 1024L
            ))
            .connectTimeout(15, TimeUnit.SECONDS)
            .readTimeout(15, TimeUnit.SECONDS)
            .writeTimeout(15, TimeUnit.SECONDS)
            .build()
    }
}

通过合理使用这些拦截器,我们可以实现:

  1. 统一的网络请求处理
  2. 灵活的缓存策略
  3. 全局的错误处理
  4. 网络请求的监控和调试
  5. 安全性保护

这些拦截器的使用大大提高了网络请求的可维护性和扩展性。

4. Glide 缓存机制详解

4.1 缓存层级

  1. 内存缓存

    • Active Resources (活动资源)
    • Memory Cache (内存缓存)
  2. 磁盘缓存

    • Resource Cache (资源缓存)
    • Data Cache (原始数据缓存)

4.2 缓存流程

graph TD
    A[请求图片] --> B{检查Active Resources}
    B -->|命中| C[返回图片]
    B -->|未命中| D{检查Memory Cache}
    D -->|命中| E[移动到Active]
    D -->|未命中| F{检查Disk Cache}
    F -->|命中| G[加载到内存]
    F -->|未命中| H[网络请求]
    H --> I[保存到磁盘]
    I --> J[加载到内存]

4.3 核心实现代码

public class Engine {
    private final ActiveResources activeResources;
    private final MemoryCache memoryCache;
    private final DiskCache diskCache;
    
    public Resource<?> load(Key key) {
        // 1. 检查活动资源
        Resource<?> active = activeResources.get(key);
        if (active != null) {
            return active;
        }
        
        // 2. 检查内存缓存
        Resource<?> cached = memoryCache.remove(key);
        if (cached != null) {
            activeResources.activate(key, cached);
            return cached;
        }
        
        // 3. 检查磁盘缓存
        File cached = diskCache.get(key);
        if (cached != null) {
            Resource<?> resource = decode(cached);
            activeResources.activate(key, resource);
            return resource;
        }
        
        // 4. 从网络加载
        return null;
    }
}

5. ViewModel 原理深入解析

5.1 核心功能

  1. 数据持久化
    • 在配置更改时保持数据
    • 避免重复加载数据
  2. 生命周期管理
    • 自动清理资源
    • 避免内存泄漏
  3. 数据共享
    • Fragment 之间共享数据
    • Activity 与 Fragment 之间共享数据

5.2 实现原理流程图

graph TD
    A[Activity/Fragment创建] --> B[获取ViewModelStore]
    B --> C[创建ViewModel]
    C --> D[存储在ViewModelStore]
    E[配置变更] --> F[重建Activity]
    F --> G[恢复ViewModelStore]
    G --> H[获取已存在ViewModel]
    I[Activity真正销毁] --> J[清理ViewModelStore]

5.3 关键代码实现

class ViewModelStore {
    private val map = HashMap<String, ViewModel>()
    
    fun put(key: String, viewModel: ViewModel) {
        map[key] = viewModel
    }
    
    fun get(key: String): ViewModel? {
        return map[key]
    }
    
    fun clear() {
        for (vm in map.values) {
            vm.clear()
        }
        map.clear()
    }
}

class ViewModelProvider(
    private val store: ViewModelStore,
    private val factory: Factory
) {
    fun <T : ViewModel> get(modelClass: Class<T>): T {
        val key = modelClass.canonicalName!!
        val viewModel = store.get(key)
        
        if (modelClass.isInstance(viewModel)) {
            return viewModel as T
        }
        
        val newViewModel = factory.create(modelClass)
        store.put(key, newViewModel)
        return newViewModel
    }
}

6. ButterKnife 实现原理详解

6.1 工作流程

  1. 注解处理器
    • 编译时扫描注解
    • 生成绑定代码
  2. 代码生成
    • 生成 ViewBinding 类
    • 实现 findViewById 逻辑
  3. 运行时绑定
    • 反射创建 ViewBinding 实例
    • 完成视图绑定

6.2 详细流程图

graph TD
    A[编译时] --> B[扫描注解]
    B --> C[生成绑定类]
    D[运行时] --> E[创建绑定类实例]
    E --> F[执行findViewById]
    F --> G[完成视图绑定]

6.3 核心实现代码

public class Butterknife {
    public static void bind(Activity target) {
        View sourceView = target.getWindow().getDecorView();
        bind(target, sourceView);
    }
    
    private static void bind(Object target, View source) {
        Class<?> targetClass = target.getClass();
        Constructor<?> constructor;
        try {
            // 查找生成的绑定类
            Class<?> bindingClass = Class.forName(
                targetClass.getName() + "_ViewBinding");
            constructor = bindingClass.getConstructor(
                targetClass, View.class);
            // 创建绑定实例
            constructor.newInstance(target, source);
        } catch (Exception e) {
            throw new RuntimeException("Unable to bind views for " + 
                targetClass.getName(), e);
        }
    }
}

// 生成的绑定类示例
public class MainActivity_ViewBinding {
    private MainActivity target;
    
    public MainActivity_ViewBinding(MainActivity target, View source) {
        this.target = target;
        // 绑定视图
        target.textView = source.findViewById(R.id.text_view);
        target.button = source.findViewById(R.id.button);
    }
}

7. RxJava 背压原理详解

7.1 背压策略详解

  1. ERROR

    • 当队列满时抛出 MissingBackpressureException
    • 适用于无法容忍数据丢失的场景
  2. BUFFER

    • 无限缓存所有数据
    • 可能导致 OOM
    • 适用于数据量可控的场景
  3. DROP

    • 丢弃无法处理的数据
    • 适用于实时数据处理
  4. LATEST

    • 只保留最新数据
    • 适用于只关心最新状态的场景

7.2 实现原理流程

graph TD
    A[上游发送数据] --> B{检查策略}
    B -->|ERROR| C[抛出异常]
    B -->|BUFFER| D[加入缓存队列]
    B -->|DROP| E[丢弃数据]
    B -->|LATEST| F[更新最新数据]
    G[下游处理] --> H[request请求数据]
    H --> I[处理数据]

7.3 示例代码实现

public class RxJavaExample {
    public void backpressureExample() {
        // 创建被观察者
        Flowable.create(emitter -> {
            for (int i = 0; i < 1000000; i++) {
                if (emitter.isCancelled()) {
                    return;
                }
                emitter.onNext(i);
            }
            emitter.onComplete();
        }, BackpressureStrategy.DROP)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Subscriber<Integer>() {
            private Subscription subscription;
            
            @Override
            public void onSubscribe(Subscription s) {
                this.subscription = s;
                // 请求处理的数据量
                s.request(Long.MAX_VALUE);
            }
            
            @Override
            public void onNext(Integer value) {
                // 处理数据
                System.out.println("Received: " + value);
            }
            
            @Override
            public void onError(Throwable t) {
                t.printStackTrace();
            }
            
            @Override
            public void onComplete() {
                System.out.println("Completed");
            }
        });
    }
}

7.4 背压实现机制

  1. 请求量控制

    • 通过 request(n) 方法控制数据请求量
    • 实现了 Publisher-Subscriber 模式
  2. 数据缓存

    • 使用 Queue 实现数据缓存
    • 根据不同策略处理溢出数据
  3. 线程调度

    • subscribeOn() 控制发送线程
    • observeOn() 控制接收线程

这些框架的深入理解对于Android开发至关重要,它们都采用了不同的设计模式和实现机制来解决特定的问题。理解这些原理不仅有助于更好地使用这些框架,也能帮助我们在实际开发中做出更好的技术选择。