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();
}
});