文章

伴鱼面试记录

伴鱼面试记录

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模式的架构图如下所示。

mvc和mvp

MVP和MVVM的关系

MVVM模式将Presenter改名为ViewModel,在整体上与MVP模式保持一致。它们唯一的区别在于,MVVM模式采用了双向绑定机制。因此,View的变动,会自动反映在ViewModel上,反之亦然。这样,开发者就不用手动侦听事件并触发相应的View的更新了,因为基于MVVM模式的应用框架已经帮我们做好了这方面的工作。MVP模式和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的现象。

2、去掉Debug信息或者去掉行号

本文由作者按照 CC BY 4.0 进行授权