Handler非同期メッセージメカニズムのインスタンス解析


いくつかの簡単な例でHandlerに関する知識点を整理し、後で調べるのに便利で、みんなが早くこの知識点をマスターするのに便利です.
名詞解釈:Messageはスレッド間で伝達されるメッセージであり、内部で少量の情報を携帯し、異なるスレッド間でデータを交換することができる.MessageQueueはメッセージキューで、Handlerによって送信されたすべてのメッセージを格納するために主に使用されます.このメッセージはメッセージキュー内で処理されるのを待っています.Handlerは、主にメッセージの送信および処理に使用される処理者である.送信メッセージは一般にhandlerのsendMessage()を使用し、処理メッセージはhandleMessage()を呼び出す.LooperはスレッドごとにMessageQueueの執事であり,loop()メソッドを呼び出すと無限ループに入り,MessageQueueにメッセージが存在することを発見するたびに取り出しhandleMessage()メソッドに渡す.
注意:各スレッドにはLooperオブジェクトとMessageQueueが1つしかありません.Handlerは作成時に存在するスレッドに依存する.
コード例の原理を使ってみましょう.
ターゲットシーン:メインスレッドはサブスレッドにメッセージを送信し、サブスレッドはメインスレッドのメッセージを受信した後、メインスレッドに通知を送信し、メインスレッドはUIを更新します.
実装手順:1,メインスレッドはサブスレッドにメッセージを送信し,サブスレッドはメッセージを受信する.サブスレッド受信メッセージである以上、handleMessageはサブスレッドにあることを示す.Handlerはサブスレッドに依存する.コードは次のとおりです.
 private LoopThread loopThread;  
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ...

        //     Runnable      
        new Thread(loopThread = new LoopThread()).start();
    }

    /**
     *     Runnable            
     */
    public class LoopThread implements Runnable {
        public Handler mHandler = null;
        @Override
        public void run() {
            Looper.prepare();
            mHandler = new Handler() {
                public void handleMessage(Message msg) {
                    handleMsgAndTodo(msg);
                }
            };
            Looper.loop();
        }
    }

Runnableインタフェースを実装したサブスレッドで、handlerがインスタンス化され、handleMessageを介してメッセージが受信されます.ここにLooperがありますprepare();ロoperとloop();説明は、サブスレッド自体が新しく作成したメッセージ執事looper(メインスレッドにはデフォルトで独自のlooperが作成されています)です.プライマリ・スレッドからメッセージを送信すると、直接呼び出すことができます.mHandler.sendEmptyMessage(1);”(LoopThreadはRunnableインタフェースを実現したクラスである).
次に,サブスレッド受信処理メッセージとメインスレッド処理メッセージの両方がhandleMsgAndTodo(msg)メソッドにカプセル化される.コードは次のとおりです.
    /**
     *            
     * @param msg
     */
    private void handleMsgAndTodo(Message msg) {
        switch (msg.what) {
            case 0:
                showMessageTv.setText("2---      UI");
                Log.d("           ", "    ");
                break;
            case 1:
                Log.d("           ", "    ");
                handler.sendEmptyMessage(0);
                Log.d("           ", "    ");
                break;
            default:
                break;
        }
    }

ホストからのメッセージmsg.what=1,ここでメッセージを受信するとすぐにメインスレッドにメッセージmsgを送信する.0であることに注意してmHandlerやloopThreadではなくhandlerを使用します.mHandler,ここでhandlerはメインスレッドでインスタンス化されている.コードは次のとおりです.
    /**
     *         UI
     */
    Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            handleMsgAndTodo(msg);
        }
    };

ここでhandlerはメインスレッドに依存しており,UIを直接更新することができる.また,非同期メッセージメカニズムに基づいたいくつかの方法もある.例えば、サブスレッドでUIを更新する例:
    /**
     *   hander.post()       UI
     */
    private void handerpost() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                //...           ,                  
//               handler.sendEmptyMessage(0);

 //            UI          handleMessage()  UI——hander.post(),view.post(), runOnUiThread(),                  。
//                handler.post(new Runnable() {
//                  @Override
//                  public void run() {
//                  showMessageTv.setText("1---      UI");
//                    }
//                });

//     new Handler(Looper.getMainLooper())    handleMessage()         UI      ,  Handler          。
        Handler handler2 = new Handler(getMainLooper()){
                @Override
                public void handleMessage(Message msg) {
                   super.handleMessage(msg);
                   showMessageTv.setText("3---      UI");
                }
         };
                handler2.sendEmptyMessage(0);
        }
    }).start();
  }

上記のいくつかのコードの方法は、プライマリスレッドのhandlerを呼び出してメッセージ更新UIを送信することにほかならない.サブスレッドでインスタンス化されたもう1つのhandler 2も、メインスレッドのlooper、すなわちメインスレッドと同じメッセージキューを維持することを共用しているため、メインスレッドでUIを更新することに相当する.
自己理解:どのスレッドがメッセージを受信するかは、そのスレッドでhandleMessageを呼び出すためにHandlerをインスタンス化します.メインスレッドがサブスレッドにメッセージを送る場合はLooperを使用する必要がある.prepare()とLooper.loop()は、handleMessage()を呼び出すために、Handlerをサブスレッドにインスタンス化する.
サブスレッドではnew Handler(Looper.getMainLooper()はそのhandleMessage()メソッドのことがメインUIスレッドで処理されていることを示し,このHandlerは実はメインスレッドにバインドされている.hander.post(),view.post()、runOnUI Thread()のいくつかの方法は、サブスレッドでUIを更新することは、メインスレッドでhandleMessage更新UIを呼び出すことに等しい.その原理は、非同期メッセージ処理メカニズムによって実現される.
Handler+ThreadとHandlerThreadの違い:HandlerThreadはメッセージキューを含むLooperとThreadをカプセル化した書き方であり、サブスレッドの受信したメッセージ処理に直接時間のかかるタスクを処理することができる.
Handler+ThreadとAsyncTaskの長所と短所:1,AsyncTaskは、Androidが提供する軽量級の非同期クラスであり、AsyncTaskクラスを直接継承して非同期操作を行い、インタフェースフィードバックの現在の非同期実行の程度(インタフェースによってUIの進捗更新を実現できる)を提供し、最後に実行の結果をUIメインスレッドにフィードバックする.使用の利点:簡単で、速い(コード上軽量であるが、実際にはhandlerよりもリソースを消費する)、プロセス制御可能な使用の欠点:複数の非同期操作を使用し、UI変更を必要とする場合、複雑になる.2,Handler+Threadは構造がはっきりしていて、機能定義がはっきりしていて、複数のバックグラウンドタスクに対して、簡単で、はっきりした使用の欠点:単一バックグラウンドの非同期処理の時、コードが多すぎて、構造が複雑すぎる(相対性)