AndroidはHandlerを用いてメッセージ配信メカニズムを実現している(ゼロ)

5863 ワード

講演前、AsyncTaskの文章.私たちは最後に話した.AsyncTask Handler非同期メッセージ処理メカニズムを利用して、操作結果です.Messageを使用してメインスレッドに戻り、UI更新スレッドを実行します.
私たちの日常的な開発作業では、Handlerのようなものが私たちの間でよく使われています.そして、Handlerの主な役割は何ですか.
Handlerの主な役割は、メッセージ(メッセージは、私たちがしたいUIの更新であってもよいし、データベースの操作など、他の見えない操作であってもよい)の非同期処理メカニズムである.みんなが非同期の概念を知っていると信じています.
簡単に言えば、
1)プログラムの観点から,ある行のコードを実行すると,非同期要求(メッセージ)が送信される.プログラムはこの行のコードで待ち続ける必要はありません.実行後のコードを続行できます.
2)ユーザの観点から,ユーザはメッセージを送信する.何もしないで、そこで愚かで、他のことをすることができます.対応するメッセージが処理されると、コールバックメカニズムによって対応する結果が処理される.
だから.AndroidのHandlerのメッセージ非同期処理メカニズムは、ユーザーにより合理的で友好的なユーザー体験を提供することができます.
もちろんです.AndroidはHandlerで実現しています.その他のプラットフォーム環境.独自の非同期実現メカニズムもあり、原理は同じで、名前が異なるだけです.
Androidの開発をしている以上.では、私たちはHandlerの使い方をよく勉強しなければなりません.Handlerの後に隠されたコードアーキテクチャを探ってみましょう.
まず.私たちはやはり簡単なサンプルから始めます.Handlerの使い方を学びましょう.
コードは次のようになります.
public class MainActivity extends ActionBarActivity {

    private static final int MSG_ID_1 = 1;
    private static final int MSG_ID_2 = 2;

    private Handler mHandler = new Handler() {

        public void handleMessage(Message msg) {
            switch (msg.what) {
            case MSG_ID_1:
                Log.v("Test", "Toast called from Handler.sendMessage()");
                break;
            case MSG_ID_2:
                break;
            }
            
        }
    };
    
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Message message = mHandler.obtainMessage();
        message.what = MSG_ID_1;
        mHandler.sendMessage(message);
    }
}

プログラムを起動するとLogCatには次のような情報が印刷されていることがわかります.
10-27 15:13:21.382: V/Test(9618): Toast called from Handler.sendMessage()

これは私たちがhandlerのhandleMessageでmsg.what=MSG_に対してID_1の場合は処理します.
この簡単な例から、Handlerの使用手順をまとめることができます.次のステップがあります.
1)Handlerオブジェクトを作成します.コードなどのhandleMessage(Message msg)メソッドを実装します.
private Handler mHandler = new Handler() {

handleMessageメソッドを実装するには一歩.Messageオブジェクトが取得されることがわかります.
Messageオブジェクトにはいくつかのパラメータがカプセル化されています.よく使うのは次のようなものです.
a)whatパラメータ:これはint値であり、メッセージを区別するために使用されるIDであることが多い.例えば、サンプルではMSG_ID_1メッセージを作成するときにmsg.whatに値を割り当てます.
b)objパラメータ:これはObjectオブジェクトです.
objパラメータにより,メッセージにどのオブジェクトを割り当ててhandleMessageで処理することができ,これもHandlerが非同期処理でデータを渡す方法である.
c)arg 1,arg 2などのパラメータ:上記a),b)の2つのパラメータは私たちが最もよく使うMessageのパラメータであり,基本的にはこの2つのパラメータが必要で十分であるが,Messageは他のフィールドを提供しているだけである.例えばargXなど.つまりargumentsの略です.arg 1とarg 2はAndroidが提供するいわゆるlow-costの変数であり、一般的にはint値を設定するために使用される.
d)dataパラメータ、dataパラメータはBundleタイプのオブジェクトであり、setDataメソッドでbundleを設定することができる.Activity間でIntentを使用してデータを転送するのと同じように使用します.
2)Handlerオブジェクトを作成した後、2番目のステップでMessageオブジェクトを作成する必要があります.Messageオブジェクトを作成するには、次の2つの方法があります.
2.1)次のような新しいオブジェクトを直接作成します.
Message msg = new Message()

