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";
        }
    }
相关推荐
千里马学框架2 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台2 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone2 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc2 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo2 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077002 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼2 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone2 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen2 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone2 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui