最后:学习总结——Android框架体系架构知识脑图(纯手绘xmind文档)
学完之后,若是想验收效果如何,其实最好的方法就是可自己去总结一下。比如我就会在学习完一个东西之后自己去手绘一份xmind文件的知识梳理大纲脑图,这样也可方便后续的复习,且都是自己的理解,相信随便瞟几眼就能迅速过完整个知识,脑补回来。
下方即为我手绘的Android框架体系架构知识脑图,由于是xmind文件,不好上传,所以小编将其以图片形式导出来传在此处,细节方面不是特别清晰。但可给感兴趣的朋友提供完整的Android框架体系架构知识脑图原件(包括上方的面试解析xmind文档)
除此之外,前文所提及的Alibaba珍藏版 Android框架体系架构 手写文档以及一本 《大话数据结构》 书籍等等相关的学习笔记文档,也皆可分享给认可的朋友!
——感谢大家伙的认可支持,请注意:点赞+点赞+点赞!!!
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
这样我们就实现了一个简单的线程池,核心线程数为CPU数量+1,非核心线程数为CPU数量*2+1,非核心线程的闲置时间为1秒,任务队列的大小为128。
线程池还有具体的好几种分类和相应不同的实现方式,这里不再细说。
2.3 Handler
有朋友可能会说,你讲的这些都是Java多线程里面的东西,能不能整点咱Android特有的?OK,现在进入专业时间。
Handler是Android提供的一种异步消息处理机制,要学会使用Handler我们首先来了解下消息处理四兄弟:
-
Message
-
Handler
-
MessageQueue
-
Looper
Handler可以帮助我们实现在不同的线程之间传递消息,这里的Message就是消息本体,也就是我们想要传递的那个东西。
Handler在这里扮演的角色是消息处理者,它的主要作用是发送和处理消息。
MessageQueue是一个消息队列,Handler发送过来的消息会放在这个队列里面,每个线程只会有一个MessageQueue对象。
Looper是线程中消息队列的管家,它会无限循环运行,每发现MessageQueue中存在一条消息,它就会把消息取出然后发送给Handler。每一个线程也只能有一个Looper对象。
好了,基本原理已经了解,现在我们来反手搓一个Handler
private static final int FLAG = 1;
private Handler mHandler = new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
if (FLAG == msg.what){
//这里已经回到主线程了
doSomething();
}
}
};
private void fun(){
new Thread(new Runnable() {
@Override
public void run() {
//子线程发送消息
Message message = new Message();
message.what = FLAG;
mHandler.sendMessage(message);
}
}).start();
}
2.4 AsyncTask
除了Handler以外,谷歌爸爸还给我们提供AsyncTask来进行线程的切换。AsyncTask是一种轻量级的异步任务,它可以在线程池中执行后台任务,然后把执行的进度和最终结果传递给主线程。从实现原理上来讲,AsyncTask是对Thread和Handle的再次封装。
AsyncTask本身是一个抽象的泛型类,有四个亲儿子:
-
onPreExecute()
-
doInBackground(Params…params)
-
onProgressUpdate(Progress…values)
-
onPostExecute(Result result)
最先执行的是方法是onPreExecute()方法,位于主线程中,一般用来做一些准备工作。
然后执行doInBackground()方法,位于线程池中,用来执行异步任务,params表示异步任务的输入参数。这个方法需要返回结果给onPostExecute()方法。
onProgressUpdate()方法在主线程中执行,当后台任务的执行进度发生变化时这个方法会被调用。
onPostExecute()方法在最后异步任务完成之后会被调用,位于主线程中,result参数是后台任务的返回值,即doInBackground()的返回值。
OK,基本原理已经了解了,现在我们来手搓一个AsyncTask
class DownloadTask extends AsyncTask<Void,Integer,Boolean> {
@Override
protected void onPreExecute() {
//这里我们使用了一个显示进度的Dialog,具体实现不表
progressDialog.show();
}
@Override
protected Boolean doInBackground(Void… voids) {
try {
while (true){
//调用我们的doDownload下载方法,具体实现不表
int downloadPercent = doDownload();
//使用publishProgress方法来更新执行的进度
publishProgress(downloadPercent);
if (downloadPercent >= 100)
break;
}
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
@Override
protected void onProgressUpdate(Integer… values) {
//更新下载进度
progressDialog.setMessage(“Download “+values[0]+”%”);
}
@Override
protected void onPostExecute(Boolean aBoolean) {
//下载完成
progressDialog.dismiss();
}
}
这里我们创建了一个Download类继承自AsyncTask,有三个泛型,void表示不需要给后台任务传入参数,Integer表示用整数类型来作为进度显示的单位,Boolean表示用布尔类型来反馈后台任务的执行结果。
要让我们的这个AsyncTask跑起来也很简单,只需要执行:
new DownloadTask().execute();
2.5 IntentService
IntentService是一种特殊的Service,它继承了Service并且是一个抽象类,我们可以创建它的子类来使用。IntentService也可以用于执行后台的耗时任务,并且当任务执行完毕之后它会自动停止。
IntentService因为是服务的原因,所以和单纯的线程相比它的优先级要高很多,从而更不容易被系统杀死。
IntentService的内部实现是封装了HandlerThread和Handler,使用的话要遵循Service的使用方法,这里先略过后面有机会在Service的专栏里面再详细介绍。
2.6 RxJava
有杠精可能会说,你讲的这些方法,一个比一个长,一个比一个复杂,就不能整个简单又粗暴的东西?
这个时候就需要祭出神兵利器RxJava了。
- 2.6.1 RxJava又是个啥?
其实网络上RxJava的入门文章多如过江之鲫,这里不打算过多的深入介绍。RxJava是一种响应式编程,大家不是很明白的话可以粗暴的理解为更优雅的多线程实现即可。
- 2.6.2 那怎么操作RxJava?
先手搓一个RxJava的普通实现方式
private void fun(){
Observable observable = Observable.create(new ObservableOnSubscribe() {
@Override
public void subscribe(ObservableEmitter emitter) throws Exception {
emitter.onNext(1);
}
});
observable.subscribeOn(Schedulers.io()) //表示在io线程执行订阅
.observeOn(AndroidSchedulers.mainThread()) //表示在主线程接收订阅
.subscribe(new Observer() {
@Override
public void onSubscribe(Disposable d) {
//接收订阅之前调用
}
@Override
public void onNext(Integer integer) {
//接收订阅成功调用
doSomething();
}
@Override
public void onError(Throwable e) {
//接收订阅出错调用
}
@Override
public void onComplete() {
//接收订阅完成调用
}
});
}
emmmmm看起来好像还是挺复杂的啊,能不能再整简单点?
OK,链式调用加lambda安排上
private void fun() {
Observable.create(emitter -> emitter.onNext(1))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(integer -> {
//接收订阅成功
doSomething();
}, throwable -> {});
}
嗯…有内味了。
这串代码我们是发送了一个Integer类型的数据;
subscribeOn()指定了我们发送的线程是在后台的io线程,就可以理解为一个子线程;
observeOn指定了我们接收的线程为主线程;
subscribe只接收成功的消息,相当于上面的OnNext()方法,本质上是我们在这里创建了一个Comsumer对象来接收;
throwable在接收失败的时候调用,相当于上面的onError()方法。
RxJava有多达几十种的操作符,灵活运用能实现各种不同的异步任务,这里就不再花大量的篇幅详细介绍了,有兴趣的朋友可以去查看ReactiveX中文文档
2.7 RxKotlin
RxKotlin可以理解为RxJava在Kotlin上的一个变种,原理都是一样的,只是操作语言变成了Kotlin,然后封装了一下使得可以更优雅的调用,这里给大家一个具体的实现案例,不再过多讲解。
private fun test() {
Observable.create { 1 }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeBy(
onNext = {},
onError = {}
)
}
2.8 Kotlin协程
协程其实和上面所说的线程并不是一个概念,协程是什么?根据官方文档的描述,协程本质上是轻量级的线程。既然是轻量,那说明协程的资源消耗和性能等方面和线程比起来应该是有优势的。那这样看来我们以前使用多线程实现的异步功能,现在基本上都可以用协程来替代了。
协程是一个全新的东西,介于篇幅这里就不展开讲解了,后面会专门写介绍协程的文章。
================================================================
今天总结了Android平台上实现多线程的几种方式,希望能给到需要的朋友一些帮助。
结语
网上高级工程师面试相关文章鱼龙混杂,要么一堆内容,要么内容质量太浅, 鉴于此我整理了上述安卓开发高级工程师面试题以及答案。希望帮助大家顺利进阶为高级工程师。
目前我就职于某大厂安卓高级工程师职位,在当下大环境下也想为安卓工程师出一份力,通过我的技术经验整理了面试经常问的题,答案部分是一篇文章或者几篇文章,都是我认真看过并且觉得不错才整理出来。
大家知道高级工程师不会像刚入门那样被问的问题一句话两句话就能表述清楚,所以我通过过滤好文章来帮助大家理解。
现在都说互联网寒冬,其实只要自身技术能力够强,咱们就不怕!我这边专门针对Android开发工程师整理了一套【Android进阶学习视频】、【全套Android面试秘籍】、【Android知识点PDF】。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
出一份力,通过我的技术经验整理了面试经常问的题,答案部分是一篇文章或者几篇文章,都是我认真看过并且觉得不错才整理出来。
大家知道高级工程师不会像刚入门那样被问的问题一句话两句话就能表述清楚,所以我通过过滤好文章来帮助大家理解。
[外链图片转存中…(img-pBI33SoN-1715349752466)]
现在都说互联网寒冬,其实只要自身技术能力够强,咱们就不怕!我这边专门针对Android开发工程师整理了一套【Android进阶学习视频】、【全套Android面试秘籍】、【Android知识点PDF】。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!