android学習(2)マルチスレッドの理解
3114 ワード
マルチスレッド操作UIの動作原理:
UIスレッド:まずappを起動すると、システムは自動的にUIスレッドを起動し、その後、このスレッドはLooperを作成し(注:Looperコンストラクション関数はMessageQueueのメッセージキューに変数mQueueが存在する)、loopメソッドを呼び出すことによって無限ループのforを実行し、このforにはMessageQueueがある.next()メソッドは、メッセージキュー内のMessage(メッセージキューが空の場合はブロック待ち)を絶え間なく検索し、Messageを取得するとmessageを実行する.target(このフィールドに格納されているHandlerクラスのインスタンス)のdispatchMessage(Message msg)メソッドを実行し、recycle()メソッドを実行してMessageオブジェクトを回収します(システムは50個のMessageオブジェクトプールを維持します).
Handler:サブスレッドの結果がUIスレッドにフィードバックされる必要がある場合、HandlerはUIスレッドで如実にインスタンス化する必要があり、逆にサブスレッドでHandlerをインスタンス化する必要があります.Handlerのデフォルトインスタンス化で使用されるLooperは、現在のスレッドのLooperです
Handler部分コード切り取り:
Handlerクラスはどのくらいのコンストラクタを提供しており,そのスレッドを使用するLooperを直接指定することができる.
public Handler(Looper looper)
詳細なコンストラクタは、ソースコードを参照してください.
サブスレッド:サブスレッドの作成(HandlerThread:デフォルトでは独自のLooperを作成し、Thread:Looperが必要な場合は手動で作成する)、サブスレッドで実行する必要があるコードを指定し、コードの実行時に結果がUIスレッドにフィードバックされる必要がある場合(UIに値を表示するなど)、このHandler(このHandlerはUIスレッドのHandlerでなければならない、つまりUIスレッドのLooperインスタンスを使用しなければならない)のMessageをUIスレッドのMessageQueueに押し込むだけでよい.このHandlerに対応するMessageインスタンスを取得する方法:HandlerのobtainMessage()メソッドを呼び出すことができます.Message Queueに押し込む方法:HandlerのsendMessage(sendEmptyMessageDelayed、sendEmptyMessageAtTime....自分のニーズに合わせて方法を選択)またはMessageを呼び出すsendToTarget()メソッドですが、実はこのメソッドはmessageが自分のtarget変数(Handlerのインスタンスを格納)を呼び出すsendMessage(Message msg)メソッドで、それから自分をメソッドのパラメータとして渡します.
補足:HandlerのdispatchMessageメソッドに注目してください.
Handler部分コードは以下の通りです.
正しくないところや厳格でないところがあれば、指摘、検討を歓迎します.ありがとう!
UIスレッド:まずappを起動すると、システムは自動的にUIスレッドを起動し、その後、このスレッドはLooperを作成し(注:Looperコンストラクション関数はMessageQueueのメッセージキューに変数mQueueが存在する)、loopメソッドを呼び出すことによって無限ループのforを実行し、このforにはMessageQueueがある.next()メソッドは、メッセージキュー内のMessage(メッセージキューが空の場合はブロック待ち)を絶え間なく検索し、Messageを取得するとmessageを実行する.target(このフィールドに格納されているHandlerクラスのインスタンス)のdispatchMessage(Message msg)メソッドを実行し、recycle()メソッドを実行してMessageオブジェクトを回収します(システムは50個のMessageオブジェクトプールを維持します).
Handler:サブスレッドの結果がUIスレッドにフィードバックされる必要がある場合、HandlerはUIスレッドで如実にインスタンス化する必要があり、逆にサブスレッドでHandlerをインスタンス化する必要があります.Handlerのデフォルトインスタンス化で使用されるLooperは、現在のスレッドのLooperです
Handler部分コード切り取り:
public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
mLooper = Looper.myLooper();// Looper mLooper
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
Handlerクラスはどのくらいのコンストラクタを提供しており,そのスレッドを使用するLooperを直接指定することができる.
public Handler(Looper looper)
詳細なコンストラクタは、ソースコードを参照してください.
サブスレッド:サブスレッドの作成(HandlerThread:デフォルトでは独自のLooperを作成し、Thread:Looperが必要な場合は手動で作成する)、サブスレッドで実行する必要があるコードを指定し、コードの実行時に結果がUIスレッドにフィードバックされる必要がある場合(UIに値を表示するなど)、このHandler(このHandlerはUIスレッドのHandlerでなければならない、つまりUIスレッドのLooperインスタンスを使用しなければならない)のMessageをUIスレッドのMessageQueueに押し込むだけでよい.このHandlerに対応するMessageインスタンスを取得する方法:HandlerのobtainMessage()メソッドを呼び出すことができます.Message Queueに押し込む方法:HandlerのsendMessage(sendEmptyMessageDelayed、sendEmptyMessageAtTime....自分のニーズに合わせて方法を選択)またはMessageを呼び出すsendToTarget()メソッドですが、実はこのメソッドはmessageが自分のtarget変数(Handlerのインスタンスを格納)を呼び出すsendMessage(Message msg)メソッドで、それから自分をメソッドのパラメータとして渡します.
補足:HandlerのdispatchMessageメソッドに注目してください.
Handler部分コードは以下の通りです.
final Callback mCallback;
public interface Callback {
public boolean handleMessage(Message msg);
}
/* Subclasses must implement this to receive messages.
*/
public void handleMessage(Message msg) {
}
public void dispatchMessage(Message msg) {
if (msg.callback != null) {// msg callback
handleCallback(msg);
} else {
if (mCallback != null) {// Handler Callback, handleMessage
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);//
}
}
正しくないところや厳格でないところがあれば、指摘、検討を歓迎します.ありがとう!