Handler使用大全

Handler是什么

handler是Android给我们提供用来更新UI的一套机制,也是一套消息处理机制,我们可以发消息,也可以通过它处理消息


原理(解析异步消息处理机制)

MessageMessage是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间交换数据。
HandlerHandler主要用于发送和处理消息的,发送消息一般是使用Handler的sendMessage()方法,而发出的消息经过处理后,最终会传递到Handler的handlerMessage()方法中
MessageQueue消息队列,用于存放所有通过Handler发送的消息。每个线程只有一个MessageQueue对象
LooperLooper是每个线程的MessageQueue的管家,调用Looper的loop()方法后,就会进入到一个无限循环当中,然后每当发现MessageQueue中存在一条消息,就会将他取出,并传递到Handler的handlerMessage()方法中。每个线程也只会有一个Looper对象

处理过程

  1. 在主线程创建Handler对象。
  2. 重写 handlerMessage() 方法。
  3. 当子线程需要UI操作时,就创建一个Message对象,并通过Handler将这条消息发出去。
  4. 这条消息被添加到MessageQueue中等待处理,最后分发回handlerMessage中。
  5. 由于Handler是在主线程创建的,所以此时handlerMessage()方法也在主线程中运行,于是就可以进行UI操作了。

举例

利用Handler修改子线程UI,这里简单演示修改TextView的文字。

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private TextView show;

    public static final int UPDATE_TEXT = 1;

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            //接收,判断,处理消息
            switch (msg.what) {
                case UPDATE_TEXT:
                    show.setText("更改UI");
                    break;
                default:
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //一个Textview,修改文字来达到模拟更改界面UI的效果
        show = (TextView) findViewById(R.id.tv_show);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.tv_show:
                //开启线程(这里是模拟在线程里要修改UI的情况)
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        //定义一个Message,可以发送给Handler
                        Message myMessage = new Message();
                        //用户定义的消息代码,以便接收者能够识别该消息的内容。
                        myMessage.what = UPDATE_TEXT;
                        //把myMessage放到消息队列的末尾,它将在handleMessage(Message)中接收
                        handler.sendMessage(myMessage);
                    }
                });
            default:
                break;
        }
    }
}

给message设置数据

如果你需要发送数据,那么可以往message里放一个Bundle类型的数据,如下

    //设置数据
    Bundle bundle = new Bundle();
    bundle.putInt("data1", 1);
    bundle.putString("data2", "数据二");
    message.setData(bundle);

在handleMessage中将数据取出

    //取出数据
    int data1 = msg.getData().getInt("data1");
    String data2 = msg.getData().getString("data2");

sendEmptyMessage()

如果你不需要设置数据,其实不用像上面例子那样麻烦,使用sendEmptyMessage()方法可以一行解决,相当于直接发个msg.what给handler了,可以做个对比。

	//方法1用三行代码
	Message myMessage = new Message();
	myMessage.what = UPDATE_TEXT;
	handler.sendMessage(myMessage);
	
	//方法2只用一行代码
	handler.sendEmptyMessage(UPDATE_TEXT)

Handler+TimerTask(3个步骤)

    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 1:
                    Log.e(TAG, "收到信息");
            }
            super.handleMessage(msg);
        }
    };
    Timer timer=new Timer();
    TimerTask task=new TimerTask(){
        @Override
        public void run() {
            Message message = new Message();
            message.what=1;
            handler.sendMessage(message);
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //延迟5秒发送消息
        timer.schedule(task,5000);
    }

Handler+Runnable(3个步骤)

    Handler handler = new Handler();
    Runnable mRunnable = new Runnable() {
        @Override
        public void run() {
            Log.e(TAG, "开始工作");
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //执行任务
        handler.post(mRunnable);
    }

简单的循环定时器

每隔一秒执行一次work()函数

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";
    
    Handler handler = new Handler();
    
    Runnable mRunnable = new Runnable() {
        @Override
        public void run() {
            work();
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //第一次调用work函数
        work();
    }
    
    //定义work函数
    public void work() {
        handler.postDelayed(mRunnable, 1000);
        Log.e(TAG, "收到信息");
    }
}

HandlerThread

关于HandlerThread的写了另外一篇,感兴趣的可以看下,把耗时的操作放到子线程中去,比如下载文件。而主线程通过收到子线程的各种动态,比如子线程开始下载、子线程下载完成来修改主页面的UI,可以弹个框提示,或者修改TextView文字等等…传送~传送


感谢
https://www.cnblogs.com/wlming/p/5553207.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章