Android:Handlerで非同期処理機能を実現

8786 ワード

Android:Handlerで非同期処理機能を実現ダウンロードに似た機能をActivityに書くと、Activityがブロックされ、ページが偽死するまで応答しない.そのため、私たちはこれらの時間のかかる操作を単独のサブスレッドの中で操作する必要があります.これがHandlerの使命です.1つの問題は、ダウンロードに似た機能(時間がかかり、必ずしも結果が出るとは限らない)をActivity(メインスレッド)に書くと、Activityがブロックされ、ページが偽死するまで長時間応答せず(5秒で完了しないと、Androidシステムのエラーメッセージ「強制閉鎖」が届く)という問題です.したがって,これらの時間のかかる操作を個別のサブスレッドに配置して操作する必要がある.これがハンドラーの使命だ.Handlerは非同期処理の機能を提供し,送受信は同時ではない(Activityのメインスレッドとスレッドキュー内のスレッドは異なるスレッドであり,並列に行われ,互いに影響しない).二.Handler概要HandlerはAndroidオペレーティングシステムのスレッド通信ツールであり、主に2つの役割を果たす:(1)メッセージをスケジュールするか、Runnableがあるメインスレッドのどこかで実行するか(2)別のスレッドで動作をスケジュールする.各Handlerオブジェクトは、2つのキュー(FIFO)、メッセージキュー、Runnableキューを維持し、Androidオペレーティングシステムが提供しています.Handlerは、メッセージを送信、受信、処理する2つのキューを介して、メッセージキューをそれぞれ処理することができる.起動、終了、スリープスレッド–Runnableキュー;Handlerの使い方は大きく3つのステップに分けられる:1.Handlerオブジェクトを作成します.2.Runnableとメッセージを作成します.3.postメソッドおよびsendMessageメソッドを呼び出して、Runnableメソッドとメッセージをキューに追加します.三.Runnableキュー1.JAvaのスレッドjavaでは、スレッドの作成には、Threadクラスの継承とRunnableインタフェースの実装の2つの方法があります.これはrunメソッドを複写してスレッドの機能を実現することが最も重要である.スレッドのタイムスライスが到着し、実行が開始されるとrun()関数が実行され、実行が完了すると死亡状態になります.スレッドを作成する例を示します.
Runnable r=new Runnable(){ 

@Override
public void run() { 
// TODO Auto-generated method stub
System.out.println("thread"); 
handler.postDelayed(thread, 3000); 
} 
}; 

2.Runnableキュー(1)原理Androidのスレッド非同期処理メカニズムについて:Handlerオブジェクトはスレッドキューを維持し、新しいRunnableが送られてきたときにキューの最後に置き、Runnableを処理するときにキューからRunnableを取り出して実行する.キューにRunnableを送信すると、すぐに戻り、Runnableが実行されたかどうか、実行が成功したかどうかなどは気にしません.具体的な実行は、Runnableにキューに並んだ後、システムが実行する.これは郵便局の例のようなものです.差出人は手紙を書いてポストに入れて家に帰ったが、いつ郵便局に配られたのか、いつ届いたのか、相手がどのように読み取ったのか分からなかった.これにより,Androidの非同期処理メカニズムが実現される.(2)具体的な操作
handler.post(Runnable ); Runnable       
handler.postDelayed(Runnable, long)       , Runnable     
handler.postAtTime(Runnable,long)   Runnable     
    :
handler.removeCallbacks(thread); Runnable Runnable     

