Android面接問題002 androidのHandlerメカニズム
4986 ワード
UIスレッドとは?
アプリケーションのメインUIスレッドの概念とその重要性は、Android開発者一人一人が理解しなければならないことです.アプリケーションが起動すると、アプリケーションのメインスレッド「main」が作成されます.このプライマリ・スレッド(すなわちUIプライマリ・スレッド)は、主に適切なviewまたはwidgetにイベントを配布する責任を負うため、非常に重要です.それはあなたのアプリケーションとアプリケーションのUIのインタラクティブなスレッドでもあります.たとえば、画面上のボタンをクリックすると、UIスレッドはビュー処理にクリック時間を渡し、ビューがイベントを受信するとpressed状態を設定し、イベントキューにinvalidateリクエストを送信します.UIスレッドはキューを順番に読み取り、viewに自分を再描画するように伝えます.
なぜAndroidのUI操作はスレッドが安全ではないのか
AndroidのUI操作はスレッドが安全ではないため、よく耳にする言葉です.だからハンドラーが現れた.
この言葉を理解するには、まずスレッドのセキュリティとは何かを知る必要があります.スレッドが安全ではないのは何ですか?
スレッドのセキュリティ:
複数のスレッドがアクセスする場合、ロックメカニズムを採用し、1つのスレッドがクラスのデータにアクセスすると、保護され、他のスレッドはスレッドが読み取り終わるまでアクセスできず、他のスレッドは使用できません.データの不一致やデータ汚染は発生しません.
スレッドが安全ではありません:
すなわち,ロックメカニズムを採用しない,すなわちデータアクセス保護を提供せず,複数のスレッドを同時にアクセスできる.これにより、複数のスレッドが前後してデータを変更し、得られたデータが汚いデータになる可能性がある.
したがってAndroidでは,複数のスレッドが同時にUIを変更すると,インタフェースが混乱する.ロックメカニズムを使用すると、実行効率が低下します.だからAndroidはスレッドが安全ではないが性能が良いという方法を選んだ.つまり、Androidはパフォーマンスを考慮してUIスレッドが安全ではないという話をよく耳にします.したがってAndroidはメインスレッドMainThreadを単一スレッドモデルとして設計し,メインスレッドでのみUI要素を変更できることを規定している.
マスタスレッドMainThreadは単一スレッドモデルであるため、マスタスレッドを時間をかけて操作することはできません.これによりuiスレッドがブロックされ、ページカートンが発生します.UIスレッドが5秒以上ブロックされている場合、ユーザーは「プログラム未応答」(ANR)のプロンプトダイアログボックスを受け取り、強制的に終了します.
ネットワーク要求、画像処理、データベース操作などの時間を費やし、ネットワーク要求、画像処理、データベース操作などのサブスレッド処理に置かなければならない.これらの操作の後、結果をユーザーにフィードバックし、ui操作を行う必要があります.
サブスレッドがUIを変更するには、メインスレッドに通知する必要があります.これは,スレッド間通信,すなわち,スレッド間の通信を実現するためのHandlerメッセージメカニズムの出現に関する.
いくつかの名詞を理解する
UIスレッド:メインスレッドです.UIスレッドを作成するときにLooperオブジェクトを初期化し、関連付けられたMessageQueue も作成します.
Handler:メッセージの送信と処理を行います.Handlerが正常に動作するには、現在のスレッドにLooperオブジェクトが必要です.
Message:Handlerが受信して処理するオブジェクト.HandlerはRunnableオブジェクトを受信して処理することもできる.
MessageQueue:メッセージキュー、管理Messageの先頭に立って、Looperオブジェクトを初期化すると、それに関連付けられたMessageQueue が作成されます.
Looper:各スレッドには1つのLooperしかありません.Looperは現在のスレッドのMessageQueueの作成と管理を担当しています.loopメソッドを呼び出すと、無限ループでMessageQueueからMessageを取り出して対応するHandlerに配布し、最後にhandleMessage()メソッドをコールしてこのメッセージを処理します.Looperこそメカニズム全体の核心だ!
Messageオブジェクトの内部実装はチェーンテーブルであり、最大長は50であり、メッセージオブジェクトをキャッシュし、メッセージオブジェクトを再利用する目的を達成し、メッセージオブジェクトの作成を減らすために、obtainMessageメソッドを使用してメッセージオブジェクトを取得するのが一般的である.
Handler実装手順
1.メインスレッドでHandler handle=new Handler()を使用してHandlerオブジェクトを作成し、handlenessageメソッドを書き換える
Hanldeを作成すると、この2つの方法が実行され、メインスレッドのLooperオブジェクトとmessageQueueオブジェクトが取得されます.
2.実行終了後にsendMessageを介してスレッドを作成
handler.postメソッドはコードを直接送信します.
内部も呼び出し
sendMessageDelayedメソッドでは、RunnableをMessageオブジェクトにカプセル化し、m.callback=rでrunnableをコールバックに設定します.
handlerメモリの漏洩と解決方法
handleは静的内部クラスではないので、handleはactivityの参照を隠すことができます.Activityが回収されるのは、handlerが時間のかかる操作をしても解放されないためであり、handlerが保有するactivityの参照が解放されないため、activityが回収されずにメモリに残ってメモリが漏洩する
1.handlerを静的内部クラスに設定
2.handlerはactivityの弱い参照を持っている
3.ActivityライフサイクルonDestroyでhandlerを呼び出す.removeCallbackメソッド
アプリケーションのメインUIスレッドの概念とその重要性は、Android開発者一人一人が理解しなければならないことです.アプリケーションが起動すると、アプリケーションのメインスレッド「main」が作成されます.このプライマリ・スレッド(すなわちUIプライマリ・スレッド)は、主に適切なviewまたはwidgetにイベントを配布する責任を負うため、非常に重要です.それはあなたのアプリケーションとアプリケーションのUIのインタラクティブなスレッドでもあります.たとえば、画面上のボタンをクリックすると、UIスレッドはビュー処理にクリック時間を渡し、ビューがイベントを受信するとpressed状態を設定し、イベントキューにinvalidateリクエストを送信します.UIスレッドはキューを順番に読み取り、viewに自分を再描画するように伝えます.
なぜAndroidのUI操作はスレッドが安全ではないのか
AndroidのUI操作はスレッドが安全ではないため、よく耳にする言葉です.だからハンドラーが現れた.
この言葉を理解するには、まずスレッドのセキュリティとは何かを知る必要があります.スレッドが安全ではないのは何ですか?
スレッドのセキュリティ:
複数のスレッドがアクセスする場合、ロックメカニズムを採用し、1つのスレッドがクラスのデータにアクセスすると、保護され、他のスレッドはスレッドが読み取り終わるまでアクセスできず、他のスレッドは使用できません.データの不一致やデータ汚染は発生しません.
スレッドが安全ではありません:
すなわち,ロックメカニズムを採用しない,すなわちデータアクセス保護を提供せず,複数のスレッドを同時にアクセスできる.これにより、複数のスレッドが前後してデータを変更し、得られたデータが汚いデータになる可能性がある.
したがってAndroidでは,複数のスレッドが同時にUIを変更すると,インタフェースが混乱する.ロックメカニズムを使用すると、実行効率が低下します.だからAndroidはスレッドが安全ではないが性能が良いという方法を選んだ.つまり、Androidはパフォーマンスを考慮してUIスレッドが安全ではないという話をよく耳にします.したがってAndroidはメインスレッドMainThreadを単一スレッドモデルとして設計し,メインスレッドでのみUI要素を変更できることを規定している.
マスタスレッドMainThreadは単一スレッドモデルであるため、マスタスレッドを時間をかけて操作することはできません.これによりuiスレッドがブロックされ、ページカートンが発生します.UIスレッドが5秒以上ブロックされている場合、ユーザーは「プログラム未応答」(ANR)のプロンプトダイアログボックスを受け取り、強制的に終了します.
ネットワーク要求、画像処理、データベース操作などの時間を費やし、ネットワーク要求、画像処理、データベース操作などのサブスレッド処理に置かなければならない.これらの操作の後、結果をユーザーにフィードバックし、ui操作を行う必要があります.
サブスレッドがUIを変更するには、メインスレッドに通知する必要があります.これは,スレッド間通信,すなわち,スレッド間の通信を実現するためのHandlerメッセージメカニズムの出現に関する.
いくつかの名詞を理解する
UIスレッド:メインスレッドです.UIスレッドを作成するときにLooperオブジェクトを初期化し、関連付けられたMessageQueue も作成します.
Handler:メッセージの送信と処理を行います.Handlerが正常に動作するには、現在のスレッドにLooperオブジェクトが必要です.
Message:Handlerが受信して処理するオブジェクト.HandlerはRunnableオブジェクトを受信して処理することもできる.
MessageQueue:メッセージキュー、管理Messageの先頭に立って、Looperオブジェクトを初期化すると、それに関連付けられたMessageQueue が作成されます.
Looper:各スレッドには1つのLooperしかありません.Looperは現在のスレッドのMessageQueueの作成と管理を担当しています.loopメソッドを呼び出すと、無限ループでMessageQueueからMessageを取り出して対応するHandlerに配布し、最後にhandleMessage()メソッドをコールしてこのメッセージを処理します.Looperこそメカニズム全体の核心だ!
Messageオブジェクトの内部実装はチェーンテーブルであり、最大長は50であり、メッセージオブジェクトをキャッシュし、メッセージオブジェクトを再利用する目的を達成し、メッセージオブジェクトの作成を減らすために、obtainMessageメソッドを使用してメッセージオブジェクトを取得するのが一般的である.
Handler実装手順
1.メインスレッドでHandler handle=new Handler()を使用してHandlerオブジェクトを作成し、handlenessageメソッドを書き換える
Hanldeを作成すると、この2つの方法が実行され、メインスレッドのLooperオブジェクトとmessageQueueオブジェクトが取得されます.
mLooper = Looper.myLooper();
mQueue = mLooper.mQueue;1. Handler handle=new Handler() Handler
private final Handler mMessageHandler = new Handler(){
@Override
public void handleMessage(Message msg){
....;
}
}
はmsgを認識する.whatは対応する操作を行います2.実行終了後にsendMessageを介してスレッドを作成
class DownloadThread extends Thread{
@Override
public void run() {
try{
System.out.println(" ");
// DownloadThread 5 ,
Thread.sleep(5000);
System.out.println(" ");
// UI
Message msg=new Message();
handle.sendMessage(msg);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
handler.postメソッドはコードを直接送信します.
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
handler.post(new Runnable() {
@Override
public void run() {
mTest.setText("post");// UI
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
内部も呼び出し
sendMessageDelayedメソッドでは、RunnableをMessageオブジェクトにカプセル化し、m.callback=rでrunnableをコールバックに設定します.
Looper messageQueue , handle handlemessage 。
Lopper
handlerメモリの漏洩と解決方法
handleは静的内部クラスではないので、handleはactivityの参照を隠すことができます.Activityが回収されるのは、handlerが時間のかかる操作をしても解放されないためであり、handlerが保有するactivityの参照が解放されないため、activityが回収されずにメモリに残ってメモリが漏洩する
1.handlerを静的内部クラスに設定
2.handlerはactivityの弱い参照を持っている
3.ActivityライフサイクルonDestroyでhandlerを呼び出す.removeCallbackメソッド