先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
如果你需要这些资料,可以添加V获取:vip204888 (备注Android)
正文
// Postpone the runnable until we know on which thread it needs to run.
// Assume that the runnable will be successfully placed after attach.
getRunQueue().post(action);
return true;
}
这里会首先判断 attachInfo 是否为空,不为空的话,会直接调用 handler.post() 方法。也就是说,如果 attachInfo 对象不为空,view.post() 和 new Handler().post() 的效果是相同的。
反之,如果 attachInfo 为空,就会调用 mRunQueue 对象的 post() 方法
public void postDelayed(Runnable action, long delayMillis) {
final HandlerAction handlerAction = new HandlerAction(action, delayMillis);
synchronized (this) {
if (mActions == null) {
mActions = new HandlerAction[4];
}
mActions = GrowingArrayUtils.append(mActions, mCount, handlerAction);
mCount++;
}
}
查看该方法的源码,会发现它并没有将任务直接发送,而是创建了一个 HandlerAction 数组保存了起来。也就是说,如果 attachInfo 对象为空,就将任务暂时保存到数组中,在后续的某一个时刻,再进行发送。
ViewRootImpl.java
private void performTraversals() {
…
// host即DecorView
host.dispatchAttachedToWindow(mAttachInfo, 0);
…
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
…
performLayout(lp, mWidth, mHeight);
…
performDraw();
…
}
View.java
void dispatchAttachedToWindow(AttachInfo info, int visibility) {
mAttachInfo = info;
…
// Transfer all pending runnables.
if (mRunQueue != null) {
mRunQueue.executeActions(info.mHandler);
mRunQueue = null;
}
…
}
可以看到,在 dispatchAttachedToWindow 方法里,通过执行 executeActions 将之前保存的任务全部发送。
这里可能会有人有疑问,dispatchAttachedToWindow 方法是在 performMeasure 等绘制操作之前进行的,也就是 view.post() 中的任务是在绘制之前发送的,为什么它还能获取到 view 的真实宽高呢?
这就涉及到 Android 的消息机制了,整个 Android 体系都是由消息来驱动的,我们这里只涉及到主线程,所以我们通过 view.post(), new Handler().post() 等方式发送的任务,都被添加到了主线程到消息队列中,等待执行,而 performTraversals() 方法也是在另一个任务中执行的,源码如下:
ViewRootImpl.java
final class TraversalRunnable implements Runnable {
@Override
public void run() {
doTraversal();
}
}
final TraversalRunnable mTraversalRunnable = new TraversalRunnable();
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
if (!mUnbufferedInputDispatch) {
scheduleConsumeBatchedInput();
}
notifyRendererOfFramePending();
pokeDrawLockIfNeeded();
}
}
所以,executeActions() 方法发送的任务,只是将其添加到主线程到任务队列中,只有当 performTraversals() 方法所在的任务执行完毕后,才会执行队列中的其他任务。
回到最初的问题,我们在 onResume() 方法中直接执行 view.post() 方法的时候,attachInfo 对象此时为空,具体原理请参考 【Android源码解析】View.post()到底干了啥。所以 view.post() 中的任务会被暂时存放到数组中,在开始绘制之前被发送到主线程的消息队列中,绘制完成后会被执行。但是被缓存的任务一定不止我们添加的这一个,还有一些其他的系统任务,所以我们还要通过 new Handler().post() 在主线程的消息队列尾部重新添加一个任务,用来作为绘制结束的标记,是相对准确的。
作者:huangbo
链接:https://juejin.im/post/6882326732511608840
文末
【360°全方位性能调优】
性能优化相关所有知识点已经为你们整理成了PDF,从理论着手,利用大量实战案例带你全方位掌握APP性能优化的各个知识点和思路,需要的小伙伴**点赞+关注后简信【1】**即可无偿获取或直接在我的GitHub直接下载~
最后,祝愿大家在这并不友好的环境下都能找到自己心仪的归宿!
感谢大家关注我,分享Android干货,交流Android技术。
对文章有何见解,或者有何技术问题,都可以在评论区一起留言讨论,我会虔诚为你解答。
也欢迎大家来我的B站找我玩,有各类Android架构师进阶技术难点的视频讲解,助你早日升职加薪。
B站直通车:https://space.bilibili.com/544650554
写在最后
今天关于面试的分享就到这里,还是那句话,有些东西你不仅要懂,而且要能够很好地表达出来,能够让面试官认可你的理解,例如Handler机制,这个是面试必问之题。有些晦涩的点,或许它只活在面试当中,实际工作当中你压根不会用到它,但是你要知道它是什么东西。
最后在这里小编分享一份自己收录整理上述技术体系图相关的几十套腾讯、头条、阿里、美团等公司的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。
还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
【Android核心高级技术PDF文档,BAT大厂面试真题解析】
【算法合集】
【延伸Android必备知识点】
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注Android)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
4888 (备注Android)**
[外链图片转存中…(img-ARj1DXut-1713714471832)]
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!