概述
在Android开发中,有主线程(UI线程)和工作线程(Worker线程)之分,两个线程是相互独立的,并不能相互访问(主线程主要负责UI的更新,不能进行耗时的操作,工作线程主要负责耗时的操作,但不能进行UI的更新),所以要在两个线程之间进行数据传递,就需要Handler作为传递数据的桥梁。每一个Handler对象,都与独立的线程以及线程的消息队列有关。本文仅供学习分享使用。
Handler逻辑
- Looper会从消息队列中,将消息对象取出。
- Looper会找到Message对象对应的Handler对象。
- Looper会调用Handler对象的handleMessage方法,用于处理对象。
涉及知识点
- Android线程:有主线程(UI线程)和工作线程(Worker线程)
- Handler 允许发送和处理与线程相关的消息对列的可运行对象。
- handleMessage (Message msg) 必须在子类进行重写的的处理消息的方法。
- sendMessage (Message msg) 发送消息方法。
- obtainMessage () 用于从全局消息池中获取一个新的对象。
- Message 定义一个用于描述和任意数据对象的消息,此消息可以发送到Handler对象。
- what 消息对象的标识符。
- arg1,arg2 用于存储整型数据的值。
- obj 可以接受任意的对象,用于存储消息的对象的值。
- Thread 线程是一个可并发执行的单元。重写run方法来处理线程内容。
Handler原理
如下图所示:
核心代码
创建一个内部类继承Handler
1 /* 2 创建一个内部Handler类 3 */ 4 class NetworkHandler extends Handler{ 5 6 @Override 7 public void handleMessage(Message msg) { 8 Log.i("DemoHandler", "run: thread id2="+Thread.currentThread().getName()); 9 String s = (String) msg.obj; 10 txtInfo.setText(s); 11 } 12 }
创建一个内部类,继承Thread
1 /* 2 创建一个线程内部类 3 */ 4 class NetworkThread extends Thread{ 5 @Override 6 public void run() { 7 Log.i("DemoHandler", "run: thread id1="+Thread.currentThread().getName()); 8 //模拟网络获取,当执行时休眠2秒钟 9 try { 10 Thread.sleep(2*1000); 11 } catch (InterruptedException e) { 12 e.printStackTrace(); 13 } 14 //通过handler将线程数据,发送到消息队列中 15 //1. Looper将消息队列中的消息对象取出。 16 //2. Looper找到消息对象对应的Handler对象 17 //3. Looper将会调用handler对象中的handleMessage(Msg)方法,处理对象 18 String s="这是一个线程中的数据"; 19 Message msg=handler.obtainMessage(); 20 msg.what=1; 21 msg.obj=s; 22 handler.sendMessage(msg); 23 } 24 }
启动线程
1 public void click_me(View v){ 2 //点击事件中启动一个线程 3 Thread thread=new NetworkThread(); 4 thread.start(); 5 }
调试输出信息(两个分属不同的线程)
1 04-25 22:56:37.424 18601-18786/com.hex.demohandler I/DemoHandler: run: thread id1=Thread-4 2 04-25 22:56:39.425 18601-18601/com.hex.demohandler I/DemoHandler: run: thread id2=main 3 04-25 22:56:55.491 18601-18800/com.hex.demohandler I/DemoHandler: run: thread id1=Thread-5 4 04-25 22:56:57.492 18601-18601/com.hex.demohandler I/DemoHandler: run: thread id2=main
备注
大多数情况下,在worker thread中修改view是不可以的,小部分是可以的,如progressbar 。