Android - 使用 FragmentActivity 的问题 +用于更新 FragmentStatePagerAdapter 的加载器

发布于 2024-12-09 19:19:02 字数 1578 浏览 1 评论 0原文

我正在尝试将 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();
    }
}

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

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 值不为 null,并且当结果返回到 onLoadFinished 时,它被设置在 LoaderManagerImpl.LoaderInfo 中>

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

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

请注意,如果我不使用 Loader,而是在 AsyncTask 中运行加载操作,则我的代码可以正常工作

I'm trying to use FragmentActivity with ViewPager to display dynamic list of Fragments. There are plenty of examples on how to do a static version of it. My problem is that the list I display needs to be loaded dynamically and also can change based on user input (add/delete). I'm trying to use customized android.support.v4.content.Loader to load set of data that I can use to build my list.

Everything goes fine in my setup until I get to the point when I want to update the adapter and issue FragmentStatePagerAdapter#notifyDataSetChanged() call at which point this code is executed (from FragmentStatePagerAdapter)

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

The transaction commit fails with this message:

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

because within FragmentManagerImpl this code is executed:

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

It turns out that mNoTransactionsBecause value is not null and it is set in LoaderManagerImpl.LoaderInfo when the result is returned back to onLoadFinished

I was looking at the various variables trying to somehow change tramsaction.commit() to transaction.commitAllowingStateLoss() but everything related to transaction seems to be private or at least package-protected.

Can someone give me a general idea if I can do what I need to do (and how)?

Just to note that my code works fine if instead of using Loader I run the loading ops in AsyncTask

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

掐死时间 2024-12-16 19:19:02

我遇到了与此非常相似的问题,并通过在片段上使用处理程序解决了它。

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

I had a very similar problem to this and solved it by using a handler on the Fragment.

I wanted to show an alert dialog on onLoadFinished(), similar to the following

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");

    }
}

But this gave an error

can not perform this action inside of onLoadFinished

The solution was to add a handler to the fragment to take care of showing the dialog

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

And then modify onLoadFinished(...) to send a message to the handler instead

   public void onLoadFinished(Loader<T> loader, T data) {
        handler.sendEmptyMessage(MSG_SHOW_DIALOG);
    }
ˉ厌 2024-12-16 19:19:02

您可以复制 FragmentStatePagerAdapter 并根据需要进行更改,或者从头开始创建自己的 PagerAdapter。或者干脆不使用装载机。

You can copy FragmentStatePagerAdapter and change it however you like, or create your own PagerAdapter from scratch. Or simply don't use a Loader.

鱼忆七猫命九 2024-12-16 19:19:02

它使用 rootView.post() 工作。只需在类作用域中定义 rootView 变量,然后在 CreateView() 上对其进行扩充。
最后 onLoadFinished() 只需像这样使用它:

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

            });

It works using rootView.post(). Just define rootView variable in class scope and then inflate it onCreateView().
Finally onLoadFinished() simply use it like this:

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

            });
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文