Подтвердить что ты не робот

Android - проблемы с использованием FragmentActivity + Loader для обновления FragmentStatePagerAdapter

Я пытаюсь использовать FragmentActivity с ViewPager для отображения динамического списка Fragments. Существует множество примеров того, как сделать статическую версию. Моя проблема в том, что отображаемый список должен быть загружен динамически, а также может меняться на основе пользовательского ввода (добавить/удалить). Я пытаюсь использовать настраиваемый android.support.v4.content.Loader для загрузки набора данных, который я могу использовать для создания моего списка.

Все будет хорошо в моей настройке, пока я не дойду до того момента, когда я хочу обновить адаптер и выпустить вызов FragmentStatePagerAdapter#notifyDataSetChanged(), в этот момент этот код выполняется (от FragmentStatePagerAdapter)

public void finishUpdate(View container)
{
    if(mCurTransaction != null)
    {
        mCurTransaction.commit(); // BANG!!! The exception is thrown
        mCurTransaction = null;
        mFragmentManager.executePendingTransactions();
    }
}

С этим сообщением происходит сбой транзакции:

java.lang.IllegalStateException: Can not perform this action inside of onLoadFinished

потому что внутри FragmentManagerImpl выполняется этот код:

private void checkStateLoss() {
    if (mStateSaved) {
        throw new IllegalStateException(
                "Can not perform this action after onSaveInstanceState");
    }
    if (mNoTransactionsBecause != null) {
        throw new IllegalStateException(
                "Can not perform this action inside of " + mNoTransactionsBecause);
    }
}

Оказывается, что значение mNoTransactionsBecause не равно null, и оно устанавливается в LoaderManagerImpl.LoaderInfo, когда результат возвращается к onLoadFinished

Я рассматривал различные переменные, пытающиеся каким-то образом изменить tramsaction.commit() на transaction.commitAllowingStateLoss(), но все, что связано с транзакцией, кажется закрытым или, по крайней мере, защищенным пакетом.

Может ли кто-нибудь дать мне общую идею, могу ли я сделать то, что мне нужно сделать (и как)?

Просто отметим, что мой код работает отлично, если вместо использования Loader я запускаю ops загрузки в AsyncTask

4b9b3361

Ответ 1

У меня была очень схожая проблема с этим и решила его, используя обработчик на фрагменте.

Я хотел показать диалоговое окно предупреждения onLoadFinished(), похожее на следующее

public class MyFragment extends Fragment 
    implements LoaderManager.LoaderCallbacks<T> {

    public void onLoadFinished(Loader<T> loader, T data) {
        showDialog();
    }

    public void showDialog() {
        MyAlertDialogFragment fragment = new MyAlertDialogFragment();
        fragment.show(getActivity().getSupportFragmentManager(), "dialog");

    }
}

Но это дало ошибку

не может выполнить это действие внутри onLoadFinished

Решение заключалось в том, чтобы добавить обработчик к фрагменту, чтобы позаботиться о отображении диалога

private Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        if(msg.what == MSG_SHOW_DIALOG) {
            showDialog();
        }
    }
};

И затем измените onLoadFinished (...), чтобы отправить сообщение обработчику вместо

   public void onLoadFinished(Loader<T> loader, T data) {
        handler.sendEmptyMessage(MSG_SHOW_DIALOG);
    }

Ответ 2

Вы можете скопировать FragmentStatePagerAdapter и изменить его, как вам нравится, или создать свой собственный PagerAdapter с нуля. Или просто не используйте Loader.

Ответ 3

Работает с использованием rootView.post(). Просто определите переменную rootView в области класса, а затем раздуйте ее onCreateView(). Наконец onLoadFinished() просто используйте его следующим образом:

            rootView.post(new Runnable() {
                public void run() {
                    General.showFragment();
                }

            });