Android多线程编程<二>Handler异步消息处理机制之Message
1 package zst.message01; 2 import android.os.Bundle; 3 import android.os.Handler; 4 import android.os.Message; 5 import android.app.Activity; 6 import android.view.Menu; 7 import android.view.View; 8 import android.view.View.OnClickListener; 9 import android.widget.Button; 10 public class MainActivity extends Activity implements OnClickListener { 11 private Button button01; 12 13 public static final int ONE = 1; 14 15 16 //在主线程中创建的Handler对象,通常定义成static 17 public static Handler handler = new Handler(){ 18 @Override 19 public void handleMessage(Message msg) { 20 switch (msg.what) { 21 case ONE: 22 System.out.println("第一个Message-->" + "arg1=" + msg.arg1 + ",arg2=" + msg.arg2 + ",obj=" + msg.obj); 23 break; 24 default: 25 break; 26 } 27 } 28 29 30 }; 31 32 33 @Override 34 protected void onCreate(Bundle savedInstanceState) { 35 super.onCreate(savedInstanceState); 36 setContentView(R.layout.activity_main); 37 button01 = (Button) findViewById(R.id.button01); 38 button01.setOnClickListener(this); 39 } 40 41 @Override 42 public void onClick(View v) { 43 if(v.getId() == R.id.button01){ 44 //启动一个子线程 45 new Thread(new Runnable() { 46 47 @Override 48 public void run() { 49 //获得Message对象的第一种方法:使用构造函数创建Message,这种方法不推荐使用 50 Message message = new Message(); 51 message.arg1 = 100; 52 message.arg2 = 200; 53 message.what = ONE; //用于标识Message 54 message.obj = "Message_01"; 55 //发送Message到主线程中 56 handler.sendMessage(message); 57 58 } 59 60 }).start(); 61 62 } 63 64 65 } 66 }
1 //获得Message对象的第二种方法 2 Message message = Message.obtain(); 3 message.arg1 = 100; 4 message.arg2 = 200; 5 message.what = TWO; //用于标识Message 6 message.obj = "Message_02"; 7 handler.sendMessage(message);
public static Message obtain()方法的源码如下:
1 // sometimes we store linked lists of these things 2 /*package*/ Message next; 3 private static final Object sPoolSync = new Object(); 4 private static Message sPool; 5 private static int sPoolSize = 0; 6 private static final int MAX_POOL_SIZE = 50; 7 /** 8 * Return a new Message instance from the global pool. Allows us to 9 * avoid allocating new objects in many cases. 10 */ 11 public static Message obtain() { 12 synchronized (sPoolSync) { 13 if (sPool != null) { 14 Message m = sPool; 15 sPool = m.next; 16 m.next = null; 17 sPoolSize--; 18 return m; 19 } 20 } 21 return new Message(); 22 }
该方法将从全局消息槽中获得一个Message对象,从而避免再分配一块新的内存来创建Message对象。从上面可以看出,当全局消息槽中当前sPool不为null,则把sPool指向的Message对象赋给一个Message的临时引用,然后sPool再指向槽中的下一个Message,最后把临时引用m指向的Message对象返回给我们,这样全局消息槽中的Message可以得到重复使用,从而节省了一定的内存。如果sPool为null时,即消息槽为空,没有Message,这时才调用Message的构造函数来创建一个Message对象给我们。
1 //获得Message对象的第三种方法: 2 Message message = Message.obtain(handler); 3 message.arg1 = 100; 4 message.arg2 = 200; 5 message.what = THREE; //用于标识Message 6 message.obj = "Message_03"; 7 //发送Message 8 message.sendToTarget();
public static Message obtain(Handler h)方法的源码如下:
1 /** 2 * Same as {@link #obtain()}, but sets the value for the <em>target</em> member on the Message returned. 3 * @param h Handler to assign to the returned Message object's <em>target</em> member. 4 * @return A Message object from the global pool. 5 */ 6 public static Message obtain(Handler h) { 7 Message m = obtain(); 8 m.target = h; 9 return m; 10 }
从上面源码中可以看出:该方法内部还是通过public static Message obtain()方法从全局消息槽中返回一个Message对象给我们,然后把传入的Handler对象参数当成发送和接收该Message对象的目标Handler对象。由于该方法内部已经指定了处理Message对象的目标Handler对象,所以在发送Message消息时,不会再调用Handler对象的sendMessage(message)方法,而是直接使用Message对象的sendToTarget()方法发送。
1 //获得Message对象的第四种方法: 2 Message message = Message.obtain(handler, FOUR); 3 message.arg1 = 100; 4 message.arg2 = 200; 5 message.obj = "Message_04"; 6 message.sendToTarget();
public static Message obtain(Handler h, int what)方法的源码如下:
1 /** 2 * Same as {@link #obtain()}, but sets the values for both <em>target</em> and 3 * <em>what</em> members on the Message. 4 * @param h Value to assign to the <em>target</em> member. 5 * @param what Value to assign to the <em>what</em> member. 6 * @return A Message object from the global pool. 7 */ 8 public static Message obtain(Handler h, int what) { 9 Message m = obtain(); 10 m.target = h; 11 m.what = what; 12 return m; 13 }
1 /** 2 * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>, and <em>obj</em> 3 * members. 4 * @param h The <em>target</em> value to set. 5 * @param what The <em>what</em> value to set. 6 * @param obj The <em>object</em> method to set. 7 * @return A Message object from the global pool. 8 */ 9 public static Message obtain(Handler h, int what, Object obj) { 10 Message m = obtain(); 11 m.target = h; 12 m.what = what; 13 m.obj = obj; 14 return m; 15 }
public static Message obtain(Handler h, int what, int arg1, int arg2, Object obj)方法源码:
1 /** 2 * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>, 3 * <em>arg1</em>, <em>arg2</em>, and <em>obj</em> members. 4 * 5 * @param h The <em>target</em> value to set. 6 * @param what The <em>what</em> value to set. 7 * @param arg1 The <em>arg1</em> value to set. 8 * @param arg2 The <em>arg2</em> value to set. 9 * @param obj The <em>obj</em> value to set. 10 * @return A Message object from the global pool. 11 */ 12 public static Message obtain(Handler h, int what, 13 int arg1, int arg2, Object obj) { 14 Message m = obtain(); 15 m.target = h; 16 m.what = what; 17 m.arg1 = arg1; 18 m.arg2 = arg2; 19 m.obj = obj; 20 return m; 21 }
public static Message obtain(Handler h, int what, int arg1, int arg2)方法源码:
1 /** 2 * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>, 3 * <em>arg1</em>, and <em>arg2</em> members. 4 * 5 * @param h The <em>target</em> value to set. 6 * @param what The <em>what</em> value to set. 7 * @param arg1 The <em>arg1</em> value to set. 8 * @param arg2 The <em>arg2</em> value to set. 9 * @return A Message object from the global pool. 10 */ 11 public static Message obtain(Handler h, int what, int arg1, int arg2) { 12 Message m = obtain(); 13 m.target = h; 14 m.what = what; 15 m.arg1 = arg1; 16 m.arg2 = arg2; 17 return m; 18 }
1 Message message = Message.obtain(handler, EIGHT, 100, 200); 2 message.obj = "Message_08"; 3 Bundle b = new Bundle(); 4 b.putString("name", "张三"); 5 message.setData(b); 6 message.sendToTarget();