是否总是有必要从Fragment中的onCreate初始化initLoader?如果加载程序的关键参数取决于另一个加载程序的结果怎么办?

即您有2个加载程序:LoaderA和LoaderB。 LoaderB需要LoaderA的结果才能运行。 LoaderA和LoaderB都在片段的onCreate中初始化,但是没有给LoaderB提供参数,因此有意失败。
一旦LoaderA完成,LoaderB将使用新的参数重新启动,以便它可以执行所需的请求。

加载程序初始化片段:

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    getLoaderManager().initLoader(LOADER_A, new Bundle(), this);
    getLoaderManager().initLoader(LOADER_B, null, mLoaderBCallback);
}


片段中LOADER_A的回调:

@Override
public Loader<MyResultObject> onCreateLoader(int id, Bundle args) {
    return new LoaderA(getActivity(), args);
}

@Override
public void onLoadFinished(Loader<MyResultObject> loader, final MyResultObject result) {
    if (result != null) {
        Bundle args = new Bundle();
        args.putInt("id", result.getId());

        getLoaderManager().restartLoader(LOADER_B, args, mLoaderBCallback);
    }
}


片段中mLoaderBCallback的定义:

private LoaderBCallback mLoaderBCallback = new LoaderBCallback();


(LoaderBCallback的实现并不重要,它只是标准的LoaderCallbacks接口,该接口创建LoaderB的实例并在加载程序完成时进行处理。)

LoaderB类(请为此类定义定义任何潜在的编译器错误,这只是一个示例):

public class LoaderB<List<AnotherResultObject>> extends AsyncTaskLoader<List<AnotherResultObject>> {
    private Bundle mArgs;

    public LoaderB(Context context, Bundle args) {
        super(context);
        mArgs = args;
    }

    @Override
    public List<AnotherResultObject> loadInBackground() {
        if (mArgs == null) {
            // bail out, no arguments.
            return null;
        }


        // do network request with mArgs here
        return MyStaticClass.performAwesomeNetworkRequest(mArgs);
    }

    // boiler plate AsyncTaskLoader stuff here
    ......

}


有没有更好的办法?没有LoaderB的initLoader可以做吗?

编辑:我的印象是加载程序总是必须在onCreate中初始化,以便它们可以处理配置更改。这可能仅适用于Activity中的装载程序。在Fragments中创建的加载程序是否无论在哪里初始化都得到管理?

最佳答案

您可以在代码中的任何位置初始化加载程序。

在您的情况下,应将oncc中的restartLoader替换为initLoader。只需从onActivityCreated中为LOADER_B删除initLoader

另外,您应该在onLoadFinished中检查加载程序的ID,以便知道哪个加载程序完成了。

编辑:您正在为LOADER_B回调使用单独的侦听器,因此我的ID检查点在那儿被击败了..但无论如何..如果您愿意,可以将它们组合为一个

@Override
public void onLoadFinished(Loader<MyResultObject> loader, final MyResultObject result) {
    switch (loader.getId())
    {
      case LOADER_A:
         if (result != null) {
             Bundle args = new Bundle();
             args.putInt("id", result.getId());
             // i put "this" as the callback listener. you can use your custom one here if you want
             getLoaderManager().initLoader(LOADER_B, args, this);
         }
         break;
      case LOADER_B:
         //do whatever
         break;
}

10-08 03:16