全局加载器(LoaderManager),用于在多个活动/片段中重用

时间:2012-04-06 15:23:51

标签: android android-fragments android-3.0-honeycomb android-loadermanager android-fragmentactivity

我想要实现的目标:

我有两个不同的片段。我希望他们两个以两种形式(在列表和地图上)显示相同的数据。我希望他们共享一个Loader(特别是AsyncTaskLoader)。一切正常,但装载机不会重复使用。创建另一个并且数据加载两次。

我做了什么:

Fragment我使用LoaderManager lm = getActivity().getSupportLoaderManager(); 在这两个中,我实现了LoaderCallbacks<ArrayList<Item>>和所需的方法。 我使用lm.initLoader(0, args, this);

但是当我输出lm.toString()时,看来这些是两个不同的装载机。数据下载两次。

如何从不同的活动/片段重新连接到同一个Loader?

这应该是可能的,因为无论如何,每个onCreate()上下文都附加到Loader,例如关于配置改变。

4 个答案:

答案 0 :(得分:5)

  

如何从与其启动的活动/片段不同的活动/片段重新连接到同一个Loader?

不应重复使用Loader个实例跨多个LoaderManagerActivity s管理的Fragment

LoaderManager会针对Loader / Activity生命周期启动/停止Fragment个,因此无法保证那些Loader Activity一旦你进入另一个Loader,它就会存在。

来自文档:

  

LoaderManager.LoaderCallbacks是一个让a的回调接口   客户端与LoaderManager交互。

     

加载器,特别是CursorLoader,应该保留它们的数据   被阻止后这允许应用程序保留其数据   跨越活动或片段的onStop()和onStart()方法,所以   当用户返回应用程序时,他们不必等待   要重新加载的数据。您使用LoaderManager.LoaderCallbacks方法   何时知道何时创建新的加载器,并告诉应用程序   什么时候停止使用加载器的数据。

换句话说,通常情况是您的Activity将特定于某些活动(或片段)。当您LoaderManager.LoaderCallbacks实施LoaderManager.LoaderCallbacks界面后,您的活动将获得initLoader(int ID, Bundle args, LoaderCallbacks<D> callback)类型。每次调用Loader时,LoaderManager都会创建或重用LoaderManager.LoaderCallbacks,该Activity特定于Fragment接口的某个实例(在本例中是您的Activity的实例)。这实质上是将Activity与一个Loader绑定在一起,并且当加载器状态发生变化时,将调用它的回调方法。

话虽如此,除非你能找到一种方法让你的两个独立的Activity共享相同的回调方法,我怀疑有一个干净的方法来做到这一点(即有一个Activity和一个Fragment共享相同的回调听起来像它即使不是不可能,也会很棘手)。我不会太担心它。在我见过的所有示例代码中,我从未见过两个Activity和/或Fragments共享相同的回调方法。此外,鉴于Loader和{{1}}都应该被设计为重用,以这种方式共享{{1}}似乎不会被鼓励。

答案 1 :(得分:1)

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

我的AsyncTaskLoader:

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

在初始化加载程序之前,应初始化适配器。 到目前为止工作。 但是,这是正确的方法吗?是否有更好的方法为多个碎片使用通用加载器?

答案 2 :(得分:0)

我不太确定在完成讨论后你想要达到的目标。但是有一个application.registerActivityLifecycleCallbacks()方法,它接受全局活动生命周期监听器(如onActivityCreated())。

答案 3 :(得分:0)

如果您在不同的片段和活动中使用相同的Loader ID,我认为您将拥有所需的行为。确保加载程序ID对要加载的数据是唯一的。例如,PhotosLoader和VideoLoader不应具有相同的ID。

相关问题