Android在子线程更新View

计算机软件开发 2024-9-8 05:17:08 87 0 来自 中国
刚开始做Android开发时,一不鉴戒就会在非UI线程中做更新UI的利用,从而造成瓦解,那么这是什么缘故原由呢?那是由于ViewRootImpl在添加View的时间通过以下代码做了线程检测
  void checkThread() {        if (mThread != Thread.currentThread()) {            throw new CalledFromWrongThreadException(                    "Only the original thread that created a view hierarchy can touch its views.");        }    }很清晰地看到mThread如果不便是当火线程就会抛出非常,而mThread地赋值是在ViewRootImpl构造函数中完成的,以是我们就推测如果构造ViewRootImpl的线程便是当火线程就可以在子线程中更新View了。下面我们通过一下代码验证。
代码分为两步
步调一:在子线程中新建ViewRootImpl;
步调二:在子线程中更新View;
private void addViewFromThread() {        new Thread(() -> {            Looper.prepare();            //获取WindowManager实例            //步调一            WindowManager wm = (WindowManager) getApplication().getSystemService(Context.WINDOW_SERVICE);            //设置LayoutParams属性            WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();            //宽高尺寸            layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;            layoutParams.width = ViewGroup.LayoutParams.WRAP_CONTENT;            layoutParams.format = PixelFormat.TRANSPARENT;            //设置配景昏暗            layoutParams.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;            layoutParams.dimAmount = 0.6f;            //Window范例            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {                layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;            } else {                layoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;            }            //构造TextView            TextView myView = new TextView(this);            myView.setText("hello window");            //设置配景为红色            myView.setBackgroundColor(Color.RED);            FrameLayout.LayoutParams myParam = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, 400);            myParam.gravity = Gravity.CENTER;            myView.setLayoutParams(myParam);            //myFrameLayout 作为rootView            FrameLayout myFrameLayout = new FrameLayout(this);            //设置配景为绿色            myFrameLayout.setBackgroundColor(Color.GREEN);            myFrameLayout.addView(myView);            //添加到window            wm.addView(myFrameLayout, layoutParams);            //步调二            Handler handler = new Handler(Looper.myLooper());            handler.postDelayed(()->{myView.setText("子线程更新view");},5000);            Looper.loop();        }).start();    }验证效果如下图,效果符合预期,在子线程中实现了UI的添加和更新:

1.png 总结

1.Android更新UI利用的线程要和创建ViewRootImpl的线程同等;
2.当火线程要开启了Loop循环,由于UI刷新依赖了Handler机制;
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-10-18 18:26, Processed in 0.196647 second(s), 35 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表