2.2)Handler.obtainMessage()メソッド,すなわち上のコードで使用される方式を利用する.たとえば、次のようになります.
Message message = mHandler.obtainMessage();

一般的には、別の方法をお勧めします.どうしてですか.
メッセージ・プールのようなオブジェクトがMessageの内部で維持されているため、Handlerを使用してMessageを配布する場合、処理が完了すると、Messageオブジェクトがすぐに破棄されるとは限りません.メッセージプールに格納される可能性があります.
HandlerのobtainMessageメソッドを使用すると、Handlerはメッセージプールから既存のオブジェクトを取得します.情報を初期化します.これにより、オブジェクトを再作成したり、メモリを浪費したりする必要はありません.組み込みアプリケーションでは、メモリが非常に大きくない場合、パフォーマンスの最適化です.
Messageを作成する際にmsg.whatを付与することができ,handleMessageでHandlerがこのメッセージの用途や目的を推定できるようにすることを目的とする.
もちろん、ニーズによって、必ず異なる処理があります.これで詳細を詳しく分析した.
3)メッセージ(Message)が作成されると,HandlerのsendMessageを用いてメッセージを送信することができ,その後.このメッセージはhandlerによってキャプチャされ、処理されます.
次に、このサンプルを拡張します.コードは次のようになります.
public class MainActivity extends ActionBarActivity {

    private static final int MSG_ID_1 = 1;
    private static final int MSG_ID_2 = 2;

    private Handler mHandler = new Handler() {

        public void handleMessage(Message msg) {
            switch (msg.what) {
            case MSG_ID_1:
                Log.v("Test", "Toast called from Handler.sendMessage()");
                break;
            case MSG_ID_2:
                String str = (String) msg.obj;
                Log.v("Test", str);
                break;
            }
            
        }
    };
    
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Message message = mHandler.obtainMessage();
        message.what = MSG_ID_1;
        mHandler.sendMessage(message);
        
        Message msg2 = mHandler.obtainMessage();
        msg2.obj = "I'm String from Message 2";
        msg2.what = MSG_ID_2;
        mHandler.sendMessage(msg2);
    }
}

その結果は次のようになります.
10-27 15:35:19.168: V/Test(12135): Toast called from Handler.sendMessage()
10-27 15:35:19.168: V/Test(12135): I'm String from Message 2

ここから、私たちは見ることができます.Objパラメータを用いて,StringオブジェクトをhandleMessageに渡した.
sendMessageメソッドに加えて、メッセージを送信する場合、Handlerは、例えば、以下の方法を使用することができる.
public final boolean post(Runnable r)
    {
       return  sendMessageDelayed(getPostMessage(r), 0);
    }

    public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
        MessageQueue queue = mQueue;
        if (queue == null) {
            RuntimeException e = new RuntimeException(
                    this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
            return false;
        }
        return enqueueMessage(queue, msg, uptimeMillis);
    }

実際には、sendMessageでもpostメソッドでも、sendMessageAtTimeメソッドを呼び出すことで、対応するMessageオブジェクトをMessageQueueに入れます.
では、なぜMessageQueueに置くのでしょうか.MessageQueueに入れるとどうやってHandlerのhandleMessageに戻るのでしょうか?
次の文章.私たちはまた勉強を続けます.
この記事では、Handlerの使い方、簡単な例を簡単に紹介します.入門だけです.
終わります.
本文のブログのオリジナルの文章、ブログ、同意を得ないで、転載してはいけません.