gpt4 book ai didi

java - 从 AsyncTask 的 onPostExecute() 将自定义 View 添加到布局后未恢复自定义 View

转载 作者:行者123 更新时间:2023-11-30 03:07:55 25 4
gpt4 key购买 nike

我写了一个相当大的自定义 View ,它覆盖了 onSaveInstanceState()onRestoreInstanceState(Parcelable state) .

我想用我的自定义 View 填充 LinearLayout,所以我编写了以下代码:

public class MainActivity extends Activity {

private LinearLayout mRootLayout;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

mRootLayout = (LinearLayout) findViewById(R.id.root_layout);

int i;

// Test: adding 10 instances of MyCustomView.
for (i = 0; i < 10; ++i) {
MyCustomView cv = new MyCustomView(this);

// I set an ID for this view so that onSaveInstanceState() and
// onRestoreInstanceState(Parcelable state) will be called
// automatically.
cv.setId(++i);

mRootLayout.addView(cv);
}
}

// ...
}

工作正常 - mRootLayout确实填充了 10 个 MyCustomView 实例,以及 MyCustomView 的每个实例例如,屏幕旋转后正在正确恢复。

我注意到,由于 MyCustomView非常大,我的代码在 UI 线程上很繁重。

为了解决这个问题并减轻 UI 线程的负担,我决定使用自定义 AsyncTask,它将创建一个 MyCustomView 的实例。在doInBackground()并将其添加到 mRootLayout 中的主布局 ( onPostExecute() ) .

下面的代码是我自定义的AsyncTask:

private class LoadMyCustomViewTask extends AsyncTask<Void, Void, MyCustomView> {

private Context mContext;
private LinearLayout mLayoutToPopulate;
private int mId;

public LoadMyCustomViewTask(Context context, LinearLayout layout, int id) {
mContext = context;
mLayoutToPopulate = layout;
mId = id;
}

@Override
protected MyCustomView doInBackground(Void... params) {

MyCustomView cv = new MyCustomView(mContext);

return cv;
}

@Override
protected void onPostExecute(MyCustomView result) {

result.setId(mId);
mLayoutToPopulate.addView(result);
}
}

MainActivity我按如下方式使用它:

public class MainActivity extends Activity {

private LinearLayout mRootLayout;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

mRootLayout = (LinearLayout) findViewById(R.id.root_layout);

int i;

for (i = 0; i < 10; ++i) {

new LoadMyCustomViewTask(this, mRootLayout, ++i).execute();
}
}
// ...
}

此代码也有效,但只有一个问题 - MyCustomView根本没有恢复。

出于调试目的,我在 MyCustomView 中放置了一个 Log.d(...)的 onSaveInstanceState()onRestoreInstanceState(Parcelable state) ,我注意到 onRestoreInstanceState(Parcelable state) 没有被调用

你知道为什么 onRestoreInstanceState(Parcelable state)当我使用 AsyncTask 填充 mRootLayout 时没有被调用, 但当我创建 MyCustomView 时它确实被调用了完全在 UI 线程上?

谢谢。

编辑:我正在发布方法 onSaveInstanceState()onRestoreInstanceState()MyCustomView

@Override
protected Parcelable onSaveInstanceState() {
debug("onSaveInstanceState()");
Bundle state = new Bundle();
state.putParcelable(_BUNDLE_KEY_PARENT_STATE, super.onSaveInstanceState());
state.putBooleanArray(_BUNDLE_KEY_CLICKED_VIEWS, mClickedViews);
return state;
}

@Override
protected void onRestoreInstanceState(Parcelable state) {
debug("onRestoreInstanceState(Parcelable state)");
if (state instanceof Bundle) {
Bundle bundle = (Bundle) state;
mClickedViews = bundle.getBooleanArray(_BUNDLE_KEY_CLICKED_VIEWS);
state = bundle.getParcelable(_BUNDLE_KEY_PARENT_STATE);
}

super.onRestoreInstanceState(state);
}

最佳答案

View 状态恢复从 Root View 开始,向下移动到当时附加的所有 subview 。这可以在 ViewGroup.dispatchRestoreInstanceState 中看到方法。这意味着 Android 只能恢复您的 View ,前提是它们当时是 View 层次结构的一部分 Activity.onRestoreInstanceState被称为。

使用 AsyncTask ,您正在异步创建 View ,然后安排它们在主循环器空闲时稍后添加。考虑到生命周期,Android 只允许你的 AsyncTask.onPostExecute追赶Activity.onStart , Activity.onRestoreInstanceState , Activity.onResume等被称为。您的 View 添加到布局的时间太晚,无法进行自动恢复。

如果您将日志语句添加到上述那些方法,以及您的 AsyncTask.onPostExecute ,您将能够看到排序/时间在现实中是如何发挥作用的。以下代码在 Activity.onRestoreInstanceState 之后运行即使这一切都发生在主线程上,仅仅是因为调度:

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...

new Handler().post(new Runnable() {
@Override
public void run() {
Log.i("TAG", "when does this run?");
}
});

...
}

关于java - 从 AsyncTask 的 onPostExecute() 将自定义 View 添加到布局后未恢复自定义 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21468814/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com