当前位置:天才代写 > tutorial > 安卓教程 > Android消息机制之Handler

Android消息机制之Handler

2021-02-04 12:55 星期四 所属: 安卓教程 浏览:539

Android为何要出示Handler

Android提议大家不要在UI进程中实行用时实际操作,由于这非常容易造成ANR出现异常(在Android源代码中我们可以见到,UI假如对客户的实际操作超出5秒无响应,便会报ANR出现异常)。因而,一些用时实际操作都是会在子进程中进行。在我们在子进程中获得了数据信息,要将其表明到UI中,要是没有Handler,这将难以进行。因而,Android往往出示Handler,便是为了更好地处理子进程浏览UI的难题。
为何Android不允许在子进程中浏览UI呢?显而易见那样做不安全,线程同步浏览UI是不安全的(学过电脑操作系统的朋友应当都掌握进程相互独立,这儿我不详解了)。有些人便会讲了,能够根据设定信号量来处理啊。这中方式不是不能,由于这类方式会使浏览UI的逻辑性复杂化;次之这会减少UI的浏览高效率。而应用Handler就非常简单高效率。Handler是同一个Message来通信的。

 

Handler的使用方法

应用Handler时,必须重写handleMessage方式,在handleMessage中接纳新进程发过来的Message,并做相对的解决。在新进程中则是根据Message来传送信息,Message中通常也带上着必须传送的数据信息及其信息的种类。也要注重一点,假如当今进程有Looper就不用实行Looper.prepare(),要是没有,就必须在新进程内实行Looper.prepare(),不然会出错。实际应用编码以下:

 public class MainActivity extends AppCompatActivity {
     private Handler mHandler=new Handler(){
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what)
             {
                 case 1:
                     //实行必须改动的UI实际操作
                     break;
                 default:
                     break;
             }
         }
     };
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
 
         new Thread(new Runnable() {
             @Override
             public void run() {//在新进程中实行用时实际操作
 
                 //假如当今进程有Looper就不用实行Looper.prepare();
                 Looper.prepare();
                 try {
                     Thread.sleep(1000);//睡眠质量一秒
                 } catch (InterruptedException e) {
                     e.printStackTrace();
                 }
 
                 //实际操作进行以后根据推送Message,来通告Handler开展UI实际操作
                 Message msg=new Message();
                 msg.what=1;
 
                 /*这些是伪代码,value 是想根据Message传送的值
                 Bundle data=new Bundle();
                 data.putSerializable("key",value);
                 msg.setData(data);
 
                 */
                 //设定好数据信息后,推送信息
                 mHandler.sendMessage(msg);
             }
         }).start();
     }
 
 }

Handler的內部体制

Handler建立的时候会选用Looper来创建信息循环系统。因此 ,当今进程务必要有Looper。当Handler建立进行后,其內部的Looper及其MessageQueue既能够和Handler一起协调工作了。Handler根据sendMessage将信息发给內部的MessageQueue,而MessageQueue会启用queue.enqueueMessage(msg, uptimeMillis)方式,它的源代码以下:

 boolean enqueueMessage(Message msg, long when) {
         if (msg.target == null) {
             throw new IllegalArgumentException("Message must have a target.");
         }
         if (msg.isInUse()) {
             throw new IllegalStateException(msg   " This message is already in use.");
         }
 
         synchronized (this) {
             if (mQuitting) {
                 IllegalStateException e = new IllegalStateException(
                         msg.target   " sending message to a Handler on a dead thread");
                 Log.w(TAG, e.getMessage(), e);
                 msg.recycle();
                 return false;
             }
 
             msg.markInUse();
             msg.when = when;
             Message p = mMessages;
             boolean needWake;
             if (p == null || when == 0 || when < p.when) {
                 // New head, wake up the event queue if blocked.
                 msg.next = p;
                 mMessages = msg;
                 needWake = mBlocked;
             } else {
                 // Inserted within the middle of the queue.  Usually we don't have to wake
                 // up the event queue unless there is a barrier at the head of the queue
                 // and the message is the earliest asynchronous message in the queue.
                 needWake = mBlocked && p.target == null && msg.isAsynchronous();
                 Message prev;
                 for (;;) {
                     prev = p;
                     p = p.next;
                     if (p == null || when < p.when) {
                         break;
                     }
                     if (needWake && p.isAsynchronous()) {
                         needWake = false;
                     }
                 }
                 msg.next = p; // invariant: p == prev.next
                 prev.next = msg;
             }
 
             // We can assume mPtr != 0 because mQuitting is false.
             if (needWake) {
                 nativeWake(mPtr);
             }
         }
         return true;
     }

根据源代码,大家发觉,queue.enqueueMessage(msg, uptimeMillis)将信息放进了MessageQueue里。Looper则会一直解决MessageQueue中的信息。



 

    关键字:

天才代写-代写联系方式