美文网首页
Android 第三方框架面试题

Android 第三方框架面试题

作者: 星邪Ara | 来源:发表于2022-04-08 09:14 被阅读0次

    1.1 谈一谈LeakCanray的工作原理?

    LeakCanary 主要利用了弱引用的对象,当 GC 回收了这个对象后,会被放进 ReferenceQueue 中;
    在页面消失,也就是 activity.onDestroy 的时候, 判断利用idleHandler发送一条延时消息,5秒之后,分析 ReferenceQueue 中存在的引用,如果当前 activity 仍在引用队列中,则认为可能存在泄漏,再利用系统类 VMDebug 提供的方法,获取内存快照,找出 GC roots 的最短强引用路径,并确定是否是泄露, 如果泄漏,建立导致泄露的引用链;
    System.runFinalization(); // 强制调用已经失去引用的对象的 finalize 方法

        Retryable.Result ensureGone(final KeyedWeakReference reference, final long watchStartNanoTime) {
            // 1.. 从 retainedKeys 移除掉已经被会回收的弱引用
            removeWeaklyReachableReferences();
            // 3.. 若当前引用不在 retainedKeys, 说明不存在内存泄漏
            if (gone(reference)) {
                return DONE;
            }
            // 4.. 触发一次gc
            gcTrigger.runGc();
            // 5.. 再次从 retainedKeys 移除掉已经被会回收的弱引用
            removeWeaklyReachableReferences();
            if (!gone(reference)) {
                // 存在内存泄漏
                long startDumpHeap = System.nanoTime();
                long gcDurationMs = NANOSECONDS.toMillis(startDumpHeap - gcStartNanoTime);
                // 获得内存快照
                File heapDumpFile = heapDumper.dumpHeap();
                if (heapDumpFile == RETRY_LATER) {
                    // Could not dump the heap.
                    return RETRY;
                }
                long heapDumpDurationMs = NANOSECONDS.toMillis(System.nanoTime() - startDumpHeap);
                HeapDump heapDump = heapDumpBuilder.heapDumpFile(heapDumpFile).referenceKey(reference.key)
                        .referenceName(reference.name)
                        .watchDurationMs(watchDurationMs)
                        .gcDurationMs(gcDurationMs)
                        .heapDumpDurationMs(heapDumpDurationMs)
                        .build();
                heapdumpListener.analyze(heapDump);
            }
            return DONE;
        }
    

    1.2 谈一谈EventBus的原理?

    1、 register方法将对象实例用软引用包裹,保存到一个map缓存集合中
    2、post方法 传入一个对象进去,然后遍历map里面多有的对象,找到所有的带有 @subscribe注解的并且方法参数与post的对象是同一类型的Method, 并通过反射执行Method
    3、Subscribe线程调度 执行method方法的时候会去获取注解上标记得线程,然后切换到指定线程
    4、unregister取消订阅 从第一步中的缓存map中移除对应注册的对象实例

    1.3 谈谈网络请求中的拦截器(Interceptor)?

    系统自带的拦截器:
    1,重试和重定向
    2,请求头+响应头处理
    3,缓存
    4,dns + 三次握手
    5,CallServer,读写数据流常用的自定义拦截器:
    1,日志拦截器
    2,自定义缓存规则拦截器
    3,重试机制等等

    1.4 谈一谈Glide的缓存机制?

    • Glide的缓存机制,主要分为2种缓存,一种是内存缓存,一种是磁盘缓存。
    • 使用内存缓存的原因是:防止应用重复将图片读入到内存,造成内存资源浪费。
    • 使用磁盘缓存的原因是:防止应用重复的从网络或者其他地方下载和读取数据。

    具体来讲,缓存分为加载和存储:

    1. 当加载一张图片的时候,获取顺序:Lru算法缓存-》弱引用缓存-》磁盘缓存(如果设置了的话)。
      当想要加载某张图片时,先去LruCache中寻找图片,如果LruCache中有,则直接取出来使用,并将该图片放入WeakReference中,如果LruCache中没有,则去WeakReference中寻找,如果WeakReference中有,则从WeakReference中取出图片使用,如果WeakReference中也没有图片,则从磁盘缓存/网络中加载图片。
    2. 将缓存图片的时候,写入顺序:弱引用缓存-》Lru算法缓存-》磁盘缓存中。
      当图片不存在的时候,先从网络下载图片,然后将图片存入弱引用中,glide会采用一个acquired(int)变量用来记录图片被引用的次数, 当acquired变量大于0的时候,说明图片正在使用中,也就是将图片放到弱引用缓存当中;如果acquired变量等于0了,说明图片已经不再被使用了,那么此时会调用方法来释放资源,首先会将缓存图片从弱引用中移除,然后再将它put到LruResourceCache当中。
      这样也就实现了正在使用中的图片使用弱引用来进行缓存,不在使用中的图片使用LruCache来进行缓存的功能。

    另:从Glide4.x开始,读取图片的顺序有所改变:弱引用缓存-》Lru算法缓存-》磁盘缓存

    1.5 ViewModel的出现是为了解决什么问题?并简要说说它的内部原理?

    viewModel出现为了解决什么问题?

    看下viewModel的优点就知道了:

    1. 对于activity/fragment的销毁重建,它们内部的数据也会销毁,通常可以onSaveInstanceState()方法保存,通过onCreate的bundle中重新获取,但是大量的数据不合适,而vm会再页面销毁时自动保存并在页面加载时恢复。
    2. 对于异步获取数据,大多时候会在页面destroyed时回收资源,随着数据和资源的复杂,会造成页面中的回收操作越来越多,页面处理ui的同时还要处理资源和数据的管理。而引入vm后可以把资源和数据的处理统一放在vm里,页面回收时系统也会回收vm。加上databinding的支持后,会大幅度分担ui层的负担。

    内部原理:
    vm内部很简单,只有一个onClean方法。
    vm的创建一般是这样ViewModelProviders.of(getActivity()).get(UserModel.class);

    1. ViewModelProviders.of(getActivity())
      在of方法中通过传入的activity获取构造一个HolderFragment,HolderFragment内有个ViewModelStore,而ViewModelStore内部的一个hashMap保存着系统构造的vm对象,HolderFragment可以感知到传入页面的生命周期(跟glide的做法差不多),HolderFragment构造方法中设置了setRetainInstance(true),所以页面销毁后vm可以正常保存。
    2. get(UserModel.class);
      获取ViewModelStore.hashMap中的vm,第一次为空会走创建逻辑,如果我们没有提供vm创建的Factory,使用我们传入的activity获取application创建AndroidViewModelFactory,内部使用反射创建我们需要的vm对象。

    1.6 请说说依赖注入框架ButterKnife的实现原理?

    1. 通过注解器在编译期间生成一个XX_ViewBinding.java文件(XX可以是activity,fragment,adapter,dialog),这个文件
      这么生成的?
      注解器里会添加需要类型的注解;
      查找XX类中的特定类型注解,如果有,拼接成字符串,创建并写到XX_ViewBinding.java文件中
    2. XX_ViewBinding.java会持有XX的引用,如果是初始化控件,通过xx.findViewById实现如果是设置监听,类似xx.setOnClickListener实现
    3. XX类中初始化XX_ViewBinding对象,这样打通了整个流程

    1.7 谈一谈RxJava背压原理?

    总共分为4种策略

    1. BackpressureStrategy.ERROR:若上游发送事件速度超出下游处理事件能力,且事件缓存池已满,则抛出异常//阻塞时队列
    2. BackpressureStrategy.BUFFER:若上游发送事件速度超出下游处理能力,则把事件存储起来等待下游处理
    3. BackpressureStrategy.DROP:若上游发送事件速度超出下游处理能力,事件缓存池满了后将之后发送的事件丢弃
    4. BackpressureStrategy.LATEST:若上有发送时间速度超出下游处理能力,则只存储最新的128个事件

    相关文章

      网友评论

          本文标题:Android 第三方框架面试题

          本文链接:https://www.haomeiwen.com/subject/vvsnjrtx.html