【发布时间】:2013-11-15 05:28:43
【问题描述】:
我在 onStart() 方法中启动了一个 AsyncTask,因为我希望它在用户返回到该 Fragment 时始终从 SQLite 数据库重新加载数据。这是因为它是一个 ListFragment,并且单击一个项目会在平板电脑上的双窗格布局中显示另一个 Fragment,或者会在列表中的所有项目上使用 ViewPager 的 Activity。在后一种情况下,我需要重新加载项目,因为用户可以从 ViewPager 中删除项目。
现在我正在各种设备和 API 上测试我的布局。
在 Froyo (API 8) NexusOne AVD 上,如果我旋转屏幕一次,它会再次启动 AsyncTask 并重新显示数据。如果我再做一次,我会得到一个 NullPointerException。当我使用 API 10+ 启动另一个 AVD 时,不会发生这种情况(我可以随意旋转显示器)。我给了它足够的时间来完成第一次轮换,然后再进行第二次轮换。
这里是 LogCat:
11-14 21:03:46.485: E/AndroidRuntime(326): FATAL EXCEPTION: main
11-14 21:03:46.485: E/AndroidRuntime(326): java.lang.NullPointerException
11-14 21:03:46.485: E/AndroidRuntime(326): at android.widget.ArrayAdapter.init(ArrayAdapter.java:271)
11-14 21:03:46.485: E/AndroidRuntime(326): at android.widget.ArrayAdapter.<init>(ArrayAdapter.java:150)
11-14 21:03:46.485: E/AndroidRuntime(326): at com.android.myapp.MyListFragment$MyAdapter.<init>(MyListFragment.java:279)
11-14 21:03:46.485: E/AndroidRuntime(326): at com.android.myapp.MyListFragment$getMyAsync.onPostExecute(MyListFragment.java:393)
11-14 21:03:46.485: E/AndroidRuntime(326): at com.android.myapp.MyListFragment$getMyAsync.onPostExecute(MyListFragment.java:1)
11-14 21:03:46.485: E/AndroidRuntime(326): at android.os.AsyncTask.finish(AsyncTask.java:417)
11-14 21:03:46.485: E/AndroidRuntime(326): at android.os.AsyncTask.access$300(AsyncTask.java:127)
11-14 21:03:46.485: E/AndroidRuntime(326): at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:429)
11-14 21:03:46.485: E/AndroidRuntime(326): at android.os.Handler.dispatchMessage(Handler.java:99)
11-14 21:03:46.485: E/AndroidRuntime(326): at android.os.Looper.loop(Looper.java:123)
11-14 21:03:46.485: E/AndroidRuntime(326): at android.app.ActivityThread.main(ActivityThread.java:4627)
11-14 21:03:46.485: E/AndroidRuntime(326): at java.lang.reflect.Method.invokeNative(Native Method)
11-14 21:03:46.485: E/AndroidRuntime(326): at java.lang.reflect.Method.invoke(Method.java:521)
11-14 21:03:46.485: E/AndroidRuntime(326): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
11-14 21:03:46.485: E/AndroidRuntime(326): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
11-14 21:03:46.485: E/AndroidRuntime(326): at dalvik.system.NativeStart.main(Native Method)
MyListFragment.java:279 是对 ArrayAdapter.constructor [EDIT]
的调用super(context, 0, myListArray);
onPostExecute(MyListFragment.java:393 是这样的:
mAdapter = new MyAdapter(getActivity(), myListArray);
如果 myListArray 为 null,则不会执行上述操作。
我在该指令上方添加了这个:
if (getActivity() == null) {
Log.d(TAG, "getActivity() is null");
}
getActivity() 在 API 8 设备上返回 null!
这只是 Eclipse/ADT 和/或 AVD 测试环境的错误吗?或者它也会发生在真实的手机上?
谢谢。
编辑
启动AsyncTask的方法:
@Override
public void onStart() {
super.onStart();
mProgressBarLayout.setVisibility(View.VISIBLE);
new getListAsync().execute(mType);
}
AsyncTask(ListFragment 的内部私有类):
private class getListAsync extends AsyncTask<EFFECT_TYPE, Void, List<Item>> {
@Override
protected List<Item> doInBackground(EFFECT_TYPE... params) {
List<Item> items;
items = DatabaseManager.get(getActivity()).getItems(params[0]);
return items;
}
@Override
protected void onPostExecute(List<Item> result) {
super.onPostExecute(result);
mProgressBarLayout.setVisibility(View.GONE);
mItemList = result;
if (mItemList != null) {
if (getActivity() == null) {
Log.d(TAG, "getActivity() is null"); <---- THIS GETS LOGGED ON THE 2nd ROTATE!
}
393 -----------> mAdapter = new MyAdapter(getActivity(), mItemList);
setListAdapter(mAdapter);
}
}
}
编辑#2
嗯,这是不可能的。
我已经有了 onAttach(),所以我这样做了:
向 MyListFragment 添加一个新变量:
private Activity mParentActivity = null;
修改了onAttach():
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mCallbacks = (Callbacks) activity;
mParentActivity = activity;
if (mParentActivity == null) {
Log.d(TAG, "onAttach() called with null Activity");
}
}
onPostExecute:
@Override
protected void onPostExecute(List<Item> result) {
super.onPostExecute(result);
mProgressBarLayout.setVisibility(View.GONE);
mItemList = result;
if (mItemList != null) {
if (mParentActivity == null) {
Log.d(TAG, "mParentActivity is null");
}
mAdapter = new MyAdapter(mParentActivity, mItemList);
setListAdapter(mAdapter);
}
}
}
mParentActivity 在那里为 NULL!即使 onAttach() 在到达 onStart() 方法之前使用有效的 Activity 成功执行。
AsyncTask 在 API 8 上被破坏。
【问题讨论】:
-
你在调用 super.. 时发现什么变量是 null..?
-
是的,上下文。请看我帖子的底部。
-
您应该发布更多关于如何/何时尝试使用上下文的代码。
-
就在那儿。我在构造函数中做了一个 getActivity()。
-
getActivity() 可能有效也可能无效,具体取决于您调用它的位置。你在调用什么 getActivity() ?还有一个建议是在设备上尝试这个,它也可能是对模拟器的限制。