Функция executeItemClick() ListView вызывает исключение IllegalStateException при вызове внутри onLoadFinished()

Я реализую этот двухпанельный интерфейс. Представление списка на левой панели заполняется загрузчиком. При щелчке элемента списка на правой панели отображаются сведения об этом элементе.

Я хочу установить первый элемент на левой панели, который будет выбран по умолчанию, и его детали, которые будут показаны на правой панели. Для этого я попытался позвонить performItemClick() в моем списке вот так:

listView.performItemClick(listView,
                          ListView.SCROLLBAR_POSITION_DEFAULT,
                          listView.getItemIdAtPosition(ListView.SCROLLBAR_POSITION_DEFAULT));

Я делаю это в onLoadFinished() метод моего загрузчика, потому что это точка, в которой я могу быть достаточно уверен, что представление списка заполнено. Этот метод работает в потоке пользовательского интерфейса, поэтому я не ожидал никаких сбоев. Однако я получаю 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.access$500(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)

1 ответ

Решение

IllegalStateException происходит не из-за вызова listView.performItemClick() но потому что этот вызов в конечном счете вызывал транзакцию фрагмента. Транзакции фрагментов запрещены в асинхронных обратных вызовах, таких как onLoadFinished(), Я нашел некоторую полезную информацию здесь.

Другие вопросы по тегам