if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
//将LifecycleBoundObserver和activity或者fragment的lifeCycle相关联
owner.getLifecycle().addObserver(wrapper);
}
**装饰器LifecycleBoundObserver**
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
@NonNull
final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
//数据发生变化,如果activity或者fragment已经销毁,就解除订阅,避免了内存泄露
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
…
public interface Observer<T> {
/**
* Called when the data is changed.
* @param t The new data
*/
void onChanged(@Nullable T t);
}
```
第一个参数可以直接传activity,如果activity已经销毁直接return,否则owner.getLifecycle().addObserver(wrapper);,LiveData调用postValue或者setValue方法就会回调Observer的onChanged方法
* LiveData的observe方法接收activity的getLifeCycle(可感知activity生命周期)和Observer(添加一个观察者到LiveData的内部集合里)。
* LiveData的setValue方法将数据通知到所有观察者,如果actiivty已经销毁则之间解除订阅。否则所有观察者的onChange(T t)方法会被执行
这数据处理逻辑放在ViewModel里,需要更新UI时给观察者发送通知即可,同时不用关心内存泄漏
4.ViewModel
===========
* 处理逻辑
* 存储数据,ViewModel储存的数据activity旋转后数据不会丢失
* 数据共享
![Android面试主题整理合集(二)](https://img-blog.csdnimg.cn/img_convert/cce5fa970d0dc169011ec6914f37d750.png)
5.Flowable和Observable
=====================
RxJava1中使用Observable和Observer建立起订阅关系,但会产生背压问题。Rxjava2使用Flowable和Subscriber替换RaJava1的Observable和Observer。Flowable是在Observable的基础上优化后的产物,Observable能解决的问题Flowable也都能解决。但是并不代表Flowable可以完全取代Observable,Flowable运行效率要比Observable慢得多。?**只有在需要处理背压问题时,才需要使用Flowable**
* 当上下游在不同的线程中,通过Observable发射,处理,响应数据流时,如果上游发射数据的速度快于下游接收处理数据的速度,这样对于那些没来得及处理的数据就会造成积压,这些数据既不会丢失,也不会被垃圾回收机制回收,而是存放在一个异步缓存池中,如果缓存池中的数据一直得不到处理,越积越多,最后就会造成内存溢出,这便是响应式编程中的背压(backpressure)问题
* 如果能够确定:
1. 上下游运行在同一个线程中
2. 上下游工作在不同的线程中,但是下游处理数据的速度不慢于上游发射数据的速度
3. 上下游工作在不同的线程中,但是数据流中只有一条数, 则不会产生背压问题,就没有必要使用Flowable,以免影响性能。
6.app优化
=======
* 内存优化:使用leakcanary抓取内存泄露,或者使用android studio抓取内存信息,通过Profiler分析内存泄露情况
* 体积优化 不复杂图片使用svg代替png。换肤时使用着色器,可减少图片资源 build文件配置 保留指定语言 保留指定so库架构 开启混淆压缩
![Android面试主题整理合集(二)](https://img-blog.csdnimg.cn/img_convert/9840f3ab7d028537b6ed690a8a83418c.png)
7.Rxjava中关于Disposable
=====================
Rxjava容易遭层内存泄漏。在订阅了事件后没有及时取阅,导致在activity或者fragment销毁后仍然占用着内存,无法释放。而disposable,可以用来取消订阅
8.Glide
=======
* Glide的缓存 Glide缓存机制大致分为三层:Lru算法缓存、弱引用缓存、磁盘缓存 读取的顺序是:Lru算法缓存、弱引用缓存、磁盘缓存(据说glide最新版改了,先从弱引用中取,没有的话再从Lru中取,再放进弱引用中)
* Glide.with(this) .load("http://www.baidu.com/img/bdlogo.png") .into(imageView); with()方法是对RequestManager进行配置 public static RequestManager with(FragmentActivity activity) { return getRetriever(activity).get(activity); } 复制代码 load()方法是对RequestBuilder进行配置 public RequestBuilder<Drawable> load(@Nullable Object model) { return asDrawable().load(model); } 复制代码 into()方法是通过线程池给imageView进行图片的加载设置
* 占用内存较小 默认使用RGB\_565格式
* 支持gif
* 与Activity生命周期绑定,不会出现内存泄露 Glide绑定Activity时,生成一个无UI的Fragment 将无UI的Fragment的LifeCycle传入到RequestManager中 在RequestManager的构造方法中,将RequestManager存入到之前传入的Fragment的LifeCycle,在回调LifeCycle时会回调到Glide的相应方法
9.Android串口
===========
通过串口编程可以让Android应用和外设进行通信,通过谷歌提供的一个库来开发。
通过那个库,打开串口。获取输入输出流,就可以利用串口接收数据和发送数据了
核心参数:
```
path:为串口的物理地址,一般硬件工程师都会告诉你的例如ttyS0、ttyS1等,或者通过SerialPortFinder类去寻找得到可用的串口地址。
baudrate:波特率,与外接设备一致
flags:设置为0,原因较复杂,见文章最底下
```
10.断点续传实现
=========
* 在本地下载过程中要使用数据库实时存储到底存储到文件的哪个位置了
* 下次继续传递时,才能通过HTTP的GET请求中的setRequestProperty("Range","bytes=startIndex-endIndex");方法可以告诉服务器,数据从哪里开始,到哪里结束
* 同时在本地的文件写入时,RandomAccessFile的seek()方法也支持在文件中的任意位置进行写入操作
* 最后通过广播或事件总线机制将子线程的进度告诉Activity的进度条。关于断线续传的HTTP状态码是206
11.RxJava 变换操作符 map flatMap concatMap zip buffer
================================================
* map:【数据类型转换】将被观察者发送的事件转换为另一种类型的事件。**适用于一对一转换**
* flatMap:【化解循环嵌套和接口嵌套】将被观察者发送的事件序列进行拆分 & 转换 后合并成一个新的事件序列,最后再进行发送。**应用场景:一个接口调用时依赖另一个接口的返回值,适用于一对多**
* concatMap:【有序】与 flatMap 的 区别在于,拆分 & 重新合并生成的事件序列 的顺序与被观察者旧序列生产的顺序一致。
* zip:?**应用场景:两个接口的数据相互结合才能显示UI**
## 文末
那么对于想坚持程序员这行的真的就一点希望都没有吗?
其实不然,在互联网的大浪淘沙之下,留下的永远是最优秀的,我们考虑的不是哪个行业差哪个行业难,就逃避掉这些,无论哪个行业,都会有他的问题,但是无论哪个行业都会有站在最顶端的那群人。我们要做的就是努力提升自己,让自己站在最顶端,学历不够那就去读,知识不够那就去学。人之所以为人,不就是有解决问题的能力吗?挡住自己的由于只有自己。
**Android希望=技能+面试**
**[CodeChina开源项目地址:https://codechina.csdn.net/m0_60958482/android_p7](https://codechina.csdn.net/m0_60958482/android_p7)**
* **技能**
![](https://img-blog.csdnimg.cn/img_convert/c876cceaf7cd586bacb0ff7204125d5a.png)
* **面试技巧+面试题**
那就去读,知识不够那就去学。人之所以为人,不就是有解决问题的能力吗?挡住自己的由于只有自己。
**Android希望=技能+面试**
**[CodeChina开源项目地址:https://codechina.csdn.net/m0_60958482/android_p7](https://codechina.csdn.net/m0_60958482/android_p7)**
* **技能**
[外链图片转存中...(img-Yqd1opQg-1630395682562)]
* **面试技巧+面试题**
![](https://img-blog.csdnimg.cn/img_convert/3655b2bf5f0eb3513638f3b560dd6a01.png)
|