让我们一起看看代码吧!
首先,CalledFromWrongThreadException这个异常是有下面的代码抛出的:
view source
void checkThread() {
if (mThread != Thread.currentThread()) {
throw new CalledFromWrongThreadException(
"Only the original thread that created a view hierarchy can touch its views.");
}
}
该段代码出自 framework/base/core/java/android/view/ViewRoot.java
其次,看看RootView的构造函数:
public ViewRoot(Context context) {
super();
if (MEASURE_LATENCY && lt == null) {
lt = new LatencyTimer(100, 1000);
}
// For debug only
//++sInstanceCount;
// Initialize the statics when this class is first instantiated. This is
// done here instead of in the static block because Zygote does not
// allow the spawning of threads.
getWindowSession(context.getMainLooper());
mThread = Thread.currentThread();
mLocation = new WindowLeaked(null);
mLocation.fillInStackTrace();
mWidth = -1;
mHeight = -1;
mDirty = new Rect();
mTempRect = new Rect();
mVisRect = new Rect();
mWinFrame = new Rect();
mWindow = new W(this, context);
mInputMethodCallback = new InputMethodCallback(this);
mViewVisibility = View.GONE;
mTransparentRegion = new Region();
mPreviousTransparentRegion = new Region();
mFirst = true; // true for the first time the view is added
mAdded = false;
mAttachInfo = new View.AttachInfo(sWindowSession, mWindow, this, this);
mViewConfiguration = ViewConfiguration.get(context);
mDensity = context.getResources().getDisplayMetrics().densityDpi;
}
最后,我们看看ViewRoot.checkThread的调用顺序:
com.david.test.helloworld.MainActivity$TestThread2.run
-> android.widget.TextView.setText
-> android.widget.TextView.checkForRelayout
-> android.view.View.invalidate
-> android.view.ViewGroup.invalidateChild
-> android.view.ViewRoot.invalidateChildInParent
-> android.view.ViewRoot.invalidateChild
-> android.view.ViewRoot.checkThread
到这里相信网友已经明白CalledFromWrongThreadException为什么出现了。那到底非主线程以外的线程能否刷新UI呢?呵呵,答案当然是能,前提条件是它要拥有自己的ViewRoot。如果你要直接创建ViewRoot的实例的话,你会失望的发现不能找到这个类。那么我们要如何做呢?让我们用实例来说说吧,代码如下:
class TestThread1 extends Thread{
@Override
public void run() {
Looper.prepare();
TextView tx = new TextView(MainActivity.this);
tx.setText("test11111111111111111");
WindowManager wm = MainActivity.this.getWindowManager();
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
250, 250, 200, 200, WindowManager.LayoutParams.FIRST_SUB_WINDOW,
WindowManager.LayoutParams.TYPE_TOAST,PixelFormat.OPAQUE);
wm.addView(tx, params);
Looper.loop();
}
}
MainActivity是建立android工程时生成的入口类,TestThread1是MainActivity的内部类。感兴趣的话,试试吧!看看是不是在屏幕上看到了"test11111111111111111"?
最后,说说那里创建了ViewRoot,这里:wm.addView(tx, params)。还是看看具体流程吧:
WindowManagerImpl.addView(View view, ViewGroup.LayoutParams params)
-> WindowManagerImpl.addView(View view, ViewGroup.LayoutParams params, boolean nest),奥妙就在这里,具体看看代码吧!
private void addView(View view, ViewGroup.LayoutParams params, boolean nest)
{
if (Config.LOGV) Log.v("WindowManager", "addView view=" + view);
if (!(params instanceof WindowManager.LayoutParams)) {
throw new IllegalArgumentException(
"Params must be WindowManager.LayoutParams");
}
final WindowManager.LayoutParams wparams
= (WindowManager.LayoutParams)params;
ViewRoot root;
View panelParentView = null;
synchronized (this) {
// Here's an odd/questionable case: if someone tries to add a
// view multiple times, then we simply bump up a nesting count
// and they need to remove the view the corresponding number of
// times to have it actually removed from the window manager.
// This is useful specifically for the notification manager,
// which can continually add/remove the same view as a
// notification gets updated.
int index = findViewLocked(view, false);
if (index >= 0) {
if (!nest) {
throw new IllegalStateException("View " + view
+ " has already been added to the window manager.");
}
root = mRoots[index];
root.mAddNesting++;
// Update layout parameters.
view.setLayoutParams(wparams);
root.setLayoutParams(wparams, true);
return;
}
// If this is a panel window, then find the window it is being
// attached to for future reference.
if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
final int count = mViews != null ? mViews.length : 0;
for (int i=0; i<count; i++) {
if (mRoots[i].mWindow.asBinder() == wparams.token) {
panelParentView = mViews[i];
}
}
}
root = new ViewRoot(view.getContext());
root.mAddNesting = 1;
view.setLayoutParams(wparams);
if (mViews == null) {
index = 1;
mViews = new View[1];
mRoots = new ViewRoot[1];
mParams = new WindowManager.LayoutParams[1];
} else {
index = mViews.length + 1;
Object[] old = mViews;
mViews = new View[index];
System.arraycopy(old, 0, mViews, 0, index-1);
old = mRoots;
mRoots = new ViewRoot[index];
System.arraycopy(old, 0, mRoots, 0, index-1);
old = mParams;
mParams = new WindowManager.LayoutParams[index];
System.arraycopy(old, 0, mParams, 0, index-1);
}
index--;
mViews[index] = view;
mRoots[index] = root;
mParams[index] = wparams;
}
// do this last because it fires off messages to start doing things
root.setView(view, wparams, panelParentView);
}
出自:frameworks/base/core/java/android/view/WindowManagerImpl.java
Ok,相信到了这里,大家都已经明白了:子线程是能够刷新UI的!!!
相关推荐
C#(winform)里子窗体修改父窗体(子窗体刷新父窗体数
遍历已知父窗里子窗所有句柄 的实例
Excel文件的导入,根据Excel里子表的选择用异步线程加载数据。
从“里子”怎么看出口?_&出口研判系列九:外需变化是“表”,结构变化是“里”(34页).pdf
20210706-华创证券-从“里子”怎么看出口?_&出口研判系列九:外需变化是“表”,结构变化是“里”.pdf
scrollView 里子view 划出屏幕后的操作,类似页面有视频,当视频不可见的时候暂停播放
行业分类-电子-一种抗静电里子绸的生产工艺
维度表与事实表组合在一起,形成了星型模型,如下图:数据仓库的设计(一) | 面子与里子对其进行查询操作的SQL语句如下:sum(sales_facts.sale
公交的“面子”地铁的“里子”——金华新能源地铁巴士运营看点多.pdf
主要介绍了详解VUE里子组件如何获取父组件动态变化的值,子组件通过props获取父组件传过来的数据,子组件存在操作传过来的数据并且传递给父组件,需要的朋友可以参考下
1. 选择业务过程:样例中管理层想要了解POS系统中顾客的购买情况,因此业务过程就是 2. 定义粒度:样例中就是粒度定义为POS上发生的第一笔交易,这样可以最大
基于图形变换原理,对自动配裁服装里子样板模型中各型值点的确定,提出了“动态”变换矩阵模型及对特殊曲线上中间型值点进行双向柔性化处理的有效设计方法;三次样条函数作为里子样板曲线模型的设计方案。结合服装...
很好的题目里子
对于刀具比较多的零件加工程式调机方便可以对刀具分开后处理调试程式。
SPCManage是SPC系统管理端,采用的是C/S架构模式,可供SPC开发参考。
为提高图像恢复质量,提出一种量子衍生神经网络模型及算法.该模型为3层结构,隐层为量子神经元,输出层为普通神经元.量子神经元由量子旋转门和多位受控非门组成,利用多位受控非门中目标量子位的输出向输入端的反馈...
200SMART PLC在符号表中修改变量的符号名后,程序中仍然显示修改前的符号和波浪线?
3d粒子插件,解压复制进ae插件文件夹就能用,简单快捷,是一款强大的新兴里子插件
由于浮动的元素脱离了文档流,所以它们不会在网页文档中占据空间。 如果一个DIV容器中想要包含这些浮动的元素的话,有两种办法。 第一:在这个DIV容器中在某个地方使用clear; 第二:让这个DIV容器也进行浮动。