最后
目前已经更新的部分资料:
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
}
public synchronized void post(Runnable runnable){
queue.add(runnable);
}
public synchronized void clearAllMessage(){
queue.clear();
}
public synchronized void clearOneMessage(Runnable runnable){
for(Runnable runnable1 : queue){
if(runnable == runnable1){
queue.remove(runnable);
}
}
}
}
public void testDemoThread(){
DemoThread thread = new DemoThread();
thread.start();
//发一个消息
Runnable r = new Runnable() {
@Override
public void run() {
}
};
thread.post®;
//不想执行了。。。。删掉
thread.clearOneMessage®;
}
看分分钟完成HandlerThread能做到的一切。。。。是不是很简单。
3.直接使用AsyncTask.execute()
AsyncTask.execute(new Runnable() {
@Override
public void run() {
}
});
个人认为AsyncTask的设计暴露了这个 接口方法 谷歌做的非常不恰当。它这样允许开发者直接使用AsyncTask本身的线程池,我们可以看看源代码做验证
@MainThread
public static void execute(Runnable runnable) {
sDefaultExecutor.execute(runnable);
}
果不其然,execute直接访问了executor。
这样的问题在于,这样使用完全丧失了AsyncTask本身的意图。个人的观点是,AsyncTask提供了一个后台任务切换到主线程的通道,就像RxJava的subscribeOn/observeOn一样,同时提供cancel方法,可以取消掉切换回主线程执行的代码,从而防止内存泄漏。
AsyncTask asyncTask = new AsyncTask() {
@Override
protected Object doInBackground(Object[] objects) {
return null;
}
@Override
protected void onPostExecute(Object o) {
//1.提供了后台线程切换回主线程的方法
super.onPostExecute(o);
}
};
//2.可以随时取消
asyncTask.cancel(true);
But!如果直接使用execute方法的话,我们完全没有利用到AsyncTask本身设计的初衷下的优势,和直接自己创建一个线程池没有任何区别,还存在内存泄漏的风险。这样的用法,肯定不能称之为best practice
.
4. 以为RxJava的unsubscribe能包治百病
这个误区标题起的有点模糊,这个没办法,因为例子有点点复杂。让我来慢慢解释。
我们以一个实际的app例子开始,让我们看看youtube的app退订频道功能:
用户点击退订按钮之后,app发出api call,告诉后台我们停止订阅该频道,同时把UI更新为progress bar,当api call结束,在api的回调里面我们更新UI控件显示已退订UI。我们写一个示例代码看看:完美!
但是万一用户在点击退订按钮,但是api call还没发出去之前就退出了app呢?
public class YoutubePlayerActivity extends Activity {
private Subscription subscription;
public void setUnSubscribeListner(){
unsubscribeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
subscription = Observable.create(new Observable.OnSubscribe() {
@Override
public void call(Subscriber<? super Void> subscriber) {
try {
//在这里我们做取消订阅的API, http
API api = new API();
api.unSubscribe();
}
catch (Exception e){
subscriber.onError(e);
}
subscriber.onNext(null);
subscriber.onCompleted();
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1() {
@Override
public void call(Void aVoid) {
//API call成功!,在这里更新订阅button的ui
unsubscribeButton.toggleSubscriptionStatus();
}
});
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
//onDestroy 里面对RxJava stream进行unsubscribe,防止内存泄漏
subscription.unsubscribe();
}
}
看似好像没啥问题,没有内存泄漏,可以后台线程和主线程直接灵活切换,更新UI不会crash。而且我们使用了Schedulers.io()调度器,看似也没有浪费线程资源。
BUT!!!!!!
我们先仔细想想一个问题。我们在点击button之后,我们的Observable
API api = new API();
api.unSubscribe();
会立刻执行么?
答案是NO。因为我们的Observable是subscribeOn io线程池。如果该线程池现在非常拥挤,这段代码,这个Observable是不会立刻执行的。该段代码会华丽丽的躺在线程池的队列中,安安静静的等待轮到自己执行。
那么如果用户点击按钮,同时退出app,我们unubscribe了这个RxJava 的observable 我们就存在一个不会执行api call的风险。也就是用户点击退订按钮,退出app,返回app的时候,会发现,咦,怎么明明点了退订,竟然还是订阅状态?
这就回到了一个本质问题,来自灵魂的拷问。是不是所有异步调用,都需要和Activity或者fragment的生命周期绑定?
答案同样是NO,在很多应用场景下,当用户做出一个行为的时候,我们必须坚定不移的执行该行为背后的一切操作,至于异步操作完成之后的UI更新,则视当前Activity或者fragment的生命周期决定。也就是异步操作和生命周期无关,UI更新和生命周期有关。简单点说,很多情况下,写操作不能取消,读操作可以。
很多情况下,比如支付,订阅等等这种用户场景,需要涉及到异步操作的都是会有以上的问题。在这些场景下,我们需要遵循以下流程。
最最重点的部分,就是当用户退出的时候虽然我们停止更新UI,但当用户重新进入的时候,app需要主动的重新向后台发送请求,查看当前订阅状态。这样,才是一个健康的app。
文章不易,如果大家喜欢这篇文章,或者对你有帮助希望大家多多, 点赞 , 转发 , 关注 。文章会持续更新的。绝对干货!!!
如何做好面试突击,规划学习方向?
面试题集可以帮助你查漏补缺,有方向有针对性的学习,为之后进大厂做准备。但是如果你仅仅是看一遍,而不去学习和深究。那么这份面试题对你的帮助会很有限。最终还是要靠资深技术水平说话。
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。建议先制定学习计划,根据学习计划把知识点关联起来,形成一个系统化的知识体系。
学习方向很容易规划,但是如果只通过碎片化的学习,对自己的提升是很慢的。
同时我还搜集整理2020年字节跳动,以及腾讯,阿里,华为,小米等公司的面试题,把面试的要求和技术点梳理成一份大而全的“ Android架构师”面试 Xmind(实际上比预期多花了不少精力),包含知识脉络 + 分支细节。
在搭建这些技术框架的时候,还整理了系统的高级进阶教程,会比自己碎片化学习效果强太多。
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!