Android-使用FragmentActivity+;加载程序更新FragmentStatePagerAdapter

Android-使用FragmentActivity+;加载程序更新FragmentStatePagerAdapter,android,android-viewpager,Android,Android Viewpager,我正在尝试使用FragmentActivity和ViewPager来显示片段的动态列表。有很多关于如何做它的静态版本的例子。我的问题是,我显示的列表需要动态加载,并且可以根据用户输入(添加/删除)进行更改。我正在尝试使用定制的android.support.v4.content.Loader加载一组数据,我可以使用这些数据来构建我的列表 在我的设置中一切正常,直到我要更新适配器并发出FragmentStatePagerAdapter#notifyDataSetChanged()调用执行此代码的点

我正在尝试使用
FragmentActivity
ViewPager
来显示
片段的动态列表。有很多关于如何做它的静态版本的例子。我的问题是,我显示的列表需要动态加载,并且可以根据用户输入(添加/删除)进行更改。我正在尝试使用定制的
android.support.v4.content.Loader
加载一组数据,我可以使用这些数据来构建我的列表

在我的设置中一切正常,直到我要更新适配器并发出
FragmentStatePagerAdapter#notifyDataSetChanged()
调用执行此代码的点(从
FragmentStatePagerAdapter

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

java.lang.IllegalStateException:无法在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
值不为空,当结果返回到
onLoadFinished
时,它在
LoaderManagerImpl.LoaderInfo
中设置

我正在查看各种变量,试图以某种方式将
tramsaction.commit()
更改为
transaction.commitAllowingStateLoss()
,但与事务相关的一切似乎都是私有的,或者至少是包保护的

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


需要注意的是,如果不是使用Loader,而是在AsyncTask中运行loading ops,那么我的代码工作得很好,您可以复制
FragmentStatePagerAdapter
并随意更改它,或者从头创建自己的
PagerAdapter
。或者干脆不使用加载程序。

我遇到了一个与此非常类似的问题,通过在片段上使用处理程序解决了这个问题

我想在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(…),改为向处理程序发送消息

   public void onLoadFinished(Loader<T> loader, T data) {
        handler.sendEmptyMessage(MSG_SHOW_DIALOG);
    }
public void onLoadFinished(加载程序,T数据){
handler.sendEmptyMessage(消息显示对话框);
}

它使用rootView.post()工作。只需在类作用域中定义rootView变量,然后在CreateView()中将其膨胀即可。 最后,onLoadFinished()只需如下使用:

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

            });

这不是适配器的问题,它所做的只是提交事务。但有人付出了相当大的努力来防止onLoadFinished中的事务提交。我想知道为什么?我也不喜欢为了一行代码而重写类,我喜欢加载器的概念并希望使用它。正如我所说的-我确实直接使用AsyncTask实现了工作,这显然是因为在调用
onLoadFinished()
时存在状态丢失的可能性。从JavaDoc:'注意,通常不允许应用程序在此调用中提交片段事务,因为它可以在保存活动状态后发生。请参阅FragmentManager.openTransaction()以了解有关此问题的进一步讨论。”您必须更改为适配器以使用
commitAllowingStateLoss()
或废弃加载程序。我也有同样的问题,下面是我得到的答案:你能想出正确的方法来使用装载机吗?我也面临同样的问题。我可以使用
transaction.commitAllowingStateLoss()
使其正常工作,但如果能知道Google打算让我们做什么,我们还是会很高兴的…似乎应该有一种方法在使用加载程序加载数据后执行片段事务…我通常放弃了这一点,现在使用的是具有有限池的ModernTaskLoader什么是ModernTaskLoader?在任何地方都找不到有关它的任何信息…这是来自兼容包v4Hmm…我在支持包中看到的仅有两个加载程序是AsyncTaskLoader和CursorLoader:/或者您将runnable发布到处理程序上<代码>处理程序h=新处理程序(Looper.getMainLooper());h、 post(新的Runnable(){…})etc@Chris.JenkinsIan的实现更高效,因为它只需要一个对象分配。:)@AlexLockwood不是一个真正的问题,除非在高性能场景中一次命中创建1000个对象。另外,请注意,此解决方案只会避免异常。它实际上并不能防止片段状态丢失。如果调用了
onLoadFinished()
,则会发布runnable,并在调用了
onSaveInstanceState()
之后执行
对话框片段#show()
代码(这种情况很少见,但可能仍然存在),随后恢复
活动
的状态时,将不会记住
对话框片段
的状态。通常,您可能希望避免在
onLoadFinished()
中显示对话框(不管怎样,这对用户体验是有害的)!这适用于
FragmentStatePagerAdapter
,不适用于
FragmentPagerAdapter
。幸运的是,OP使用的是正确的。但我在这上面花了几个小时。
   public void onLoadFinished(Loader<T> loader, T data) {
        handler.sendEmptyMessage(MSG_SHOW_DIALOG);
    }
            rootView.post(new Runnable() {
                public void run() {
                    General.showFragment();
                }

            });