android,handler实现两个线程通信

相关链接:Android HandlerThread 总结

基本概念

android中的Handler对象是两个线程之间通信的桥梁,桥的一端是Handler对象的setXxxMessage()方法(发送msg),另一端是同一个Handler对象的handleMessage(msg)方法(接收msg),两个线程共享一个Handler对象

一个常用的使用场景

Android为了线程安全,并不允许我们在UI线程(主线程)外操作UI,即不允许在子线程中直接操作UI,这时候就需要在子线程中调用Handler对象的setXxxMessage()方法(发送msg),在主线程中调用同一个Handler对象的handleMessage(msg)方法(接收msg),根据msg处理相应的跟新UI逻辑

错误示范:直接在子线程中更新UI

报错信息:Only the original thread that created a view hierarchy can touch its views.

package com.clc.app14;

import android.os.Bundle;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import java.util.Timer;
import java.util.TimerTask;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //执行Timer的schedule方法时,会新建一个线程
        new Timer().schedule(new TimerTask() {
            int i = 0;
            @Override
            public void run() {
                i ++;
                //在这个新的线程中操作UI
                TextView textView = findViewById(R.id.textview);
                textView.setText(""+i);
            }
        },0,1000);
    }
}

利用Handler使子线程间接操作UI(通知主线程跟新UI)

package com.clc.app14;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import java.util.Timer;
import java.util.TimerTask;

public class MainActivity extends AppCompatActivity {

    //系统已经为主线程初始化了一个Looper对象,所以我们直接创建Handler对象
    Handler handler = new Handler(){
        int i = 0;

        //重写handleMessage(),接收本对象sendXxx()方法发来的msg对象,并做处理
        @Override
        public void handleMessage(Message msg) {

            if (msg.what == 1){
                i ++;
                TextView textView = findViewById(R.id.textview);
                textView.setText(""+i);
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main); 

        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                //在需要的地方,调用在主线程中实例化的handler对象的sendXxx()方法,向本对象的handleMessage()发送msg
                //每一次调用sendXxx(),执行一次handleMessage()
                handler.sendEmptyMessage(1);
            }
        },0,1000);
    }
}

另一个demo:自定义一个子线程

package com.clc.app14;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {


    Handler handler = new Handler() {

        //重写handleMessage(),接收本对象sendXxx()方法发来的msg对象,并做处理
        //handleMessage()在主线程中执行
        //本对象sendXxx()方法的调用与执行,可以在其他线程中
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == 1){
                TextView textView = findViewById(R.id.textview);
                textView.setText(msg.getData().getString("key"));
            }
        }
    };

    //新建一个线程,在这个线程中通知更新UI
    class Thread1 extends Thread{
        @Override
        public void run() {
            //创建要发送的msg
            Message msg = new Message();
            msg.what = 1;
            Bundle bundle = new Bundle();
            bundle.putString("key","value");
            msg.setData(bundle);
            //在需要的地方,调用在子线程中实例化的handler对象的sendXxx()方法,向本对象的handleMessage()发送msg
            //每一次调用sendXxx(),执行一次handleMessage()
            handler.sendMessage(msg);
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //在主线程中启动子线程
        Thread1 thread1 = new Thread1();
        thread1.start();
    }
}

 

你可能感兴趣的:(Android)