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
Ответы
Ответ 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();
}
});