写点什么

Android 面试总结 - LiveData,2021 大厂 Android 知识点总结

用户头像
Android架构
关注
发布于: 2021 年 11 月 05 日

// 很关键的 mVersion ,在这里进行 + 1 操作


mVersion++;


// 将新值赋值给属性 mData


mData = value;


// 分发值 (后面再看它具体实现)


dispatchingValue(null);


}


关键哟:setValue 必须在主线程中调用


/**


  • 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".

  • 首先设置值“b”,然后主线程将用值“a”覆盖它。(等我们看完了 postValue 具体怎么做的,这个官方小示例就能明白了)

  • <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


mPendingData = value;


}


// 当 mPendingData == NOT_SET 时,才会往下走


if (!postTask) {


return;


}


ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);


}


ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);?看似是把 mPostValueRunnable 这 Runnable 对象发送到主线程?


private final Runnable mPostValueRunnable = new Runnable() {


@SuppressWarnings("unchecked")


@Override


public void run() {


Object newValue;


synchronized (mDataLock) {


// 将刚赋值新值的 mPendingData 赋值给对象 newValue


newValue = mPendingData;


// 将 mPendingData 重置为 NOT_SET


// 回头看看 postValue 会明白为啥要这么做


mPendingData = NOT_SET;


}


// 嘶 ~ 在这儿调用了 setValue,


setValue((T) newValue);


}


};


这时候看出来 postValue 最终还是调用了 setValue 再看下 postToMainThread


@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)


public class ArchTaskExecutor extends TaskExecutor {


@NonNull


private TaskExecutor mDelegate;


private ArchTaskExecutor() {


mDefaultTaskExecutor = new DefaultTaskExecutor();


mDelegate = mDefaultTaskExecutor;


}


@Override


public void postToMainThread(Runnable runnable) {


mDelegate.postToMainThread(runnable);


}


}


由 DefaultTaskExecutor 对象调用的 postToMainThread


@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)


public class DefaultTaskExecutor extends TaskExecutor {


@Nullable


private volatile Handler mMainHandler;


@Override


public void postToMainThread(Runnable runnable) {


if (mMainHandler == null) {


synchronized (mLock) {


if (mMainHandler == null) {


// MainLooper 主线程的 Looper 呢


mMainHandler = createAsync(Looper.getMainLooper());


}


}


}


//noinspection ConstantConditions


mMainHandler.post(runnable);


}


private static Handler createAsync(@NonNull Looper looper) {


if (Build.VERSION.SDK_INT >= 28) {


return Handler.createAsync(looper);


}


if (Build.VERSION.SDK_INT >= 16) {


try {


return Handler.class.getDeclaredConstructor(Looper.class, Handler.Callback.class,


boolean.class)


.newInstance(looper, null, true);


} catch (IllegalAccessException ignored) {


} catch (InstantiationException ignored) {


} catch (NoSuchMethodException ignored) {


} catch (InvocationTargetException e) {


return new Handler(looper);


}


}


return new Handler(looper);


}


}


最终是通过 Handler 的 post ~~ 太熟悉了。


看代码得知 Handler 的 Looper 是 MainLooper


So LiveData#postValue 最终使用主线程将新 value 分发给观察者。意味着我们可以在任何线程调用 postValue,而不用担心线程问题。因为 LiveData 内部做好了线程转换。


第二个问题:2.?setValue 和 postValue 有什么区别


简单来说:setValue 只能在主线程使用,而 postValue 不限制线程。


由上知道了:setValue 调用了 dispatchingValue, postValue 调用了 setValue 所以最终也是调用 dispatchingValue


void dispatchingValue(@Nullable ObserverWrapper initiator) {


// mDispatchingValue 是一个标记,为 true 表示正在分发 value,


if (mDispatchingValue) {


mDispatchInvalidated = true;


return;


}


mDispatchingValue = true;


do {


mDispatchInvalidated = false;


if (initiator != null) {


// 1.


considerNotify(initiator);


initiator = null;


} else {


// 2.


for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =


mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {


considerNotify(iterator.next().getValue());


if (mDispatchInvalidated) {


break;


}


}


}


} while (mDispatchInvalidated);


mDispatchingValue = false;


}


从 setValue 中看到调用 dispatchingValue 时传入的参数是 null 所以我们先看注释第 2 点的情况,使用迭代器获取 ObserverWrapper 对象传到 considerNotify 方法。


private void considerNotify(ObserverWrapper observer) {


// 观察者处于不活跃状态时,不往下走了


if (!observer.mActive) {


return;


}


// Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.


//


// we still first check observer.active to keep it as the entrance for events. So even if


// the observer moved to an active state, if we've not re


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


ceived that event, we better not


// notify for a more predictable notification order.


// 分发的时候判断当前观察者是否不活跃了


if (!observer.shouldBeActive()) {


// 更改 ObserverWrapper 的 mActive 为 false 非活跃状态


observer.activeStateChanged(false);


return;


}


// 版本号来了~~!


if (observer.mLastVersion >= mVersion) {


return;


}


// 同步版本号,


observer.mLastVersion = mVersion;


// 这里终于调用了我们 LiveData.observe 方法传入的 Observer 对象的 onChanged 方法。


// 终于形成了闭环


observer.mObserver.onChanged((T) mData);


}


来看看版本号 LiveData#mVersion


static final int START_VERSION = -1;


private int mVersion;


// 当创建 LiveData 时传入了初始值,则 mVersion 的版本为 -1 + 1 也就是 0


public LiveData(T value) {


mData = value;


mVersion = START_VERSION + 1;


}


// 大多数我们会使用无参构造,这时候 mVersion 是 START_VERSION -1


/**


  • Creates a LiveData with no value assigned to it.


*/


