Android - 使用FragmentActivity + Loader更新FragmentStatePagerAdapter的问题

Bos*_*one 16 android android-viewpager

我试图用FragmentActivityViewPager显示的动态列表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();
    }
}
Run Code Online (Sandbox Code Playgroud)

事务提交失败并显示以下消息:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

事实证明,mNoTransactionsBecausevalue不为null,并在LoaderManagerImpl.LoaderInfo返回结果时设置onLoadFinished

我正在寻找各种变量试图以某种方式改变tramsaction.commit(),transaction.commitAllowingStateLoss()但与事务相关的所有内容似乎都是私有的或至少是受包保护的.

如果我可以做我需要做的事情(以及如何做),有人可以给我一个大概的想法吗?

只是要注意我的代码工作正常,如果不使用Loader我在AsyncTask中运行加载操作

Ian*_*ick 35

我有一个非常类似的问题,并通过使用片段上的处理程序解决它.

我想在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");

    }
}
Run Code Online (Sandbox Code Playgroud)

但这给了一个错误

无法在onLoadFinished中执行此操作

解决方案是在片段中添加一个处理程序来处理显示对话框

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

然后修改onLoadFinished(...)以向处理程序发送消息

   public void onLoadFinished(Loader<T> loader, T data) {
        handler.sendEmptyMessage(MSG_SHOW_DIALOG);
    }
Run Code Online (Sandbox Code Playgroud)

  • 或者您将runnable发布到处理程序上.`Handler h = new Handler(Looper.getMainLooper()); h.post(new Runnable(){....});`等 (11认同)
  • 另请注意,此解决方案仅避免异常.它实际上并不会阻止碎片状态丢失.如果调用`onLoadFinished()`,则发布runnable,并且在调用`onSaveInstanceState()`之后执行`DialogFragment#show()`代码(这可能很少见,但可能仍然可能),然后`当"活动"的状态稍后恢复时,将不会记住DialogFragment`的状态.通常,您可能希望避免在`onLoadFinished()`中显示对话框(无论如何它对用户体验都不利). (4认同)