目录
引言
Android为我们提供了消息循环的机制,我们可以利用这个机制来实现线程间的通信。那么,我们就可以在非UI线程发送消息到UI线程,最终让UI线程来进行UI的操作。
对于运算量较大的操作和IO操作或者网络请求,我们需要新开线程来处理这些繁重的工作,以免阻塞UI线程。
Thread+Handler
HandlerThread一般用于批处理,在需要切换对象较多的情况下。
使用:
-
创建Handler类并重写handleMessage方法
Handler mHandler = new Handler(){ @Override public void handeMessage(@NonNull Message msg){ super.handlerMessage(msg); } }
-
将对UI操作的代码放进上面的
HandelMessage
里面,然后在子线程加入一句代码mHandler.sendEmptyMessage(1);//不带参数
-
此时子线程如果得到的数据要传回主线程并在UI上显示,就需要构造一个Message对象,将数据通过Message传给UI线程
Message message = new Message(); message.what = 1; Bundle bundle = new Bundle(); bundle.putString("key","子线程得到的数据"); message.setData(bundle); mHandler.senMessage(message);//带参数
-
然后就是在主线程接受子线程发过来的数据,并写到UI里面
String s = msg.getData().getString("key");//子线程传过来的数据,通过key值获取 textView.setText(s);//更新UI
原理:
首先是子线程发送消息给主线程,主线程有对应的回调方法去收到这个消息通知,并更新。
- 创建的Handler在主线程,所以主线程和子线程可以拿到它的引用,并对它进行操作。
- 它们之间的消息传递通过一个叫Message的对象,子线程通过sendMessage()这个方法,将这个对象放到一个叫MessageQueue的队列里面每次发送一个Message就放到这个队列的队尾。
- 主线程有一个Looper来对这个队列进行操作,里面有一个loop()方法,通过循环操作将队列里面的Message对象以先进先出的顺序取出来
- 取出来以后调用Handler的dispatchMessage()方法,这个方法里面调用了handleMessage方法,也就是回调handleMessage方法
AsyncTask
AsyncTask一般用于单个任务的线程切换。
核心方法:
-
execute(Params)(在主线程手动调用,执行异步任务)
-
onPreExecute() (在execute方法前自动调用,用于界面的初始化,如显示进度条等)
-
doInBackground(Params)(在onPreExecute方法之后自动调用,接受参数,执行耗时操作,返回一个执行结果)
-
onProgressUpdate(Progress)(在主线程调用publishProgress时自动调用显示线程任务执行的进度)
-
onPostExecute(Result)(任务结束时自动调用,接收结果并显示到UI组件)
-
onCancelled()(将异步任务设置为取消状态,在任务被取消时自动调用,此时onPostExecute()不会被调用)
创建子类继承AsyncTask抽象类,并重写上面的几个方法…
再创建这个类的对象实例,在主线程使用execute方法调用。
AsyncTask
不与任何组件绑定生命周期,另外最好在activity里面的onDistory()里面调用cancel()- 若
AsyncTask
被声明为Activity
的非静态内部类,当Activity
需销毁时,会因AsyncTask
保留对Activity
的引用 而导致Activity
无法被回收,最终引起内存泄露
**原理:**AsyncTask是对Handler和线程池(一个任务队列线程池,一个执行线程池)的封装,Handler用于给主线程发送一个通知去更新UI,线程池用于避免不必要的创建和销毁线程,在线程池内通过维护 固定数量的线程,使他们轮番上阵,避免不必要的开销。
它有几个局限性:
- AsyncTask对象必须在主线程创建
- AsyncTask对象的execute方法必须在主线程调用
- 一个AsyncTask对象只能调用一次execute方法
AsyncTask的成员mWorker(派生子WorkRunnable类的对象,实现了Callable接口)包含了AsyncTask最终要执行的任务(mWorker的call方法)和mFuture(FutureTask的直接子类的对象,里面传入mWorker作为参数)。前者覆写call()后者覆写done()。
FutureTask类实现了FutureRunnable接口,通过这个接口可以方便的取消后台任务以及获取后台任务的执行结果
- 执行任务前,通过 任务队列 线程池类(SerialExecutor)将任务按顺序放入到队列中;
通过同步锁 修饰
execute()
从而保证AsyncTask中的任务是串行执行的
- 之后的线程任务执行是 通过任务线程池类(THREAD_POOL_EXECUTOR) 进行的。
- 任务线程池类
(THREAD_POOL_EXECUTOR)
实际上是1个已配置好的可执行并行任务的线程池 - 调用
THREAD_POOL_EXECUTOR.execute()
实际上是调用线程池的execute()
去执行具体耗时任务 - 而该耗时任务则是步骤2中初始化
WorkerRunnable
实例对象时复写的call()
内容 - 在
call()
方法里,先调用 我们复写的doInBackground(mParams)
执行耗时操作 - 再调用
postResult(result)
, 通过InternalHandler
类 将任务消息传递到主线程;根据消息标识(MESSAGE_POST_RESULT)
判断,最终通过finish()
调用我们复写的onPostExecute(result)
,从而实现UI更新操作
InterService
-
自定义类继承InterService,重写onHandleIntent方法中写下载逻辑
-
Activity中使用startService或bindService来启动职务
RxJava
这个也可以实现线程的切换…
什么是RxJava
它的自我介绍:一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库
其实总结就是RxJava
是一个 基于事件流、实现异步操作的库
类似于 Android
中的 AsyncTask
、Handler
作用
https://blog.csdn.net/qq_46526828/article/details/107456378
原理介绍
RxJava的异步实现,是通过一种扩展的观察者模式来实现的
观察者模式:定义对象之间的一种一对多的依赖关系,使得每当一个对象状态发生改变时其相关依赖对象都得到通知。(设计模式-刘伟)
举个例子:设计模式里面的例子,在一个红绿灯的问题里面,驾驶员是观察者,红绿灯是被观察者,在程序中就采用注册或者订阅的方式告诉被观察者:我需要你的某某状态,你要在它变化的时候通知我。
对应于Android里面就是点击监听器,对设置 OnClickListener
来说, View
是被观察者, OnClickListener
是观察者,二者通过 setOnClickListener()
方法达成订阅关系,概念转化:(Button
-> 被观察者、OnClickListener
-> 观察者、setOnClickListener()
-> 订阅,onClick()
-> 事件)
所以RxJava有四个基本概念:
角色 | 作用 | 类比 |
---|---|---|
观察者(Observer) | 接收事件,并给出响应动作 | OnClickListener |
被观察者(Observable) | 产生事件 | button |
订阅(Subscribe) | 连接 被观察者 & 观察者 | setOnClickListener |
事件(Event) | 被观察者 & 观察者 沟通的载体 | onClick |
事件回调除了onNext和onError外还有onCompleted(onCompleted()
和 onError()
二者互斥)
基本实现
实现原理
-
创建Observer
接口的实现方式:
Observer observer = new Observer() {
//重写三个方法
}
抽象类实现方式:
Subscriber subscriber = new Subscriber() {
//重写三个方法
}
Subscriber比Observer多了onStart和unsubscribe,前者用于在 subscribe 刚开始,而事件还未发送之前被调用,可以用于做一些准备工作,例如数据的清零或重置。后者用于取消订阅。在这个方法被调用后,
Subscriber
将不再接收事件 -
创建Observeable
使用create方法来创建一个Observable,并定义触发规则
Observable observable = Observable.create(new Observable.OnSubscribe() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext(“Hello”);
subscriber.onNext(“Hi”);
subscriber.onNext(“Aloha”);
subscriber.onCompleted();
}
});
当
Observable
被订阅的时候,OnSubscribe
的call()
方法会自动被调用,事件序列就会依照设定依次触发(对于上面的代码,就是观察者Subscriber
将会被调用三次onNext()
和一次onCompleted()
)。这样,由被观察者调用了观察者的回调方法,就实现了由被观察者向观察者的事件传递,基于create方法还提供-
just(T…):将传入的参数依次发送出来
Observable observable = Observable.just(“Hello”, “Hi”, “Aloha”);
-
**from(T[ ])
/
from(Iterable<? extends T>)😗*将传入的数组或Iterable
拆分成具体对象后,依次发送出来String[] words = {“Hello”, “Hi”, “Aloha”};
Observable observable = Observable.from(words);
-
-
创建Subscribe
创建了
Observable
和Observer
之后,再用subscribe()
方法将它们联结起来,整条链子就可以工作了observable.subscribe(observer);
//或者:
Observable.subscribe(subscriber);
public class MainActivity extends AppCompatActivity { TextView textView ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView=findViewById(R.id.textview); Observer<String> observer = new Observer<String>() { @Override public void onNext(String s) { Log.d("tag", "Item: " + s); } @Override public void onCompleted() { Log.d("tag", "Completed!"); } @Override public void onError(Throwable e) { Log.d("tag", "