16

在 LoaderManager 中识别 Loader 时,您使用唯一的 id。我在问这些 id 必须有多独特。

每个 Activity 和 Fragment 都有自己的 LoaderManager 吗?片段是否使用它们附加到的 Activity 的 LoaderManager?应用程序是否只有一个 LoaderManager?

如果您能告诉我如何更改您正在使用的 LoaderManager,则可以加分。如果我希望我的 Activity 中的每个片段都使用相同的 LoaderManager(其中一些正在提取相同的数据并且共享 Loader 会很好),这可能吗?

4

2 回答 2

8

我目前正在将我的应用程序移植到 android 兼容包(主要用于 CursorLoader 和 Fragments)。我目前正在尝试在两个片段之间共享一个 CursorLoader,以便对我的 ContentProvider 进行查询。欢迎来到我的世界!;)

一个简单的用例:

− DummyActivity 扩展 FragmentActivity / Log.d(Constants.LOGTAG, "DummyActivity.onCreate " + getSupportLoaderManager().toString());

− DataFragment 扩展 Fragment 实现 LoaderManager.LoaderCallbacks / Log.d(Constants.LOGTAG, "DataFragment.onCreate " + getLoaderManager().toString());

− ReportFragment 扩展 Fragment 实现 LoaderManager.LoaderCallbacks / Log.d(Constants.LOGTAG, "ReportFragment.onCreate " + getLoaderManager().toString());

DummyActivity 实例化 DataFragment,后者实例化 ReportFragment。logcat 输出显示每个 LoaderManager 的不同地址。作为第一个结论,每个 Fragment 似乎都有一个合适的 LoaderManager……</p>

如果我能回答你的(我们的;))问题,我会继续更新。如果您取得了任何进展,请分享您的宝贵知识。

更新:

我的假设是加载器 id 仅与特定片段的 LoaderManager 的本地范围相关联,以使多个本地加载器与片段相关联(因此您可以根据 id int arg 在 onCreateLoader 中返回不同的加载器和initLoader 调用)。

到目前为止,我设法“重用”了一个加载器(......或不):

− 首先,我getSupportLoaderManager().enableDebugLogging(true);在 DummyActivityonCreate方法中启用了 LoaderManager 调试。

− 然后我getActivity().getSupportLoaderManager().initLoader(78, null, this);onCreateDataFragment 和 ReportFragment 的方法中调用。

onCreateLoader− DataFragment通过 mCursorLoader 私有成员上的 setter公开该方法创建的 CursorLoader 。

− ReportFragmentonCreateLoader返回 DataFragment CursorLoader(使用 检索 Fragment 后findFragmentByTag)。

过滤(并且稍微混淆)的 logcat 输出:

      DummyApp  D  DummyActivity.onCreate
      DummyApp  D  DataFragment.newInstance
      DummyApp  D  ReportFragment.newInstance
      DummyApp  D  DataFragment.onCreate
 LoaderManager  V  initLoader in LoaderManager{405a19d0 in SpecificAction{4059ee98}}: args=null
      DummyApp  D  DataFragment.onCreateLoader
 LoaderManager  V    Created new loader LoaderInfo{405a2298 #78 : CursorLoader{405a22e0}}
      DummyApp  D  DataFragment.onCreate
      DummyApp  D  DataFragment.onActivityCreated
      DummyApp  D  ReportFragment.onCreate
 LoaderManager  V  initLoader in LoaderManager{405a19d0 in DummyActivity{4059ee98}}: args=null
 LoaderManager  V    Re-using existing loader LoaderInfo{405a2298 #78 : CursorLoader{405a22e0}}
      DummyApp  D  SpecificActionReportFragment.onCreate
      DummyApp  D  SpecificActionReportFragment.onActivityCreated
 LoaderManager  V  Starting in LoaderManager{405a19d0 in DummyActivity{4059ee98}}
 LoaderManager  V    Starting: LoaderInfo{405a2298 #78 : CursorLoader{405a22e0}}
 DummyProvider  D  query called
 DummyProvider  D  […]       
 DummyProvider  D  [end of query]
 LoaderManager  V  onLoadComplete: LoaderInfo{405a2298 #78 : CursorLoader{405a22e0}}
 LoaderManager  V    onLoadFinished in CursorLoader{405a22e0 id=78}: CursorWrapperInner{405afb20}
      DummyApp  D  ReportFragment.onLoadFinished
      DummyApp  D  ReportFragment.displayActionReport
      DummyApp  D  DummyActivity.setReportViewsVisibility
      DummyApp  D  ReportFragment.setSaveReportImageViewVisibility

这两个片段是从 DummyActivityonCreate方法添加的(与所描述的用例不同,但这对我们正在处理的问题没有任何改变)。不幸的是,加载器被重新分配给调用它的最新片段(此处为 ReportFragment)……并且永远不会调用 DataFragment.onLoadFinished。因此,ReportFragment 看起来不错,但 DataFragment 不是最新的,因为从onLoadFinished此类调用更新。

我假设有一个底层取消注册调用,然后是 CursorLoader 上的一个注册调用。

待续……</p>

于 2011-09-29T23:13:59.620 回答
0

是的。它对我有用。我在导航抽屉中有 3 个不同的片段,其中相同的数据填充在不同的 ListView 中。(所有片段都是相同活动的一部分)。

我的异步任务加载器:

public class MyTaskLoader extends AsyncTaskLoader<HashMap<String, Integer>> {

public MyTaskLoader(Context context) {
    super(context);
}

@Override
public HashMap<String, Integer> loadInBackground() {
...
return hashMap;
}

...
}

在所有片段中使用相同的加载程序 ID。

片段1:

public class Fragment1 extends BaseFragment implements LoaderManager.LoaderCallbacks<HashMap<String, Integer>> {
@Override
public void onCreate(Bundle savedInstanceState) {

//initialize adapter

getActivity().getSupportLoaderManager().initLoader(0, null, this);

}

@Override
public Loader<HashMap<String, Integer>> onCreateLoader(int arg0, Bundle arg1) {
    // TODO Auto-generated method stub

    return new MyTaskLoader(getActivity());
}

@Override
public void onLoadFinished(Loader<HashMap<String, Integer>> arg0,
        HashMap<String, Integer> data) {
    // TODO Auto-generated method stub

    listAdapter.setData(data.keySet());

}

@Override
public void onLoaderReset(Loader<HashMap<String, Integer>> arg0) {
    // TODO Auto-generated method stub

    listAdapter.setData(null);
}
}

对 Fragment2 使用相同的 ID:

public class Fragment2 extends BaseFragment implements LoaderManager.LoaderCallbacks<HashMap<String, Integer>> {
@Override
public void onCreate(Bundle savedInstanceState) {

//initialize adapter

getActivity().getSupportLoaderManager().initLoader(0, null, this);

}

@Override
public Loader<HashMap<String, Integer>> onCreateLoader(int arg0, Bundle arg1) {
    // TODO Auto-generated method stub

    return new MyTaskLoader(getActivity());
}

@Override
public void onLoadFinished(Loader<HashMap<String, Integer>> arg0,
        HashMap<String, Integer> data) {
    // TODO Auto-generated method stub

    listAdapter.setData(data.keySet());

}

@Override
public void onLoaderReset(Loader<HashMap<String, Integer>> arg0) {
    // TODO Auto-generated method stub

    listAdapter.setData(null);
}
}

应该在初始化加载器之前初始化适配器。工作至今。但是,这是正确的方法吗?有没有更好的方法来为多个片段使用通用加载器?

于 2015-01-06T05:47:56.807 回答