伴鱼面试记录
1、给两个View,返回最近的公共父View
2、ViewModel在Activity异常销毁如何恢复数据
https://developer.android.google.cn/topic/libraries/architecture/viewmodel-savedstate?hl=zh_cn
3、LiveData原理,在子线程里能不能收到消息,快速postValue
setValue()方法只能在主线程调用,内部有线程判断代码,非主线程抛异常
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* Sets the value. If there are active observers, the value will be dispatched to them.
* <p>
* This method must be called from the main thread. If you need set a value from a background
* thread, you can use {@link #postValue(Object)}
*
* @param value The new value
*/
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
postValue()在子线程调用,内部会切换到主线程发送信息。如果在主线程消耗一个post的value之前多次post信息,只有最后一次post的信息会被分发
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* Posts a task to a main thread to set the given value. So if you have a following code
* executed in the main thread:
* <pre class="prettyprint">
* liveData.postValue("a");
* liveData.setValue("b");
* </pre>
* The value "b" would be set at first and later the main thread would override it with
* the value "a".
* <p>
* If you called this method multiple times before a main thread executed a posted task, only
* the last value would be dispatched.
*
* @param value The new value
*/
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
在主线程调用一下代码
1
2
3
4
liveData.postValue("a");
liveData.setValue("b");
//The value "b" would be set at first and later the main thread would override it with
//the value "a".
b会先被接收,然后才会接收a
LiveData 的 observe方法里第一句代码就是坚持当前线程是否是主线程,如果在子线程调用则会抛出一个异常信息,所以不能子线程接收消息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
owner.getLifecycle().addObserver(wrapper);
}
4、谈谈MVC、MVP、MVVM的区别
https://blog.csdn.net/iteye_13407/article/details/109419670
MVC和MVP的关系
在这两个模式中,Controller和Presenter都负责业务逻辑的处理,Model则负责提供数据,最终View负责显示这些数据。它们最大的区别在于:在MVP模式中,View并不直接使用Model,它们之间的通信是通过Presenter来进行的。而在MVC模式中,View会直接从Model中读取数据,而不是通过Controller。MVC模式和MVP模式的架构图如下所示。
MVP和MVVM的关系
MVVM模式将Presenter改名为ViewModel,在整体上与MVP模式保持一致。它们唯一的区别在于,MVVM模式采用了双向绑定机制。因此,View的变动,会自动反映在ViewModel上,反之亦然。这样,开发者就不用手动侦听事件并触发相应的View的更新了,因为基于MVVM模式的应用框架已经帮我们做好了这方面的工作。MVP模式和MVVM模式的架构图如下所示。
5、做了哪些性能优化,怎么做的
响应速度,流畅度,内存,稳定性
https://zhuanlan.zhihu.com/p/30691789
启动速度优化,内存泄漏,ANR(https://www.cnblogs.com/huansky/p/13944132.html),
6、怎么优化的包体积大小
资源压缩,一些非必要信息不打包近apk里,通过网络下载使用,减少so数量
事实上安装包中无非就是Dex、Resource、Assets、Library以及签名信息这五部分
首先从代码上下手,对于大部分应用来说,Dex都是包体积中的大头。在不砍功能的前提下,我们看看有哪些方法可以减少这部分空间。
1、ProGuard
“十个ProGuard配置九个坑”,特别是各种第三方SDK。我们需要仔细检查最终合并的ProGuard配置文件,是不是存在过度 keep的现象。