Android handle的难点问题及解答
1. 消息的使用
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
finish();
overridePendingTransition(R.anim.abc_fade_in, R.anim.abc_fade_out);
}
}, 500);
2. Looper 死循环为什么不会导致应用卡死?
线程默认没有Looper的,如果需要使用Handler就必须为线程创建Looper。我们经常提到的主线程,也叫UI线程,它就是ActivityThread,ActivityThread被创建时就会初始化Looper,这也是在主线程中默认可以使用Handler的原因。
3. 子线程中使用Toast,更新UI会导致奔溃的原因
在这里显示Toast一定会崩溃,报错日志如下:
new Thread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "run on thread" , Toast.LENGTH_SHORT).show();//崩溃无疑
}
}).start();
一般如果子线程不能更新UI控件是会报如下错误的(子线程不能更新UI)
原因分析:
子线程中Looper不同于主线程里面的Looper!
主线程里面的Looper是一直循环的,同时该looper不影响程序崩溃,只有在程序在OnCreate(),OnPause()会暂时结束,在activity生命周期OnPause()结束后,Looper继续。因此主线程中更新UI不会出现问题。
子线程中looper不是一直循环的,因此在子线程中更新UI可能会发生崩溃。
完成代码
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
public static final int UPDATE_TEXT = 1;
private TextView textView;
private Button changeText;
// 消息异步处理机制
@SuppressLint("HandlerLeak")
private Handler handler = new Handler(){
public void handleMessage(Message msg){ // 在这里接收handle消息,handleMessage()方法在主线程中处理
switch (msg.what) {
case UPDATE_TEXT:
// 在这里进行UI操作
textView.setText("更新数据");
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView)findViewById(R.id.text);
changeText = (Button) findViewById(R.id.change);
changeText.setOnClickListener(this); // 设置button点击监听
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.change:
// 创建子线程
new Thread(new Runnable() {
@Override
public void run() {
// 1.0版本,这样写,在子线程中进行UI操作会导致奔溃
// textView.setText("更新数据");
Message message = new Message();
message.what = UPDATE_TEXT;
handler.sendMessage(message); // 将Message对象发送出去
}
}).start();
break;
default:
break;
}
}
}