Android--多线程的切换

本文详细介绍了Android中多线程切换的四种方法:Thread+Handler、AsyncTask、InterService以及RxJava。讲解了它们的工作原理、使用方法和应用场景,重点探讨了RxJava的异步处理和线程控制。
摘要由CSDN通过智能技术生成

引言

Android为我们提供了消息循环的机制,我们可以利用这个机制来实现线程间的通信。那么,我们就可以在非UI线程发送消息到UI线程,最终让UI线程来进行UI的操作。

对于运算量较大的操作和IO操作或者网络请求,我们需要新开线程来处理这些繁重的工作,以免阻塞UI线程。

Thread+Handler

HandlerThread一般用于批处理,在需要切换对象较多的情况下。
使用:

  1. 创建Handler类并重写handleMessage方法

    Handler mHandler = new Handler(){
         
        @Override
        public void handeMessage(@NonNull Message msg){
         
            super.handlerMessage(msg);
        }
    }
    
  2. 将对UI操作的代码放进上面的HandelMessage里面,然后在子线程加入一句代码

    mHandler.sendEmptyMessage(1);//不带参数
    
  3. 此时子线程如果得到的数据要传回主线程并在UI上显示,就需要构造一个Message对象,将数据通过Message传给UI线程

    Message message = new Message();
    message.what = 1;
    Bundle bundle = new Bundle();
    bundle.putString("key","子线程得到的数据");
    message.setData(bundle);
    mHandler.senMessage(message);//带参数
    
  4. 然后就是在主线程接受子线程发过来的数据,并写到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方法调用。

  1. AsyncTask不与任何组件绑定生命周期,另外最好在activity里面的onDistory()里面调用cancel()
  2. AsyncTask被声明为Activity的非静态内部类,当Activity需销毁时,会因AsyncTask保留对Activity的引用 而导致Activity无法被回收,最终引起内存泄露

**原理:**AsyncTask是对Handler和线程池(一个任务队列线程池,一个执行线程池)的封装,Handler用于给主线程发送一个通知去更新UI,线程池用于避免不必要的创建和销毁线程,在线程池内通过维护 固定数量的线程,使他们轮番上阵,避免不必要的开销。

它有几个局限性

  1. AsyncTask对象必须在主线程创建
  2. AsyncTask对象的execute方法必须在主线程调用
  3. 一个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

  1. 自定义类继承InterService,重写onHandleIntent方法中写下载逻辑

  2. Activity中使用startService或bindService来启动职务

RxJava

这个也可以实现线程的切换…

什么是RxJava

它的自我介绍:一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库

其实总结就是RxJava 是一个 基于事件流、实现异步操作的库

类似于 Android中的 AsyncTaskHandler作用

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() 二者互斥)

基本实现

实现原理

  1. 创建Observer

    接口的实现方式:

    Observer observer = new Observer() {

    ​ //重写三个方法

    }

    抽象类实现方式:

    Subscriber subscriber = new Subscriber() {

    ​ //重写三个方法

    }

    Subscriber比Observer多了onStart和unsubscribe,前者用于在 subscribe 刚开始,而事件还未发送之前被调用,可以用于做一些准备工作,例如数据的清零或重置。后者用于取消订阅。在这个方法被调用后,Subscriber 将不再接收事件

  2. 创建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 被订阅的时候,OnSubscribecall() 方法会自动被调用,事件序列就会依照设定依次触发(对于上面的代码,就是观察者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);

  3. 创建Subscribe

    创建了 ObservableObserver 之后,再用 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", "
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值