消息机制,对于Android开发者来说,应该是非常熟悉。对于处理有着大量交互的场景,采用消息机制,是再好不过了。有些特殊的场景,比如我们都知道,在Android开发中,子线程不能更新UI,而主线程又不能进行耗时操作,一种常用的处理方法就是,在子线程中进行耗时操作,完成之后发送消息,通知主线程更新UI。或者使用异步任务,异步任务的实质也是对消息机制的封装。
常见的异常为:
AndroidRuntime: FATAL EXCEPTION: Thread-176
Process: com.example.joy.messagetest, PID: 11201
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6357)
at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:874)
说明线程存在异常,子线程不能更新ui。
布局文件:
<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.joy.messagetest.MainActivity">
<TextView
android:id="@+id/tv_test"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="Hello World!" />
<Button
android:id="@+id/btn_test1"
android:layout_below="@id/tv_test"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="子线程更新UI测试"/>
<Button
android:id="@+id/btn_test2"
android:layout_below="@id/btn_test1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="Handler发送消息"/>
<Button
android:id="@+id/btn_test3"
android:layout_below="@id/btn_test2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="Handler.Post"/>
<Button
android:id="@+id/btn_test4"
android:layout_below="@id/btn_test3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="View.Post"/>
<Button
android:id="@+id/btn_test5"
android:layout_below="@id/btn_test4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="Activity.RunOnUIThread"/>
</RelativeLayout>
java代码:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private TextView mTvTest;
private Button mBtnTest1;
private Button mBtnTest2;
private Button mBtnTest3;
private Button mBtnTest4;
private Button mBtnTest5;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == 100) {
mTvTest.setText("由Handler发送消息");
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
new Thread(new Runnable() {
@Override
public void run() {
mTvTest.setText("子线程可以更新UI");
}
}).start();
}
private void initView() {
mTvTest = (TextView) findViewById(R.id.tv_test);
mBtnTest1 = (Button) findViewById(R.id.btn_test1);
mBtnTest2 = (Button) findViewById(R.id.btn_test2);
mBtnTest3 = (Button) findViewById(R.id.btn_test3);
mBtnTest4 = (Button) findViewById(R.id.btn_test4);
mBtnTest5 = (Button) findViewById(R.id.btn_test5);
mBtnTest1.setOnClickListener(this);
mBtnTest2.setOnClickListener(this);
mBtnTest2.setOnClickListener(this);
mBtnTest3.setOnClickListener(this);
mBtnTest4.setOnClickListener(this);
mBtnTest5.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_test1:
new Thread(new Runnable() {
@Override
public void run() {
mTvTest.setText("子线程真的可以更新UI吗?");
}
}).start();
break;
case R.id.btn_test2: //通过发送消息
new Thread(new Runnable() {
@Override
public void run() {
mHandler.sendEmptyMessage(100);
}
}).start();
break;
case R.id.btn_test3: //通过Handler.post方法
new Thread(new Runnable() {
@Override
public void run() {
mHandler.post(new Runnable() {
@Override
public void run() {
mTvTest.setText("handler.post");
}
});
}
}).start();
break;
case R.id.btn_test4: //通过 view.post方法
new Thread(new Runnable() {
@Override
public void run() {
mTvTest.post(new Runnable() {
@Override
public void run() {
mTvTest.setText("view.post");
}
});
}
}).start();
break;
case R.id.btn_test5: //通过 activity 的 runOnUiThread方法
new Thread(new Runnable() {
@Override
public void run() {
runOnUiThread(new Runnable() {
@Override
public void run() {
mTvTest.setText("runOnUIThread");
}
});
}
}).start();
break;
default:
break;
}
}
}
其中点击第一个按钮是错误示范,也是常见的异常情况。