gar*_*daf 1 debugging multithreading android
是的,它不应该,但我在我的mainActivityin中制作的线程onCreate可以修改UI,如下所示:
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
someTextview.setText("Hello");
}
});
thread.start();
Run Code Online (Sandbox Code Playgroud)
我正在使用android studio 2.2.2.
简短的回答:只要你在mainthread输入onResume()之前就可以做到这一点
详情:
通常,在从非UI线程修改UI时会出现类似这样的错误
android.view.ViewRootImpl$CalledFromWrongThreadException:
Only the original thread that created a view hierarchy can touch its views.
Run Code Online (Sandbox Code Playgroud)
这个异常在ViewRootImpl课堂上抛出来了
void checkThread() {
if (mThread != Thread.currentThread()) {
throw new CalledFromWrongThreadException(
"Only the original thread that created a view hierarchy can touch its views.");
}
}
Run Code Online (Sandbox Code Playgroud)
这mThread是主线程.ViewRootImpl创建实例后,UI修改操作将需要检查线程.
那么什么时候ViewRootImpl创建了实例?
android.view.WindowManagerImpl.java
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}
Run Code Online (Sandbox Code Playgroud)
android.view.WindowManagerGlobal.java
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
...
ViewRootImpl root;
...
root = new ViewRootImpl(view.getContext(), display);
...
}
Run Code Online (Sandbox Code Playgroud)
那么这个addView方法何时被调用?
android.app.ActivityThread.java
final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
...
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (r.mPreserveWindow) {
a.mWindowAdded = true;
r.mPreserveWindow = false;
// Normally the ViewRoot sets up callbacks with the Activity
// in addView->ViewRootImpl#setView. If we are instead reusing
// the decor view we have to notify the view root that the
// callbacks may have changed.
ViewRootImpl impl = decor.getViewRootImpl();
if (impl != null) {
impl.notifyChildRebuilt();
}
}
if (a.mVisibleFromClient && !a.mWindowAdded) {
a.mWindowAdded = true;
wm.addView(decor, l);
}
}
Run Code Online (Sandbox Code Playgroud)
.
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
...
case RESUME_ACTIVITY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
SomeArgs args = (SomeArgs) msg.obj;
handleResumeActivity((IBinder) args.arg1, true, args.argi1 != 0, true,
args.argi3, "RESUME_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
...
}
Object obj = msg.obj;
if (obj instanceof SomeArgs) {
((SomeArgs) obj).recycle();
}
if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));
}
Run Code Online (Sandbox Code Playgroud)
在这里你可以看到ViewRootImpl实例是围绕RESUME_ACTIVITY事件创建的,所以在主线程处理resume事件之前,你可以从其他线程修改UI.你只需要快点.
但不建议这样做.
| 归档时间: |
|
| 查看次数: |
966 次 |
| 最近记录: |