Android子线程在没有ViewRoot的情况下能刷新UI吗?

如果你看了我写的《Android里子线程真的不能刷新UI吗? 》,会回答:不能。那么到底能不能呢?呵呵,其实是能的了。那么《Android里子线程真的不能刷新UI吗? 》里写错了吗?嗯,没有。呵呵,相信大家看到这里一定是一头雾水,认为笔者自相矛盾了。

让我们看个实例吧:

package com.david.test.helloworld;

 

import Android.app.Activity;

import android.os.Bundle;

import android.widget.Button;

 

public class TestActivity extends Activity {

    Button btn = null;

 

    /** Called when the activity is first created. */

    public void onCreate(Bundle savedInstanceState) {

       super.onCreate(savedInstanceState);

       setContentView(R.layout.main);

 

       btn = (Button) findViewById(R.id.Button01);

 

       TestThread2 t = new TestThread2(btn);

       t.start();

    }

 

    class TestThread2 extends Thread {

       Button btn = null;

 

       public TestThread2(Button btn) {

           this.btn = btn;

       }

 

       @Override

       public void run() {

           btn.setText("TestThread2.run");

       }

    }

}

建立一个工程,将上述代码拷贝进去,运行看看吧! Btn的文本一定改变为"TestThread2.run"了。

那么这到底是怎么回事呢?当我发现这个问题时,也困惑了。经过一番调查后,真相大白。现在和大家分享一下。奥秘在于ViewRoot的建立时间,它是在ActivityThread.java的final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward)里创建的。

看看代码吧:

final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {

// If we are getting ready to gc after going to the background, well

// we are back active so skip it.

unscheduleGcIdler();

ActivityRecord r = performResumeActivity(token, clearHide);

if (r != null) {

final Activity a = r.activity;

if (localLOGV) Slog.v(

TAG, "Resume " + r + " started activity: " +

a.mStartedActivity + ", hideForNow: " + r.hideForNow

+ ", finished: " + a.mFinished);

final int forwardBit = isForward ?

WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;

// If the window hasn't yet been added to the window manager,

// and this guy didn't finish itself or start another activity,

// then go ahead and add the window.

boolean willBeVisible = !a.mStartedActivity;

if (!willBeVisible) {

try {

willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible(

a.getActivityToken());

} catch (RemoteException e) {

}

}

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 (a.mVisibleFromClient) {

a.mWindowAdded = true;

wm.addView(decor, l);

}

// If the window has already been added, but during resume

// we started another activity, then don't yet make the

// window visible.

} else if (!willBeVisible) {

if (localLOGV) Slog.v(

TAG, "Launch " + r + " mStartedActivity set");

r.hideForNow = true;

}

// The window is now visible if it has been added, we are not

// simply finishing, and we are not starting another activity.

if (!r.activity.mFinished && willBeVisible

&& r.activity.mDecor != null && !r.hideForNow) {

if (r.newConfig != null) {

if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity "

+ r.activityInfo.name + " with newConfig " + r.newConfig);

performConfigurationChanged(r.activity, r.newConfig);

r.newConfig = null;

}

if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward="

+ isForward);

WindowManager.LayoutParams l = r.window.getAttributes();

if ((l.softInputMode

& WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)

!= forwardBit) {

l.softInputMode = (l.softInputMode

& (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))

| forwardBit;

if (r.activity.mVisibleFromClient) {

ViewManager wm = a.getWindowManager();

View decor = r.window.getDecorView();

wm.updateViewLayout(decor, l);

}

}

r.activity.mVisibleFromServer = true;

mNumVisibleActivities++;

if (r.activity.mVisibleFromClient) {

r.activity.makeVisible();

}

}

r.nextIdle = mNewActivities;

mNewActivities = r;

if (localLOGV) Slog.v(

TAG, "Scheduling idle handler for " + r);

Looper.myQueue().addIdleHandler(new Idler());

} else {

// If an exception was thrown when trying to resume, then

// just end this activity.

try {

ActivityManagerNative.getDefault()

.finishActivity(token, Activity.RESULT_CANCELED, null);

} catch (RemoteException ex) {

}

}

}

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwyggg.html