標籤:
之前的例子都是我們在子線程(WorkerThread)當中處理並發送訊息,然後在主線程(UI線程)中擷取訊息並修改UI,那麼可以不可以在由主線程發送訊息,子線程接收呢?我們按照之前的思路寫一下代碼:
package cn.lixyz.handlertest;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.util.Log;import android.view.View;import android.widget.Button;public class MainActivity extends Activity { private Button button; private Handler handler; private int i = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button = (Button) findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.d("TTTT", "onClick:" + Thread.currentThread().getName()); Message msg = handler.obtainMessage(); handler.sendMessage(msg); } }); WorkerThread wt = new WorkerThread(); wt.start(); } class WorkerThread extends Thread { @Override public void run() { super.run(); handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); Log.d("TTTT", "收到了訊息對象"); } }; } }}MainActivity.java
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity"> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginTop="30dp" android:text="Send Message" /></LinearLayout>
activity_main.xml
上面的問題貌似沒什麼錯誤,但運行時卻出錯
拋出異常:
09-17 04:01:31.655 15854-15869/? E/AndroidRuntime﹕ FATAL EXCEPTION: Thread-120 Process: cn.lixyz.handlertest, PID: 15854 java.lang.RuntimeException: Can‘t create handler inside thread that has not called Looper.prepare() at android.os.Handler.<init>(Handler.java:200) at android.os.Handler.<init>(Handler.java:114) at cn.lixyz.handlertest.MainActivity$WorkerThread$1.<init>(MainActivity.java:48) at cn.lixyz.handlertest.MainActivity$WorkerThread.run(MainActivity.java:48)
提示我們沒有調用Looper.prepare(),無法建立線程,原因是非主線程中預設是沒有建立Looper對象的,需要先調用Looper.prepare()啟用Looper。修改一下上面的代碼。
package cn.lixyz.handlertest;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Looper;import android.os.Message;import android.util.Log;import android.view.View;import android.widget.Button;public class MainActivity extends Activity { private Button button; private Handler handler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button = (Button) findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Message msg = handler.obtainMessage(); msg.what = 100; handler.sendMessage(msg); Log.d("TTTT", "sendMessage:" + Thread.currentThread().getName()); } }); WorkerThread wt = new WorkerThread(); wt.start(); } class WorkerThread extends Thread { @Override public void run() { super.run(); Looper.prepare(); handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); Log.d("TTTT", "handleMessage:" + Thread.currentThread().getName()); int i = msg.what; Log.d("TTTT", "收到了訊息對象:" + i); } }; Looper.loop(); } }}MainActivity.java
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity"> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginTop="30dp" android:text="Send Message" /></LinearLayout>
activity_main.xml
運行結果:
09-17 04:29:48.669 28397-28397/cn.lixyz.handlertest D/TTTT﹕ sendMessage:main09-17 04:29:48.669 28397-28410/cn.lixyz.handlertest D/TTTT﹕ handleMessage:Thread-14109-17 04:29:48.669 28397-28410/cn.lixyz.handlertest D/TTTT﹕ 收到了訊息對象:100
上面代碼錶示,訊息是從MainThread發送的,WorkerThread接收到了訊息。
PS:非UI線程預設是沒有建立Looper對象的,所以需要主線程向子線程傳遞訊息時,需建立Looper對象並啟動迴圈,子線程才可以迴圈著從MaessageQueue中取出訊息。
Android筆記(三十二) Android中線程之間的通訊(四)主線程給子線程發送訊息