1. 程式人生 > >HandlerThread的用法與自定義HandlerThread(2)

HandlerThread的用法與自定義HandlerThread(2)

自定義HandlerThread

(其實HandlerThread本身也沒有多少程式碼,不到200的程式碼很容易看完的,但是裡面所使用的類還要繼續往下看,然後就沒有然後了)

介面

介面和使用方法在上一節已經放出

簡單的自定義

 class MyLooperThread extends Thread implements Handler.Callback {
        public Looper looper = null;

        public Looper getLooper() {
        //下面的程式碼是是從HandlerThread抄來的————標記1
/* synchronized (this) { while (isAlive() && looper == null) { try { wait(); } catch (InterruptedException e) { } } }*/ return looper; } @Override public
void run() { Looper.prepare(); looper = Looper.myLooper(); Looper.loop(); handler.sendEmptyMessage(3); } @Override public boolean handleMessage(Message msg) { handler.sendEmptyMessage(1); return false; } }

其實裡面很簡單,Callback依舊可以沒有

 Looper.prepare();
 looper = Looper.myLooper();

 Looper.loop();

裡面的順序不能搞錯只有先prepare才能通過myLooper獲取,一旦進入loop迴圈後面的程式碼就無法執行

handler.sendEmptyMessage(3);

只有當looper.quit()後loop()方法後面的程式碼才能執行
另外在標記1的地方當handlerThread在start()後無法立即獲取(有一些ms單位的時間吧),這裡通過幾個button來觸發獲取looper的事件

 btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
            Handler handler1 = new Handler(myLooper.getLooper(), myLooper);
            //執行在MyLooperThread裡面的looper
                handler1.sendEmptyMessage(1);
            }
        });

話說原始碼是怎麼設計的呢?
就是上面標記的部分的那段程式碼

 synchronized (this) {
            while (isAlive() && mLooper == null) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
        }

一個wait就讓UI執行緒ANR了,
然後在run裡面

synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }

好了一個notifyAll又讓所有等待該執行緒的執行緒(Ui執行緒)執行起來了,不得不說Ui執行緒有那麼點時間是延遲的。(說錯請噴)

完整程式碼

(內網不能傳檔案,只能粘了)介面是在上一節有的,之貼上2個Activity的程式碼了
主Activity程式碼:TestHandlerActivity

package com.holdfoot.looper;

import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.TextView;

import java.util.Random;

public class TestHandlerActivity extends AppCompatActivity {

    private Button btn2, btn_start, btn;
    private TextView tv, tv1;
    private MyHandlerThread handlerThread;
    private Handler handler, handlerUi;
    private int i;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        System.out.println("onCreate CurrentThread=" + Thread.currentThread().getName());
        btn2 = (Button) findViewById(R.id.btn2);
        btn_start = (Button) findViewById(R.id.btn_start);
        btn = (Button) findViewById(R.id.btn);

        tv = (TextView) findViewById(R.id.tv);
        tv1 = (TextView) findViewById(R.id.tv1);

        //
        handlerThread = new MyHandlerThread("myHandler");
        handlerThread.start();
        handler = new Handler(handlerThread.getLooper(), handlerThread);

        handlerUi = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                tv.setText("msg.what=" + msg.what);
                super.handleMessage(msg);
            }
        };


        MyRunnable runnable=new MyRunnable();

        handler.postDelayed(runnable,500);
        btn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                handler.sendEmptyMessage(1);//handler——>handlerThread——>handlerUi
            }
        });


        btn_start.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(TestHandlerActivity.this, LooperThreadActivity.class));
            }
        });
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                tv1.setText("每個應用通常都有不止一個執行緒,無論是網路通訊還是後臺服務," +
                        "這樣就需要大量的建立執行緒,所以乾脆google就直接建立了HandlerThread," +
                        "通過該Thread人們可以將自己的程式執行在裡面而不必每次都建立執行緒," +
                        "正是由於該Thread裡面的Looper才使得不用建立多個Thread,而讓每個Thread都能執行到," +
                        "說白了類似執行緒池的概念,但只有一個執行緒,一個執行緒包含一個任務池");
            }
        });
    }
    class  MyRunnable implements Runnable{
        @Override
        public void run() {
            handlerUi.sendEmptyMessage(i);
            i=i+2;
            handler.postDelayed(MyRunnable.this,1000);
        }
    }


    @Override
    protected void onDestroy() {
        handlerThread.quit();
        super.onDestroy();
    }


    private class MyHandlerThread extends HandlerThread implements Handler.Callback {
        public MyHandlerThread(String name) {
            super(name);
        }

        @Override
        public boolean handleMessage(Message msg) {
            System.out.println("handleMessage CurrentThread=" + Thread.currentThread().getName());
            handlerUi.sendEmptyMessage(i);
            i=i+10;
            return false;
        }



        @Override
        protected void onLooperPrepared() {

            super.onLooperPrepared();
        }

    }
}

LooperThreadActivity

package com.holdfoot.looper;

import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;


public class LooperThreadActivity extends AppCompatActivity {

    private Handler handler;
    private TextView tv;
    private Button btn, btn1, btn0;
    private MyLooperThread myLooper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_looper_thread);

        tv = (TextView) findViewById(R.id.tv);
        btn = (Button) findViewById(R.id.btn);
        btn1 = (Button) findViewById(R.id.btn1);
        btn0 = (Button) findViewById(R.id.btn0);

        handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case 1:
                        tv.setText("在looper裡面接受到了");
                        break;
                    case 3:
                        tv.setText("looper.quit()之後的的動作");
                        break;
                }
                super.handleMessage(msg);
            }
        };
        btn0.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                myLooper = new MyLooperThread();
                myLooper.start();
            }
        });
    /*    if(myLooper.getLooper()==null){
            Log.d("tag","====null");

        }
        if(myLooper.getObj()==null){
            Log.d("tag","obj==null");
        }
*/
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Handler handler1 = new Handler(myLooper.getLooper(), myLooper);//執行在MyLooperThread裡面的looper
                handler1.sendEmptyMessage(1);
            }
        });
        btn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                myLooper.getLooper().quit();
            }
        });
    }

    class MyLooperThread extends Thread implements Handler.Callback {


        public Looper looper = null;
        public Handler mHandler = null;

        public Looper getLooper() {
          /*  synchronized (this) {
                while (isAlive() && looper == null) {
                    try {
                        wait();
                    } catch (InterruptedException e) {
                    }
                }
            }*/
            return looper;
        }

        @Override
        public void run() {
            Looper.prepare();
            looper = Looper.myLooper();

            Looper.loop();
            handler.sendEmptyMessage(3);
        }

        @Override
        public boolean handleMessage(Message msg) {

            handler.sendEmptyMessage(1);
            return false;
        }

    }

    @Override
    protected void onDestroy() {
        if (myLooper != null) {
            myLooper.getLooper().quit();
        }
        super.onDestroy();
    }
}