Android中多线程实现

Android中多线程主要有三种实现方式:通过Thread类、AsyncTask或者RxJava。

  1. 通过Thread类

我们使用Thread类时,可以创建Thread的子类并重写其run方法, 或者自定义一个实现Runable协议的类,然后将其与Thread进行绑定。将线程间数据交互则可通过共享Hander对象来实现。

一个简单的例子如下:

java 复制代码
public class MainActivity extends AppCompatActivity {
    public TextView mTextView;
    public Handler mHandler;
    // 步骤1:(自定义)新创建Handler子类(继承Handler类) & 复写handleMessage()方法
    class Mhandler extends Handler {
        // 通过复写handlerMessage() 从而确定更新UI的操作
        @Override
        public void handleMessage(Message msg) {
            // 根据不同线程发送过来的消息,执行不同的UI操作
            // 根据 Message对象的what属性 标识不同的消息
            switch (msg.what) {
                case 1:
                    mTextView.setText("执行了线程1的UI操作");
                    break;
                case 2:
                    mTextView.setText("执行了线程2的UI操作");
                    break;
            }
        }
    }
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        mTextView = (TextView) findViewById(R.id.show);
 
        // 步骤2:在主线程中创建Handler实例
        mHandler = new Mhandler();
       
        // 采用继承Thread类实现多线程演示
        new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                 // 步骤3:创建所需的消息对象
                 Message msg = Message.obtain();
                 msg.what = 1; // 消息标识
                 msg.obj = "A"; // 消息内存存放
                 // 步骤4:在工作线程中 通过Handler发送消息到消息队列中
                 mHandler.sendMessage(msg);
            }
        }.start();
        // 步骤5:开启工作线程(同时启动了Handler)
 
        // 此处用2个工作线程展示
        new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 通过sendMessage()发送
                 // a. 定义要发送的消息
                 Message msg = Message.obtain();
                 msg.what = 2; //消息的标识
                 msg.obj = "B"; // 消息的存放
                 // b. 通过Handler发送消息到其绑定的消息队列
                 mHandler.sendMessage(msg);
            }
        }.start();
 
    }
  1. 通过AsyncTask
    AsyncTask只能在UI线程调用,一般作为Activity的子类, 以便在重写的方法中访问 Activity中的属性和数据。
java 复制代码
/**

  * 步骤1:创建AsyncTask子类
  * 注: 
  *   a. 继承AsyncTask类
  *   b. 为3个泛型参数指定类型;若不使用,可用java.lang.Void类型代替
  *   c. 根据需求,在AsyncTask子类内实现核心方法
*/ 
private class MyTask extends AsyncTask<Params, Progress, Result> {
        ....
      // 方法1:onPreExecute()
      // 作用:执行 线程任务前的操作
      // 注:根据需要决定是否复写
      @Override
      protected void onPreExecute() {
           ...
        }
 
      // 方法2:doInBackground()
      // 作用:接收输入参数、执行任务中的耗时操作、返回 线程任务执行的结果
      // 注:必须复写,从而自定义线程任务
      @Override
      protected String doInBackground(String... params) {
      
            ...// 自定义的线程任务
            
            // 可调用publishProgress()显示进度, 之后将执行onProgressUpdate()
             publishProgress(count);
              
         }
 
      // 方法3:onProgressUpdate()
      // 作用:在主线程 显示线程任务执行的进度
      // 注:根据需求复写
      @Override
      protected void onProgressUpdate(Integer... progresses) {
            ...
 
        }
 
      // 方法4:onPostExecute()
      // 作用:接收线程任务执行结果、将执行结果显示到UI组件
      // 注:必须复写,从而自定义UI操作
      @Override
      protected void onPostExecute(String result) {
 
         ...// UI操作
 
        }
 
      // 方法5:onCancelled()
      // 作用:将异步任务设置为:取消状态
      @Override
        protected void onCancelled() {
        ...
        }
  }
 
/**
  * 步骤2:创建AsyncTask子类的实例对象(即 任务实例)
  * 注:AsyncTask子类的实例必须在UI线程中创建
  */
  MyTask mTask = new MyTask();
 
/**
  * 步骤3:手动调用execute(Params... params) 从而执行异步线程任务
  * 注:
  *    a. 必须在UI线程中调用
  *    b. 同一个AsyncTask实例对象只能执行1次,若执行第2次将会抛出异常
  *    c. 执行任务中,系统会自动调用AsyncTask的一系列方法:onPreExecute() 、doInBackground()、onProgressUpdate() 、onPostExecute() 
  *    d. 不能手动调用上述方法
  */
 mTask.execute();

3.通过RxJava实现

使用RxJava的好处是,通过采用这种封装好的异步调度框架,可以大大简化线程间切换的过程。

java 复制代码
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final TextView tv_return = (TextView) findViewById(R.id.tv_return);
        //创建被观察者
        Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                Log.d(TAG, "Observer thread is :" + Thread.currentThread().getName());
                emitter.onNext(getResponse());
            }
        });

        //创建观察者
        Consumer<String> consumer = new Consumer<String>() {
            @Override
            public void accept(String mResponse) throws Exception {
                Log.d(TAG, "Observer thread is :" + Thread.currentThread().getName());
                tv_return.setText(mResponse);
            }
        };
       //subscribeOn() 指定的是发送事件的线程, observeOn() 指定的是接收事件的线程.
        observable.subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(consumer);

    }
    //使用okhttp访问网上提供的接口,由于是同步get请求,需要在子线程进行
    private String getResponse() {
        String url = "http://v.juhe.cn/weather/index?cityname=%E6%9D%AD%E5%B7%9E&dtype=&format=&key=7970495dbf33839562c9d496156e13cc";
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(url)
                .build();
        Response response;

        try {
            response = client.newCall(request).execute();
            return response.body().string();
        } catch (IOException e) {
            return "error";
        }
    }
相关推荐
拭心4 小时前
Google 提供的 Android 端上大模型组件:MediaPipe LLM 介绍
android
带电的小王6 小时前
WhisperKit: Android 端测试 Whisper -- Android手机(Qualcomm GPU)部署音频大模型
android·智能手机·whisper·qualcomm
梦想平凡6 小时前
PHP 微信棋牌开发全解析:高级教程
android·数据库·oracle
元争栈道7 小时前
webview和H5来实现的android短视频(短剧)音视频播放依赖控件
android·音视频
阿甘知识库8 小时前
宝塔面板跨服务器数据同步教程:双机备份零停机
android·运维·服务器·备份·同步·宝塔面板·建站
元争栈道8 小时前
webview+H5来实现的android短视频(短剧)音视频播放依赖控件资源
android·音视频
MuYe8 小时前
Android Hook - 动态加载so库
android
居居飒9 小时前
Android学习(四)-Kotlin编程语言-for循环
android·学习·kotlin
Henry_He12 小时前
桌面列表小部件不能点击的问题分析
android
工程师老罗12 小时前
Android笔试面试题AI答之Android基础(1)
android