public LiveData() {


mData = NOT_SET;


mVersion = START_VERSION;


}


那 mVersion 的值是什么时候更改的呢?


其实在刚刚分析 setValue 时就 ++ 了,回顾一下


protected void setValue(T value) {


assertMainThread("setValue");


mVersion++;


mData = value;


dispatchingValue(null);


}


而且我们也知道 postValue 最后会调用 setValue,所以 mVersion 值更改的只是就到这儿了。 这时候是不是可以分析一下第三个问题


3.?设置相同的值,订阅的观察者们会收到同样的值吗?在分发值的过程中没有判断过新值是否等于老值的代码出现,只出现了一个判断 version,通过 demo 尝试也会发现,会收到同样的值的哟。


以下资料全部免费赠送,需要的可以点击这里:[https://github.com/hunanmaniu/AndroidNotes](


)


架构师筑基必备技能




目前 Android APP 开发主流语言就是 Java 语言,Java 语言最大的特性就是提高了软件的交互可能性,可以说安卓手机几乎所有应用程序都是利用 Java 语言来进行编写的。


JAVA 知识要点:


1、 Java 序列化、泛型与反射


2、虚拟机底层原理


3、Android 内存原理


4、 Java 高级并发原理详解


5、 编译时技术掌握与实战


6、JDK 高级动态代理


7、高级数据结构与算法


8、 Java IO 操作


9、


。。。。



Android R FrameWork 源码与 UI




在 Android 中,Framework 泛指系统架构层。Framework 的中文意思是“框架”,在软件开发中通常指开发框架,在一个系统中处于内核层之上,为顶层应用提供接口,被设计用来帮助开发者快速开发顶层应用,而不必关心系统内核运行机制,通常 Framework 都会隐藏 main 函数等应用程序必须的组件,开发人员只需把精力放在功能代码的实现上。说简单点,Framework 具体的工作也就是为 android 应用开发的开发人员提供了一系列的服务和 API 的接口。


UI 其实并不是单纯指用户看到的效果。因为在 Android 开发中,每个控件背后都有一套深层次的体系在支撑,自然而然,会 UI 不单纯指的是会自定义控件,我们还应该知道自定义控件背后的执行流程,包括从 Activity 的创建,XML 的解析,到每个控件的测量、布局、绘制。当然在中间还夹杂着比如动画、事件分发机制、嵌套滑动机制等知识点。还有谷歌提供的一些 UI 框架也使我们要掌握的对象,比如 Jetpack 组件库、Material Design 等。


