【问题标题】:RestartLoader in Fragment from FragmentActivityFragmentActivity 中的 Fragment 中的 RestartLoader
【发布时间】:2012-07-20 21:42:41
【问题描述】:

我在从 ListFragment 外部调用 restartLoader() 时遇到了一点问题。该序列按照点击“添加”按钮打开一个活动 -> 输入数据 -> 点击保存,这将启动一个 AsyncTask 以将数据存储在服务器上。数据传输成功后,返回上一个 Activity -> 让 Activity 调用 ListFragment 中运行 getLoaderManager().restartLoader() 的方法。

这总是会创建一个“java.lang.IllegalStateException: Fragment ListsFragment{42481238} not attach to Activity”-错误。如果我将 restartLoader() 移至 onResume 效果会稍微好一些,但我还有其他按钮可以直接修改连接到 ListFragments 的数据,无论如何仍然会触发 IllegalStateException。

从 logcat 中摘录错误消息

E/AndroidRuntime(29594): java.lang.IllegalStateException: Fragment ListsFragment{42450b18} not attached to Activity
E/AndroidRuntime(29594):        at android.support.v4.app.Fragment.getLoaderManager(Fragment.java:768)
E/AndroidRuntime(29594):        at testpager.ListsFragment.resetList(ListsFragment.java:122)

我错过了什么?如何在不触发此异常的情况下从 FragmentActivity 刷新 ListFragment?

【问题讨论】:

    标签: android android-fragments android-viewpager android-loadermanager


    【解决方案1】:

    您不应该从 FragmentActivity 刷新您的 ListFragment... 这违反了 Fragments 的基本设计准则(它们应该是为重用而设计的,而不是与任何特定的活动)和LoaderManager(应该属于单个ActivityFragment)。你应该让你的ListFragment 实现LoaderManager.LoaderCallbacks<D> 接口。

    另外,Loaders 应该在其基础数据源更改时接收通知,通知他们执行新的异步加载并将结果返回给回调的 onLoadFinished 方法。如果您必须依靠restartLoader 来获取最新数据,那么您做错了什么(即您的ContentObserver 没有收到通知Loader 重新查询其数据)。

    【讨论】:

    • 抱歉,我迟到了不可原谅的回复。我的项目被搁置了很长一段时间,但我正在重振它。
    • 抱歉,我迟到了不可原谅的回复。我实际上正在使用 LoaderManager.LoaderCallbacks 和 Christians Loader stackoverflow.com/questions/7182485/… 我尝试制作一个使用 Loader 但不一定包括整个内容提供程序的实现,因为我只会在我自己的应用程序中运行它。我已经读过这个stackoverflow.com/a/4245672/975641 并且似乎提供者可能为此矫枉过正。有什么想法吗?可能这是一个全新的问题。只是想澄清一下。
    • Commonsware 总是谈论 ContentProviders 的垃圾:P。争论是 CP 对于不共享其数据的应用程序来说太过分了……我几乎同意这一点,但是我真正喜欢 CP + loader 组合的一件事是它带有全球通知系统。也就是说,如果您在 CP 查询方法中调用光标上的setNotificationUri(),并在插入/删除方法中调用notifyUri(),则光标将在整个整个应用程序中收到内容更改通知(即无需投票!)。没有 ContentResolver 没有简单的方法来做到这一点。
    • 还有一堆库可以自动为你编写 CP 的大部分过程......老实说,我不认为编写 CP 真的有那么大交易。
    【解决方案2】:

    如果我理解正确,您的活动 A 创建了一个加载程序,该加载程序具有通过 Activity B 保存数据的菜单选项。一旦 Activity B 保存数据,您希望重新启动 Activity A 中的加载程序......我我说的对吗?

    如果是这样,请尝试在活动 B 中执行此操作:

    public interface onSavedDataListener { 
         void DoneSavingData(); //add parameters if needed
    }
    ... //Whatever other code you have
     //This method should be called from your AsyncTask onFinished() method
     public void dataSaved() { //add parameters if needed
        onSavedDataListener activity = (onSavedDataListener) getActivity();
        activity.DoneSavingData(); //make sure you add the same parameters as you did above
    }
    

    然后在 Activity A 中,您将实现监听器

    public class ActivityA extends ListFragment implements onSavedDataListener {
    
        ... //your other code here
    
        //Add the listener function
        public void DoneSavingData() { //make sure any parameters you have get added here
            getLoaderManager().restartLoader(id, args, loadercallback);
        }
    
        ...
    

    本质上,您在 Activity B 中创建了一个在 Activity A 中实现的侦听器对象。我希望我是对的,它会帮助您...

    【讨论】:

    • 顺便说一句,如果您使用支持包向后兼容以前的 SDK,您应该调用 getSupportLoaderManager() 来代替...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多