Handler简介
Android 中规定,只允许UI线程修改Activity中的UI组件。当程序第一次启动的时候,就启动了一条主线程(Main Thread),通常被称为UI线程。如果新启动的线程想要改变界面组件里的属性值,则要借助Handler的消息传递机制。
程序实例:
//布局文件仅含有一个ImageView组件。
1 public class MainActivity extends AppCompatActivity { 2 3 4 5 6 7 int[] imageIds = new int[]{ 8 9 R.drawable.java,10 11 R.drawable.ee,12 13 R.drawable.ajax,14 15 R.drawable.xml,16 17 R.drawable.classic18 19 };20 21 int currentImageId = 0;22 23 24 25 @Override26 27 protected void onCreate(Bundle savedInstanceState) {28 29 super.onCreate(savedInstanceState);30 31 setContentView(R.layout.activity_main);32 33 34 35 final ImageView show = (ImageView) findViewById(R.id.show);36 37 final Handler myHandler = new Handler() {38 39 @Override40 41 // import android.os.Handler;42 43 public void handleMessage(Message msg) {44 45 if (msg.what == 0x1233) {46 47 show.setImageResource(imageIds[currentImageId++ % imageIds.length]);48 49 }50 51 }52 53 };54 55 56 57 new Timer().schedule(new TimerTask() {58 59 @Override60 61 public void run() {62 63 myHandler.sendEmptyMessage(0x1233);64 65 }66 67 }, 0, 1200);68 69 }70 71 }
TimerTask对象本质是启动一条新线程,因此不能对UI组件进行更改。
程序通过Timer方法定时传递一个空的消息(0x1233)给myHandler,然后主线程中handleMessage来处理该消(0X1233)
Handler 工作原理
- Message: Handler接受和处理的消息对象。
- Looper: 每个线程只有一个Looper,它负责管理MessageQueue,会不断从MessageQueue中取出消息,并将消息分给对应的Handler处理。
- MessageQueue: 由Looper负责管理。它采用先进先出的方式来管理Message。
- Handler: 他能把消息发送给Looper 管理的MessageQueue,并负责处理Looper 分给它的消息。
在线程中使用Handler的步骤:
- 调用Looper 的 preper() 方法为当前线程创建Looper对象,创建Looper对象时,它的构造器会创建与之配套的MessageQueue。
- 有了Looper后,创建Handler子类的实例,重写handlrMessage()方法,该方法负责处理来自其他线程的消息。
- 调用Looper的loop()方法启动Looper。
实例:
//布局文件中包含一个按键和一个文本框
//其中按键中包含属性onClick = "cal" cal 为activity中声明的方法。
1 2 3 public class MainActivity extends AppCompatActivity { 4 5 6 7 static final String UPPER_NUM = "upper"; 8 9 EditText etNum; 10 11 CalThread calThread; 12 13 14 15 @Override 16 17 protected void onCreate(Bundle savedInstanceState) { 18 19 super.onCreate(savedInstanceState); 20 21 setContentView(R.layout.activity_main); 22 23 24 25 etNum = (EditText) findViewById(R.id.etNum); 26 27 calThread = new CalThread(); 28 29 calThread.start(); 30 31 } 32 33 34 35 public void cal(View source){ 36 37 Message msg = new Message(); 38 39 msg.what = 0x1233; 40 41 Bundle bundle = new Bundle(); 42 43 bundle.putInt(UPPER_NUM, Integer.parseInt(etNum.getText().toString())); 44 45 msg.setData(bundle); 46 47 calThread.mHandler.sendMessage(msg); 48 49 } 50 51 52 53 private class CalThread extends Thread { 54 55 56 57 public Handler mHandler; 58 59 @Override 60 61 public void run() { 62 63 Looper.prepare(); 64 65 mHandler = new Handler(){ 66 67 @Override 68 69 public void handleMessage(Message msg) { 70 71 if(msg.what == 0x1233){ 72 73 int upper = msg.getData().getInt(UPPER_NUM); 74 75 Listnums = new ArrayList (); 76 77 outer: 78 79 for(int i = 2; i <= upper; i++){ 80 81 for(int j =2; j <= Math.sqrt(i); j++){ 82 83 if(i != 2 && i % j == 0){ 84 85 continue outer; 86 87 } 88 89 } 90 91 nums.add(i); 92 93 } 94 95 Toast.makeText(MainActivity.this, nums.toString(), 96 97 Toast.LENGTH_LONG).show(); 98 99 }100 101 }102 103 };104 105 Looper.loop();106 107 }108 109 }110 111 }