【发布时间】:2014-01-30 22:30:14
【问题描述】:
我编写了一个相当大的自定义视图,它覆盖了onSaveInstanceState() 和onRestoreInstanceState(Parcelable state)。
我想用我的自定义视图填充一个 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,它将在 doInBackground() 中创建一个 MyCustomView 的实例并将其添加到主布局(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 的onSaveInstanceState() 和onRestoreInstanceState(Parcelable state) 中放置了一个Log.d(...),我注意到onRestoreInstanceState(Parcelable state) 没有被调用。
您知道为什么当我使用 AsyncTask 填充 mRootLayout 时没有调用 onRestoreInstanceState(Parcelable state),但是当我在界面线程?
谢谢。
编辑:我发布了MyCustomView 的onSaveInstanceState() 和onRestoreInstanceState() 方法
@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);
}
【问题讨论】:
标签: java android multithreading android-asynctask