天天看點

Android精通之Handler講解

版權聲明:未經部落客允許不得轉載
Android精通之Handler講解

一:簡介

【達叔有道】軟體技術人員,時代作者,從 Android 到全棧之路,我相信你也可以!閱讀他的文章,會上瘾!You and me, we are family !

二:重點

那麼什麼是Handler呢?為什麼要使用Handler呢?如何去實作呢?我們要了解Handler的工作原理在學Handler中,我們要知道并學習Handler,Looper,MessageQueue,Message等知識點。

消息循環機制

Handler

1.Looper循環者

2.Message消息

3.MessageQueue消息隊列(專門存放消息的)

一:在Handler學習中,主要了解Handler,Looper,MessageQueue,Message,Handler的作用将Message對象發送到MessageQueue中,Looper的作用像個發動機,從MessageQueue中取出資料交給Handler中的handleMessage方法。

Handler的方法以及使用

1.Handler.sendMessage()

2.Handler.post()

二:在onCreate中為主線程/UI線程,做一些輕量級的事情

主線程:

//建立一個Handler
final Handler handler = new Handler(){
  @Override
  public void handleMessage(Message msg) {
     super.handleMessage(msg);

  /*
    * 接到子線程發出來的消息,處理
    * */
     //處理消息
    Log.i(TAG,"handleMessage:" + msg.what);

      if (msg.what==110){
        textView.setText("huang");
        }
     }
};
           

子線程:

/*
* 有可能做大量耗時的操作
* 子線程
 * */
  new Thread(new Runnable() {
        @Override
        public void run() {
          try {
               Thread.sleep(10000);
              } catch (InterruptedException e) {
                e.printStackTrace();
          }

          /*
           * 通知UI更新
           * */
           handler.sendEmptyMessage(110); 
    }
}).start();
           

三: Handler

public class Handler extends Object

導入android.os.Handler

//子類
[AsyncQueryHandler][AsyncQueryHandler.WorkerHandler][HttpAuthHandler][SslErrorHandler]
           

處理程式:

處理Message與線程關聯的Runnable對象MessageQueue,第一,安排将要執行的消息和可執行的程式;二,在不用的線程執行任務。

排程消息和實作
sendMessage(Message msg)
sendMessageAtTime(Message,long)
sendMessageDelayed(Message,long)

sendEmptyMessage(int)
post(Runnable)
postAtTime(Runnable,log)
postDelayed(Runnable,Object,log)
//有很多方法還是要查官方文檔的好

SystemClock.uptimeMillis()為系統時間,給執行帶來額外的延遲

這裡了解一下源碼裡有
obtainMessage(參數)
what:int:要配置設定給傳回的Message.what字段的值。
arg1:int:要配置設定給傳回的Message.arg1字段的值。
arg2:int:要配置設定給傳回的Message.arg2字段的值。

//
發送消息延遲sendMessageAtTime
           

四://Two

public class MainActivity extends AppCompatActivity {
//主線程
}
           

在子線程中:

findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /*
                * 有可能做大量耗時的操作
                * 子線程
                * */
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            Thread.sleep(10000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                        /*
                        * 通知UI更新
                        * */
                    
                        Message message = Message.obtain();
                        message.what=1;
                        message.arg1=2;
                        message.arg2=3;
                        message.obj=MainActivity.this;
                        handler.sendMessage(message);

                        //定時任務
                        handler.sendMessageAtTime(message,SystemClock.uptimeMillis() + 5000);
                        handler.sendMessageDelayed(message,5000);

                        //運作可執行對象 消息來做
                        /*handler.post(new Runnable() {
                            @Override
                            public void run() {
                               執行代碼
                            }
                        });*/
                        final Runnable runnable = new Runnable() {
                            @Override
                            public void run() {
                                //執行代碼
                            }
                        };
                        handler.post(runnable);
                        runnable.run();
                        //定時任務
                        handler.postDelayed(runnable,5000);

                    }
                }).start();

            }
        });
           

五:

在子線程中先調用 Looper.prepare(),然後Handler handler = new Handler();//...//Looper.loop();

了解一下Looper

Looper為線程運作消息循環的類。線程預設情況下沒有與它們相關的消息循環;建立一個,在要運作循環的線程中調用prepare(),然後讓loop()處理,直到循環停止。

與消息循環的大多數互動是通過Handler類。

class LooperThread extends Thread {
public void run() {
     Looper.prepare();
     Handler mHandler = new Handler() {
             public void handleMessage(Message msg) {
                 
         }
     };
  Looper.loop();
}
}
           

六:強引用與弱引用

什麼是強引用和弱引用呢?對象的引用機制,使得程式能夠靈活地控制對象的生命周期。

強引用(StrongReference)

強引用可以了解為我們生活中必不可少的東西,如你的手機,當你空間不足時(占用空間),你也不會丢棄它,甯可抛出異常,在Java中最為常見的對象,隻要此引用存在并且沒有被釋放就不會被垃圾回收機制回收,隻有當釋放了,才可能回收。

弱引用(WeakReference)

弱引用即是生活中可有可無的東西,在Java中如果一個對象具備弱引用,那麼不管空間是否足夠都會被回收。

//建立一個對象
Person person=new Person();
WeakReference<Person> weakPerson=new WeakReference<Person>(person);
           

七:防止記憶體洩漏:

private static class MyHandler extends Handler{
 //WeakReference
 WeakReference<MainActivity> weakReference;
 public MyHandler(MainActivity activity){
  weakReference = new WeakReference<MainActivity>(activity);
 }
 public void handleMessage(Message msg){
  super.handleMessage(msg);
   if(weakReference.get() != null){
   } 
 }
}
           

當weakReference.get() != null,表示weakReference指向的對象activity沒有被回收。

如果此方法傳回為空的話,說明weakReference指向的對象activity已經被回收。

隻要指向還指向就不會被回收。

八:例子:

public class OneActivity extends Activity{
 private MyHandler mHandler=new MyHandler(this);
    public static class MyHandler extends Handler{
        
        public final WeakReference<OneActivity > mWeakReference;

        public DiglettHandler(OneActivity activity) {
            mWeakReference = new WeakReference<>(activity);
        }

     @Override
     public void handleMessage(Message msg) {
         super.handleMessage(msg);

         OneActivity activity = mWeakReference.get();
    }
 }
}
           
Ctrl+n 查找類
Ctrl+Alt+L 格式化代碼
Ctrl+d 複制行
Ctrl+y 删除行
           

版權聲明: 本部落格所有文章除特别聲明外,均采用 CC BY-NC-SA 3.0 許可協定。轉載請注明出處!