四.メッセージキュー1.メッセージオブジェクト(1)MessageオブジェクトMessageオブジェクトは、通常arg 1,arg 2でメッセージを伝達します.もちろん、objパラメータがあり、Bundleデータを携帯することもできます.システムのパフォーマンス消費量が非常に少ないのが特徴です.初期化:Message msg=handler.obtainMessage(); (2)BundleオブジェクトBundleはAndroidが提供するクラスであり,特殊なMap,すなわちキー値ペアのパッケージと見なすことができる.また、キーと値の両方において、基本データ型または基本データ型の配列(Mapのキー値の要件はすべてオブジェクト)である必要があります.特に、キー要件はStringタイプです.MessageでBundleデータを携帯する:入れ:msg.setData(Bundle bundle); 取り出し:msg.getData(); 2.メッセージキュー(1)原理Androidのメッセージ非同期処理メカニズムについて:Handlerオブジェクトはメッセージキューを維持し、新しいメッセージが送られてきた場合(sendMessage()に)、それをキューの最後に置き、その後、そのメッセージを処理するまでキューに並び、メインスレッドのHandlerイメージ処理(handleMessage()によって処理される.プロセス全体も非同期であり,Runnableキューの原理と同じである.(2)具体的な操作:Runnable:handlerをキューに追加する.sendMessage(Message); メッセージキューmsgにメッセージを送信.sendToTarget(); 一定時間遅延後、メッセージキューhandlerにメッセージを送信.sendMessageDelayed(Message,long); メッセージキューhandlerにメッセージをタイミング的に送信する.sendMessageAtTime(Message,long)メッセージの処理:メッセージの具体的な処理手順は、new Handlerオブジェクトの場合、匿名の内部クラスを使用してHandlerのhandleMessage(Message msg)メソッドを書き換える必要があります.
Handler handler=new Handler(){ 

@Override
public void handleMessage(Message msg) { 
// TODO Auto-generated method stub
。。。。。。 

。。。。。。 
} 
}; 

五.Handlerの2つの役割1.スケジュールメッセージまたはRunnableは、主スレッドのどこかでコードの例を実行します.
public class HandlerTestActivity extends Activity { 
private Button start; 
@Override
protected void onCreate(Bundle savedInstanceState) { 
// TODO Auto-generated method stub
super.onCreate(savedInstanceState); 
setContentView(R.layout.handlertest); 
start=(Button) findViewById(R.id.start); 
start.setOnClickListener(new startListener()); 

System.out.println("Activity Thread:"+Thread.currentThread().getId()); 
} 
Handler handler=new Handler(); 
Runnable thread=new Runnable(){ 

@Override
public void run() { 
// TODO Auto-generated method stub
System.out.println("HandlerThread:"+Thread.currentThread().getId()); 

} 
}; 
class startListener implements OnClickListener{ 

@Override
public void onClick(View v) { 
// TODO Auto-generated method stub
handler.post(thread); 
} 
} 

} 

このウィジェットでは、まずプログラムが起動し、onCreate()に入り、現在のスレッド(すなわちメインスレッド)のIDを印刷し、その後ボタンstartをクリックすると、スレッドthreadがスレッドキューに追加され、スレッドthreadが実行され、threadの役割は現在のスレッドのIDを印刷することである.このプログラムでは,HandlerによってRunnableがあるメインスレッドのどこかで実行されるように手配すること,すなわち役割(1)を実現できることが分かる.しかし、ここには小さな罠があります.見つけましたか.このプログラムはHandlerの非同期メカニズムを実現したように見えますpost(thread)は新しいスレッド起動の役割を果たしているようですが、実行することで、2つのスレッドのIDが同じであることがわかりました.つまり、実際にはthreadは元のメインスレッドであることから、handler.post()メソッドは実際にスレッドを新規作成するのではなく,元のスレッド上で実行するだけであり,非同期メカニズムを実現していない.2.アクションを別のスレッドで実行するように手配します.(1)javaで標準的なスレッドの作成方法の最初のステップ:
 Runnable r=new Runnable(){ 

@Override
public void run() { 
// TODO Auto-generated method stub
System.out.println("thread"); 
handler.postDelayed(thread, 3000); 
} 
}; 

ステップ2:
Thread t=new Thread (r); ステップ3:
t.start(); 上記の例のプログラムのhandlerをpost(thread);文は以上の形式に変更され、印刷することで、2つのIDが異なり、新しいスレッドが起動していることがわかります.(2)Looper Looperクラスについてスレッドのメッセージループを開くために用いられ,メッセージキューからメッセージをループして読み取る役割を果たすため,Looperは実際にはメッセージキュー+メッセージループのカプセル化である.各スレッドには1つのLooperしか対応できません.Androidのスレッドは、メインスレッドを除いてデフォルトではLooperがオンになっていません.HandlerがLooperと対話することにより、Handlerは、指定されたLooperにメッセージを送信し、処理方法を定義するためのLooperのインタフェースと見なすことができる.デフォルトでは、HandlerはスレッドのLooperにバインドされます.つまり、Handler handler=new Handler()です.Handler handler=new Handler(Looper.myLooper();Looperには2つの主な方法があります:Looper.prepare();Looper Looperを有効にするloop(); Looperに作業を開始させ,メッセージキューからメッセージを取り出し,メッセージを処理する.注意:Looperに書きます.loop()以降のコードは実行されません.この関数の内部にはmHandlerが呼び出されるループがあるはずです.getLooper().quit()後、loopは中止され、その後のコードが実行されます.(3)Handler非同期機構の実現Handlerは,HandlerThreadによってサブスレッドがメインスレッドと異なるスレッドに属するようにした.実際、HandlerThreadは特殊なスレッドであり、Looperをカプセル化したスレッドであり、コードの例:
//handlerという名前の作成hreadのHandlerThreadオブジェクトHandlerThread handlerThread=new HandlerThread("handler_hread");
//handlerThreadを開き、handlerThreadを使用する.getLooper()を呼び出す前にstartメソッドを呼び出さなければなりません.そうしないと、空のhandlerThreadが取り出されます.start();
//handlerをhandlerThreadのLooperにバインドします.つまり、このhandlerはhandlerThreadスレッドで実行されるmyHandler handler=new myHandler(handlerThread.getLooper()です.
class myHandler extends Handler{ 
public myHandler(){} 
public myHandler(Looper looper){ 
super(looper); 
} 
@Override
public void handleMessage(Message msg) { 
// TODO Auto-generated method stub
System.out.println("Activity Thread:"+Thread.currentThread().getId()); 
} 
}

これにより、handlerの非同期処理機構が実現する、handlerが呼び出される.post()メソッドでは,スレッドIDを印刷することにより,サブスレッドとメインスレッドが異なるスレッドに分かれていることが分かる.