Android可以在子线程更新UI吗
16lz
2021-01-26
之前一直有个疑问,为什么不能在子线程中更新UI。最近在看Android源码关于界面加载的部分,发现更新UI的动作最终都会执行一个线程检测方法checkThread(),在ViewRootImpl。很重要的一点,在ViewRootImpl被初始化之前,mThread是为空的,此时在线程中更新UI也是没问题的。
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); final TextView textView = findViewById(R.id.test_tv); new Thread(new Runnable() { @Override public void run() { textView.setText("error"); } }); }
void checkThread() { if (mThread != Thread.currentThread()) { throw new CalledFromWrongThreadException( "Only the original thread that created a view hierarchy can touch its views."); } }
如果在子线程中更新UI就会抛出上面这个异常。
我注意到,判断的依据是mThread与你当前执行更新的线程是否为同一个线程。再看mThread的赋值是在初始化的时候进行的。
public ViewRootImpl(Context context, Display display) { mContext = context; mWindowSession = WindowManagerGlobal.getWindowSession(); mDisplay = display; mBasePackageName = context.getBasePackageName(); mThread = Thread.currentThread();//这里给mThread赋值,即实例化ViewRootImpl的那个线程 //省略代码}
ViewRootImpl的初始化通过分析源码,源于在Activity的onCreate中执行setContentView方法。因为onCreate是在UI线程执行的,所以ViewRootImpl的初始化也是在UI线程。知道原因就可以回答标题的问题了,答案是:可以的。只要我们在子线程执行
setContentView,然后在这个线程中更新UI就没问题。demo如下:
public class MainActivity extends AppCompatActivity { private MyUIThread mMyUIThread; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mMyUIThread = new MyUIThread(); mMyUIThread.mHandler.sendEmptyMessage(1); mMyUIThread.mHandler.post(new Runnable() { @Override public void run() { TextView textView = findViewById(R.id.test_tv); textView.setText("error"); } }); } class MyUIThread extends Thread { Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case 1: setContentView(R.layout.activity_main); break; } } }; @Override public void run() { while (true) { Looper.prepare(); Looper.loop(); } } }}
更多相关文章
- SpringBoot 2.0 中 HikariCP 数据库连接池原理解析
- RxJava 学习笔记(四)
- android-----AsyncTask源码分析
- 面试总结(6):ScheduledExecutorService的使用
- Android之MVVM架构指南(五):ViewModel
- Android(java)同步方法synchronized
- 最全面的安卓ANR
- Webkit for Android分析
- GIS的学习(二十四)android异步调用geoserver wms中的地图