ListView 的 performItemClick() 在 onLoadFinished() 内部调用时导致 IllegalStateException
ListView's performItemClick() causes IllegalStateException when called inside onLoadFinished()
我正在实施此 Two Pane UI。左窗格中的列表视图由加载程序填充。单击列表项时,右侧窗格会显示有关该项目的详细信息。
我想将左侧窗格中的第一项设置为默认选中,其详细信息显示在右侧窗格中。为此,我尝试在我的列表中调用 performItemClick()
,如下所示:
listView.performItemClick(listView,
ListView.SCROLLBAR_POSITION_DEFAULT,
listView.getItemIdAtPosition(ListView.SCROLLBAR_POSITION_DEFAULT));
我在加载程序的 onLoadFinished()
方法中执行此操作,因为这是我可以合理确定列表视图已填充的点。此方法在 UI 线程中运行,所以我没想到会出现任何问题。但是我收到 java.lang.IllegalStateException
错误。
我想知道为什么在 onLoadFinished()
中执行点击操作会导致异常,而列表视图上的其他调用如 smoothScrollToPosition()
会完成。
从其他 SO 帖子中我可以看到可以使用 Handler()
来完成。但我不清楚为什么滚动列表可以通过直接调用来完成,但单击一个项目需要通过 Handler()
发布到消息队列。我是 Android 的新手,对其架构的理解存在差距。
这是失败的完整代码:
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
//Update the adapter
mForecastAdapter.swapCursor(data);
//If there is some item in the list that was selected before then scroll to it
if(lastSelectedIndex != ListView.INVALID_POSITION) {
//Restore to last scrolled position
// Get a reference to the ListView, and attach this adapter to it.
ListView listView = (ListView) getActivity().findViewById(R.id.listview_forecast);
listView.smoothScrollToPosition(lastSelectedIndex);
}
//select the first element if two pane is supported and last state doesn't exist
else if(!mUseTodayLayout) {
ListView listView = (ListView) getActivity().findViewById(R.id.listview_forecast);
listView.performItemClick(listView,
ListView.SCROLLBAR_POSITION_DEFAULT,
listView.getItemIdAtPosition(ListView.SCROLLBAR_POSITION_DEFAULT));
}
}
堆栈跟踪粘贴在下面:
java.lang.IllegalStateException: Can not perform this action inside of onLoadFinished
at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1369)
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1383)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:636)
at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:615)
at com.example.android.sunshine.app.MainActivity.onListItemClicked(MainActivity.java:200)
at com.example.android.sunshine.app.ForecastFragment.onLoadFinished(ForecastFragment.java:285)
at com.example.android.sunshine.app.ForecastFragment.onLoadFinished(ForecastFragment.java:46)
at android.support.v4.app.LoaderManagerImpl$LoaderInfo.callOnLoadFinished(LoaderManager.java:427)
at android.support.v4.app.LoaderManagerImpl$LoaderInfo.onLoadComplete(LoaderManager.java:395)
at android.support.v4.content.Loader.deliverResult(Loader.java:104)
at android.support.v4.content.CursorLoader.deliverResult(CursorLoader.java:73)
at android.support.v4.content.CursorLoader.deliverResult(CursorLoader.java:35)
at android.support.v4.content.AsyncTaskLoader.dispatchOnLoadComplete(AsyncTaskLoader.java:223)
at android.support.v4.content.AsyncTaskLoader$LoadTask.onPostExecute(AsyncTaskLoader.java:61)
at android.support.v4.content.ModernAsyncTask.finish(ModernAsyncTask.java:461)
at android.support.v4.content.ModernAsyncTask.access0(ModernAsyncTask.java:47)
at android.support.v4.content.ModernAsyncTask$InternalHandler.handleMessage(ModernAsyncTask.java:474)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5257)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
IllegalStateException
的发生不是因为调用 listView.performItemClick()
,而是因为此调用最终导致了片段事务。 onLoadFinished()
之类的异步回调中不允许片段事务。我找到了一些有用的信息 here.
我正在实施此 Two Pane UI。左窗格中的列表视图由加载程序填充。单击列表项时,右侧窗格会显示有关该项目的详细信息。
我想将左侧窗格中的第一项设置为默认选中,其详细信息显示在右侧窗格中。为此,我尝试在我的列表中调用 performItemClick()
,如下所示:
listView.performItemClick(listView,
ListView.SCROLLBAR_POSITION_DEFAULT,
listView.getItemIdAtPosition(ListView.SCROLLBAR_POSITION_DEFAULT));
我在加载程序的 onLoadFinished()
方法中执行此操作,因为这是我可以合理确定列表视图已填充的点。此方法在 UI 线程中运行,所以我没想到会出现任何问题。但是我收到 java.lang.IllegalStateException
错误。
我想知道为什么在 onLoadFinished()
中执行点击操作会导致异常,而列表视图上的其他调用如 smoothScrollToPosition()
会完成。
从其他 SO 帖子中我可以看到可以使用 Handler()
来完成。但我不清楚为什么滚动列表可以通过直接调用来完成,但单击一个项目需要通过 Handler()
发布到消息队列。我是 Android 的新手,对其架构的理解存在差距。
这是失败的完整代码:
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
//Update the adapter
mForecastAdapter.swapCursor(data);
//If there is some item in the list that was selected before then scroll to it
if(lastSelectedIndex != ListView.INVALID_POSITION) {
//Restore to last scrolled position
// Get a reference to the ListView, and attach this adapter to it.
ListView listView = (ListView) getActivity().findViewById(R.id.listview_forecast);
listView.smoothScrollToPosition(lastSelectedIndex);
}
//select the first element if two pane is supported and last state doesn't exist
else if(!mUseTodayLayout) {
ListView listView = (ListView) getActivity().findViewById(R.id.listview_forecast);
listView.performItemClick(listView,
ListView.SCROLLBAR_POSITION_DEFAULT,
listView.getItemIdAtPosition(ListView.SCROLLBAR_POSITION_DEFAULT));
}
}
堆栈跟踪粘贴在下面:
java.lang.IllegalStateException: Can not perform this action inside of onLoadFinished
at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1369)
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1383)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:636)
at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:615)
at com.example.android.sunshine.app.MainActivity.onListItemClicked(MainActivity.java:200)
at com.example.android.sunshine.app.ForecastFragment.onLoadFinished(ForecastFragment.java:285)
at com.example.android.sunshine.app.ForecastFragment.onLoadFinished(ForecastFragment.java:46)
at android.support.v4.app.LoaderManagerImpl$LoaderInfo.callOnLoadFinished(LoaderManager.java:427)
at android.support.v4.app.LoaderManagerImpl$LoaderInfo.onLoadComplete(LoaderManager.java:395)
at android.support.v4.content.Loader.deliverResult(Loader.java:104)
at android.support.v4.content.CursorLoader.deliverResult(CursorLoader.java:73)
at android.support.v4.content.CursorLoader.deliverResult(CursorLoader.java:35)
at android.support.v4.content.AsyncTaskLoader.dispatchOnLoadComplete(AsyncTaskLoader.java:223)
at android.support.v4.content.AsyncTaskLoader$LoadTask.onPostExecute(AsyncTaskLoader.java:61)
at android.support.v4.content.ModernAsyncTask.finish(ModernAsyncTask.java:461)
at android.support.v4.content.ModernAsyncTask.access0(ModernAsyncTask.java:47)
at android.support.v4.content.ModernAsyncTask$InternalHandler.handleMessage(ModernAsyncTask.java:474)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5257)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
IllegalStateException
的发生不是因为调用 listView.performItemClick()
,而是因为此调用最终导致了片段事务。 onLoadFinished()
之类的异步回调中不允许片段事务。我找到了一些有用的信息 here.