AndroidのメッセージメカニズムHandler

4870 ワード

AndroidのメッセージメカニズムはHandlerの実行メカニズムです.
まず以下の3つの問題を理解し,Handlerに対する深い認識に役立つ.
1.なぜハンドラーがいるのか.
主にAndroidがUIを非プライマリスレッドで操作することを許さないため、サブスレッドはネットワークにアクセスして時間のかかる演算をした後、私たちが望んでいるデータを得たが、気まずいことにサブスレッドがデータを握っていたが、UIを変更する権限がなかった.このときHandlerは天使の翼を伸ばした…Handlerはサブスレッドからデータを受け取ってメインスレッドにデータを渡し、メインスレッドはUIを更新した.
余談
ViewRootImplのcheckThreadメソッドはUI操作に対してスレッドの検証を行いましたメインスレッドでなければ「Only the original thread that created a view hierarchy can touch its views」中国語翻訳は「越板代行」です
2.だからHandlerは何に使いますか.
AndroidシステムにおけるHandlerの役割は非常に重要であり,サブスレッドがUIを更新できないという矛盾を解決し,メッセージの送信と処理を行うことができる.
これは皇上だけが聖旨を出すことができるようなものだが、皇上は具体的なことをしない.理由はみんな知っているからだ.皇上が管理しているのは江山社稷だ.もし彼が具体的なことをしたら、国は基本的に終わるだろう.だからこれらの事は各大臣が実施するしかなくて、大臣达はそれぞれの州府県役所の事务の过程の中で新しい事件の情报を得て、これらの情报は天下の人にすべてどのようにすることを知っていて、また圣旨を出して天下に告げることができなくて、この事は皇上だけがすることができます.この時宿場が現れ、官殿たちは宿場にメッセージを渡し、宿場は手紙を受け取り、速馬加鞭は宮城内の皇帝の手にメッセージを伝え、皇帝は大筆を振って情報を天下に伝えた.だから脳洞は私にHandlerが郵便宿場システムだと理解できると教えてくれた.
3.Androidでは、メインスレッド以外のUI処理が許可されていないのはなぜですか?
AndroidのUIコントロールはスレッドセキュリティではないため、マルチスレッド同時アクセスではUIコントロールがほぼ予想できない状態になる可能性があります.ロックで解決できると思いますが、ロックではまずUIにアクセスする論理が複雑になります.次に、ロックがスレッドの実行をブロックするため、UIのアクセス効率が低下します.したがって、最も簡単で効率的な方法は、UI操作を処理するために単一スレッドモデルを採用することである.(この言葉はAndroid開発芸術探索から出ている)これで、マルチスレッドの問題に関心を持つ必要はありません.また、どんな冗談を言っても、誰もが聖旨を出すことができて、それは天下の大乱ではありません!
なお、サブスレッド操作UIを許可しないことはできないわけではないが、死んだらサブスレッドでUIを操作しなくてもよい.できるかどうかの鍵は、このスレッドにView Rootが含まれていないことだからです.つまり、インタフェースを更新する操作はinvalidate()メソッドを呼び出します.このメソッドはcheckThreadに行きますが、invalidate()はViewRootImplが呼び出し、ViewRootImplはActivityのonResumeのときにwindow getDecorViewを通過した後にaddViewが作成されます.だからonResumeの前にすれば間違いはありません.この点は多くありませんが、サブスレッドもUIを更新できることを知っていればいいのですが、サブスレッドがUIを更新できるかどうかを聞かれたら、実際にはできると言ってくれればOKです.
Handlerの使用方法
Handlerを作成すると、デフォルトのスレッドにバインドされます.このスレッドにはMessageQueue(メッセージキュー)があります.MessageQueueはメッセージの記憶ユニットにすぎず、メッセージを処理することはできません.Looperはこれに使用します.Looperは常に新しいメッセージがあるかどうかをループして調べ、あれば処理します.スレッドのデフォルトにはLooperはありません.これは(Looper.prepare()を使用して作成し、メッセージ関連コードの最後にLooperを呼び出す必要があります.loop()のみポーリングできます.しかし、UIスレッドではActivity Threadであるため、Activity Threadが作成されたときにLooperが初期化するので、メインスレッドではHandlerを直接使用することができる.
Handler handler=new Handler(){

public void handlerMessage(Message msg){

mas.what…//    Message             msg   

           }

}

主な方法は次のとおりです.
Handler.post(Runnable)       UI   

Handler.postDelayed(Runnable,long) long               

Handler.sendMessage(Message)

Handler.senMessageDelayed

Handler.removeCallbacks(Runnable);             。


ここで転送されるMessageの主なプロパティは次のとおりです.
Message.arg (int)        
Message.obj  (Object)  Object
Message.what  (int)          ,        
Message.sendToTarget();         ,         Handler。    Handler.sendMessage();        。

メッセージを作成する必要がない場合は、システムのメッセージオブジェクト:handlerを多重化することもできます.obtainMessage();Messageオブジェクトが返されます.
私たちがメッセージを送信する場合は必ずメッセージを送信するアドレスを指定し、メッセージがどこに送信されているかを知るには、obtainMessage()メソッドでは実際にこのHnadler自身にメッセージを送信します.メソッドの内部はMessageです.targetが実現し、このtargetが現在のHandlerである.
Message.sendToTarget()には実際にtargetが呼び出されています.sendMessage();ターゲットはハンドラー自身だから本質的にはMessagesendToTargetとHandlersendMessage();方法は同じです.
Handlerの原理
MessageQueue
メッセージキューです.メッセージは追加および削除できます.Handlerが送ったメッセージはすべてここにまとめられています.
Looper
Looperの内部にはMessageQueueメッセージキューが含まれているので、LooperはMessageQueueを恣意的にポーリングすることができます.Looper.Loopメソッドが起動するとデッドループを開いてMessageQueueをポーリングし,メッセージがあれば処理し,なければブロックする.
Looperを作成すると、MessageQueueがnewされ、現在のスレッドが確定します.
Looper(boolean){

       MessageQueue mQueue=new MessageQueue(boolean);

        …….

       mThread = Thread.currentThread();

}

Handler
handler内部はLooperに関連付けられ、Looper内部にはMessageQueueがあり、Handlerが送信したメッセージはMessageQueueに含まれています.
簡単に言えばhandlerはメッセージを送信し、Looperはメッセージを受信してhandler自身にメッセージを返す.
実際にメインスレッドで作成したHandlerの場合、handlerMessageメソッドではあまり時間のかかるメソッドは書かないでください.そうしないとカードUIの現象が発生します.
時間のかかる操作をhandlerで処理する必要がある場合は、HandlerThread、HandlerThreadでLooperを作成し、デフォルトのHandlerを関連付けて、マルチスレッド同時問題を解決し、looperを指定するときに発生する空のポインタの問題をバインドしないようにすることもできます.これにより、プライマリ・スレッド・リソースを完全に占有しません.
HandlerThread thread=new HandlerThread(“xxxxxthread”);

thread.start();

handler=new Hanlder(thread.getLooper()){

public void handlerMessage(Message msg){

//                         

         }

}

handler.sendMessage……..;//         

UIの更新について
handlerを直接利用する以外runOnUIThread()ビュー自体のpostメソッドとUIを更新することもできます
private void xxxxUpdateUI(){

        runOnUiThread(new Runnable){

             public void run(){

                //  UI   
                               }
                        }
                  }

handlerのpostメソッドおよびrunOnUIThread()およびviewのpostメソッドの内部は実際にはカプセル化されたhandlerがmessageを送信する一連の方法であり,本質的にはhandlerメカニズムによって行われている.