我的新书《Android App开发入门与实战》已于2020年8月由人民邮电出版社出版,欢迎购买。点击进入详情
Android面试文章系列合集,欢迎阅读和收藏
Least Recently Used,也就是最近最少使用算法。当缓存空间满了的时候,将最近最少使用的数据从缓存空间中删除以增加可用的缓存空间来缓存新内容。
1. 双向链表LinkedHashMap
//第一个参数是初始容量
//第二个参数是填装因子,或叫加载因子
//第三个参数是排序模式,true表示在访问的时候进行排序,否则只在插入的时候才排序。
this.map = new LinkedHashMap
2. 头结点header
LinkedHashMap初始化会有一个头结点header,add的时候会在header后面依次添加,也就是说header后面是很久没有使用的元素。get的时候会先调用remove方法把自己删除,然后调用add方法放到链表的末尾;
3. 主要方法
eldest方法获取最近最少使用元素;trimToSize检查缓存大小和设置最大缓存;
其实java线程池的实现原理很简单,说白了就是一个线程集合workerSet和一个阻塞队列workQueue。当用户向线程池提交一个任务(也就是线程)时,线程池会先将任务放入workQueue中。workerSet中的线程会不断的从workQueue中获取线程然后执行。当workQueue中没有任务的时候,worker就会阻塞,直到队列中有任务了就取出来继续执行。
AsyncTask的实现原理 = 线程池 + Handler;
线程池用于线程调度、复用 & 执行任务;Handler 用于异步通信;
其内部封装了2个线程池 + 1个Handler,具体介绍如下:
使用发布/订阅事件总线框架,基于观察者模式,将事件的接收者和发送者分开,简化了组件之间的通信,使用简单、效率高、体积小。
使用APT:Annotation Processing Tools。
LiveData的特点:
1)采用观察者模式,类比RxJava,数据发生改变,可以自动回调(比如更新UI)。
2)不需要手动处理生命周期,不会因为Activity的销毁重建而丢失数据。
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
//把wrapper 与Activity/Fragment的生命周期,建立关系,
//当UI的生命周期发生变化的时候,就会去回调wrapper中的 onStateChanged
owner.getLifecycle().addObserver(wrapper);
3)不会出现内存泄漏。
4)不需要手动取消订阅,Activity在非活跃状态下(pause、stop、destroy之后)不会收到数据更新信息。
在一个Activity执行完onDestroy()之后,将它放入WeakReference中,然后将这个WeakReference类型的Activity对象与ReferenceQueque关联。这时再从ReferenceQueque中查看是否有没有该对象,如果没有,执行gc,再次查看,还是没有的话则判断发生内存泄露了。最后用HAHA这个开源库去分析dump之后的heap内存。
Reference引用的对象被回收时,Reference 对象将被添加到 ReferenceQueue中,前提是构造 Reference 时,参数中有 ReferenceQueue。
Object obj = new Object();
ReferenceQueue queue = new ReferenceQueue<>();
WeakedReference r = new WeakedReference(ojb, queue);
如果 obj 对象被回收了,那么 queue 将添加 r,那么我们可以查找队列,如果有r,则证明 obj 对象被回收了,监控完成。
1:编写Annotation,通过field.getAnnotation反射方式找到Annotation里面的值;
2:通过Annotation Processing Tool:
①.编译期间通过反射扫描Java代码中所有的ButterKnife注解@Bind、@OnClick、@OnItemClicked等
②.当它发现一个类中含有任何一个注解时,ButterKnifeProcessor会帮你生成一个Java类,名字类似$$ViewBinder,这个新生成的类实现了ViewBinder接口
③.这个ViewBinder类中包含了所有对应的代码,比如@Bind注解对应findViewById(), @OnClick对应了view.setOnClickListener()等等
④.最后当Activity启动ButterKnife.bind(this)执行时,ButterKnife会去加载对应的ViewBinder类调用它们的bind()方法
有容乃大,可扩展性强,底层网络请求集成了Okhttp,异步处理可集成RxJava,内容解析可集成Gson,Jackson等。
全面支持Restful请求,并且通过注解的方式,支持链式调用,使用简洁方便。
精妙的源码设计模式,内部层次分工明确,解耦性强。
Retrofit就是一个定义接口然后对OKHttp的一个封装,事实上网络请求还是在OKHttp里进行。利用注解和参数利用动态代理来替使用者生成网络请求的Request和Call,来完成网络请求的一个框架。
1、构建者模式
建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
使用Builder内部类,通过链式调用来完成初始化。让每一个配置变得清晰。
2、工厂方法
定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。CallAdapter的get方法使用工厂模式实现了不同平台的调用。例如RxJavaCallAdapter的get就返回了Observer。
3、外观模式
外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性。
这种模式涉及到一个单一的类,该类提供了客户端请求的简化方法和对现有系统类方法的委托调用。
Retrofit里面封装了很多类,其实使用者并不需要知道具体是什么,只要通过Retrofit来和他们进行交互就行了。
4、策略模式
在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
其实就是将我们的业务逻辑分成不同的策略,使用时可以进行替换即可。
CallAdapter其实就是一个策略,具体实现的策略的方法由子类实现。例如RxJavaCallAdapter就是一种策略,要替换成别的Adapter也可以,这就是策略模式。
5、适配器模式
适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。
适配器模式可以说是一种中间件,将不同的平台上的网络请求封装成一类,OKHttpCall就是这样做的。
6、观察者模式
当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。
CallBack作为观察者观察OKHttpCall,根据执行的不同做出反应。
链式编程+接口互调
APT
,ARouter会通过它自己存储的路由表找到路由地址对应的Activity.class(activity.class = map.get(path)),然后new Intent(context, activity.Class),当调用ARouter的withString()方法它的内部会调用intent.putExtra(String name, String value),调用navigation()方法,它的内部会调用startActivity(intent)进行跳转,这样便可以实现两个相互没有依赖的module顺利的启动对方的Activity了。
欢迎关注我的技术公众号:国民程序员,我们的目标:输出干货
- 每天分享原创技术文章
- 海量免费技术资料和视频学习资源
- 分享赚钱门道,带领程序员走向财务自由