知识要点:


1、 FrameWork 源码解析(SDK 30)


2、Android 常用组件深入解析


3、JetPack 全家桶


4、Android R 新特性解析


。。。。。



大厂内部 APP 调优方案




性能优化是一个项目必须要经历的过程,你的应用好与坏都是在用户使用的过程中反映出来的,如果性能优化没有做好,对于你的应用来说影响是非常大的。尤其是现在的 Android 市场竞争非常激烈,如果你的应用体验没有竞品的好,那么用户流失是必然的。


性能优化不是一件简单的事情,每个应用的性能好与坏无法由一个人来决定,因为性能优化的维度有太多了,从我们项目的整体架构,到我们代码的每一个细节,再到应用使用环境的测试,只有步步为营,才能做好一个项目的优化。大部分开发者把性能优化指向与不闪退就行,但是实际上性能优化包含了很多方面,比如从简单的启动优化、 UI 优化、 卡顿优化、 崩溃优化、 安全性优化,到深层次的弱网优化、 大图加载优化、 储存优化、 高效传输优化、 极限瘦身优化,再到实际开发过程中的 OOM 问题原理解析、 ANR 问题解析、 Crash 监控方案。要想把这些优化流程做好,我们不仅从项目架构、代码规范等方面入手,还用学会利用第三方的检测工具来检测项目性能,最主要是,我们需要一套完整的性能优化方案,这正是我们所缺少的,所以我们必须要把缺少的补上, 打造一套真正的完整的性能优化体系,把性能优化流程化,常态化。


1、 APP 基础优化


2、APP 深度优化


3、开发焦点问题优化


4、编程效率优化


5、项目实战


抖音在 APK 包大小资源优化的实践


优酷响应式布局技术全解析


网络优化


手机淘宝双十一性能优化项目揭秘


高德 APP 全链路源码依赖分析


彻底干掉 OOM 的实战经验分享


微信 Android 终端内存优化实践



对标腾讯 T3.3 架构师




Android 框架体系架构(高级 UI+FrameWork 源码) 这块知识是现今使用者最多的,我们称之 Android2013~2016 年的技术。


Android 开发者也往往因为网上 Copy 代码习惯了而导致对这块经常“使用”的代码熟悉而又陌生:熟悉的是几乎天天在和它们打交道, 天天在复制这些代码 ;陌生的是虽然天天和这些代码打交道,但是并没有深入研究过这些代码的原理,代码深处的内涵。


知识要点:


1、架构师设计思想篇


2、 手淘全套架构设计与实现


3、 开源框架


4、OKHttp 网络框架


5、一线大厂核心框架剖析与实现



NDK 模块开发(音视频系列)




NDK(Native Development Kit 缩写)一种基于原生程序接口的软件开发工具包,可以让您在 Android 应用中利用 C 和 C++ 代码的工具。通过此工具开发的程序直接在本地运行,而不是虚拟机。


在 Android 中,NDK 是一系列工具的集合,主要用于扩展 Android SDK。NDK 提供了一系列的工具可以帮助开发者快速的开发 C 或 C++的动态库,并能自动将 so 和 Java 应用一起打包成 apk。


知识要点:


1、NDK 开发之 C/C++入门


2、JNI 模块开发


3、Linux 编程


4、底层图片处理


5、音视频开发


6、机器学习



Flutter 学习进阶




2021 年无疑是 Flutter 技术如火如荼发展的一年。


每一个移动开发者都在为 Flutter 带来的“快速开发、富有表现力和灵活的 UI、原生性能”的特色和理念而痴狂,从超级 App 到独立应用,从纯 Flutter 到混合栈,开发者们在不同的场景下乐此不疲的探索和应用着 Flutter 技术,也在面临着各种各样不同的挑战。


知识要点:


1、Flutter 跨平台开发概述


2、Windows 中 Flutter 开发环境搭建


3、编写你的第一个 Flutter APP


4、Flutter Dart 语言系统入门




微信小程序开发




用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
Android 面试总结 - LiveData,2021大厂Android知识点总结