问题:
1.子线程可以修改UI
2.Toast的必要条件
从源码中解决:
1.刚开始子线程可以更新UI,过一会就不能更新UI在onCreate中发送消息
EventBus.getDefault().post(new Message("test ", 22));
可以在子线程可以更新UI(而且不会抛出异常)
原因在于,此时ViewRootImpl类还未被创建,无法调用checkThread()方法检测是否是UI线程,所以可以更新UI
当点击button后再发送消息后
@Subscribe(threadMode = ThreadMode.ASYNC)
public void messages(final Message message){}
获得到对象在子线程更新UI,此时ViewRootImpl对象已经被创建,调用checkThread()判断,执行textView.setText(message.toString())
在哪个线程中,当检测到不是主线程就直接抛出异常CalledFromWrongThreadException
2.Toast并不是一定非要在主线程
在调用 show()方法的时候需要一个TN tn = mTN对象,创建TN对象的时候需要创健Handler对象,但是此时没有创健Looper
为什么没有创健Looper呢?
因为主线程已经帮助我们创健好Looper,所以不用我们自己创健,那么问题来了,当没有Looper对象的时候Toast就用不了
也就是在子线程中使用Toast的时候需要我们手动创健一个Looper对象
测试代码:
package com.example.event; import android.os.Bundle; import android.os.Looper; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.widget.TextView; import android.widget.Toast; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnClick; public class TestActivity extends AppCompatActivity { @BindView(R.id.textView) TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); ButterKnife.bind(this); EventBus.getDefault().register(this); EventBus.getDefault().post(new Message("test ", 22)); // new Thread(new Runnable() { // @Override // public void run() { // try { // Thread.sleep(2000); // } catch (InterruptedException e) { // e.printStackTrace(); // } // EventBus.getDefault().post(new Message("hh", 22)); // } // }).start(); } /** * 解决问题: * 1.刚开始子线程可以更新UI,过一会就不能更新UI * 在onCreate中发送消息 * EventBus.getDefault().post(new Message("test ", 22)); * 可以在子线程可以更新UI(而且不会抛出异常) * 原因在于,此时ViewRootImpl类还未被创建,无法调用checkThread()方法检测是否是UI线程,所以可以更新UI * 当点击button后再发送消息后 * @Subscribe(threadMode = ThreadMode.ASYNC) * public void messages(final Message message){} * 获得到对象在子线程更新UI,此时ViewRootImpl对象已经被创建,调用checkThread()判断,执行textView.setText(message.toString()) * 在哪个线程中,当检测到不是主线程就直接抛出异常CalledFromWrongThreadException * * 2.Toast并不是一定非要在主线程 * 在调用 show()方法的时候需要一个TN tn = mTN对象,创建TN对象的时候需要创健Handler对象,但是此时没有创健Looper * 为什么没有创健Looper呢? * 因为主线程已经帮助我们创健好Looper,所以不用我们自己创健,那么问题来了,当没有Looper对象的时候Toast就用不了 * 也就是在子线程中使用Toast的时候需要我们手动创健一个Looper对象 * * * */ @Subscribe(threadMode = ThreadMode.ASYNC) public void messages(final Message message) { Log.i("TestActivity", Thread.currentThread().getName()); message.toString(); textView.setText(message.toString()); // this.runOnUiThread(new Runnable() { // @Override // public void run() { // Toast.makeText(TestActivity.this,message.toString(),Toast.LENGTH_LONG).show(); // } // }); // Looper.prepare(); // Toast.makeText(TestActivity.this,message.toString(),Toast.LENGTH_LONG).show(); // Looper.loop(); new Thread(new Runnable() { @Override public void run() { Looper.prepare(); Toast.makeText(TestActivity.this,message.toString(),Toast.LENGTH_LONG).show(); Looper.loop(); } }).start(); } @Override protected void onDestroy() { super.onDestroy(); EventBus.getDefault().unregister(this); } @OnClick(R.id.button2) public void onViewClicked() { EventBus.getDefault().post(new Message("send",20)); //finish(); } }
github地址:
https://github.com/suhuMM/AIDLDome