【问题标题】:Multiple loaders in same activity同一活动中的多个加载程序
【发布时间】:2013-03-26 17:42:57
【问题描述】:

我有两个从AsyncTaskLoader 继承的自定义构建加载器,我想在我的活动中使用它们。它们中的每一个都返回不同类型的结果。 要将我的活动用于回调,我必须实现两个接口:

implements LoaderCallbacks<GetSyncListDataResult>, LoaderCallbacks<ErrorResult>

但是,尝试在同一个类中实现所需的方法,我最终得到 重复方法错误和擦除(???)错误:

// Methods for the first loader
public Loader<GetSyncListDataResult> onCreateLoader(int ID, Bundle bundle) ...
public void onLoaderReset(Loader<GetSyncListDataResult> loader) ...
public void onLoadFinished(Loader<GetSyncListDataResult> loader, GetSyncListDataResult result) ...

// Methods for the second loader
public Loader<ErrorResult> onCreateLoader(int ID, Bundle bundle) ...
public void onLoaderReset(Loader<ErrorResult> loader) ...
public void onLoadFinished(Loader<ErrorResult> loader, ErrorResult result) ...

显然,这些方法相互冲突,我需要一种简单的方法来解决这个问题。 解决这个问题的正确方法是什么?

【问题讨论】:

  • 不要实现加载器。你只能实现一个加载器。相反,您应该将 LoaderCallbacks 声明为变量。例如。 LoaderCallbacks syncListCallbacks = new LoaderCallbacks() { ...方法在这里 };
  • 好的,所以最好在变量中有一个内部匿名类实例?
  • 是的。然后启动你的加载器 getLoaderManager().initLoader(loaderId, bundle, syncListCallbacks);
  • 好的,如果你愿意,你可以写这个作为答案,我会接受的。

标签: java android


【解决方案1】:

正确答案是根据@dymmeh 的评论,即不是让Activity 实现两个LoaderCallbacks 接口,而是让活动包含两个LoaderCallbacks 实现。例如:在您的活动中初始化您的LoaderCallbacks 字段...

private LoaderCallbacks<GetSyncListDataResult> dataResultLoaderListener
  = new LoaderCallbacks<GetSyncListDataResult>() { ...methods here... };

private LoaderCallbacks<ErrorResult> errorResultLoaderListener
  = new LoaderCallbacks<ErrorResult>() { ...methods here... };

...并声明您的加载程序ID...

private static final int DATA_RESULT_LOADER_ID = 1;
private static final int ERROR_RESULT_LOADER_ID = 2;

...然后初始化您的加载器...

getLoaderManager().initLoader(DATA_RESULT_LOADER_ID, dataResultBundle, dataResultLoaderListener);
getLoaderManager().initLoader(ERROR_RESULT_LOADER_ID, errorResultBundle, errorResultLoaderListener);

...完成!

【讨论】:

  • 我有一个问题。 Activity 实现LoaderCallbacks 并传递this 代替dataResultLoaderListener 的目的是确保LoaderManager 充当ActivityLoader 通过LoaderCallbacks 之间的通信通道。 Activity 没有实现 LoaderCallbacks 而是创建匿名内部类,是如何在这里创建的通信通道?
  • @AnV LoaderCallbacks 本身就是activity和loader之间的通信通道。所以匿名内部类很好。
【解决方案2】:
class YourActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks {
// you still implements LoaderManager.LoaderCallbacks but without add <returnType> 
//and you have to cast the data into your needed data type in onLoadFinished()

    Private int loader1 = 1;
    private int loader2 =2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_detail);

    getSupportLoaderManager().initLoader(REVIEW_LOADER, null, this);
    getSupportLoaderManager().initLoader(REVIEW_LOADER, null, this);
}
    @Override
    public Loader onCreateLoader(int id, Bundle args) {
        if (id == loader1 ) {

            //YourLoaderClass1 is you loaderClass where you implement onStartLoading and loadingInBackground() 
            return new YourLoaderClass1();  
        } else if (id == loader2 ) {

            return new YourLoaderClass2();
        }
        return null;
    }

    @Override
    public void onLoadFinished(Loader loader, Object data) {
        int id = loader.getId();// find which loader you called
        if (id == loader1 ) {

            yourMethod1((List< >) data); // eg. cast data to List<String>
        } else if (id == loader2 ) {
            yourMethod1((String) data); // eg. cast data to String
        }
    }

    @Override
    public void onLoaderReset(Loader loader) {
        int id = loader.getId();
        if (id == loader1 ) {

        } else if (id == loader2 ) {

        }
    }
}

我的Github example

【讨论】:

  • 您的答案能否提供更多解释?对于遇到这种情况的人来说,仅代码很少像代码 + 解释那样有用。
  • 感谢您的建议,我只是添加了一些解释,希望对您有所帮助
  • 这两个任务是串行执行还是并行执行?
【解决方案3】:

实际上,如果您在 Activity 类上实现 LoaderManager.LoaderCallbacks&lt;T&gt; 并使用特定的加载器 id,使用结果进行操作,会更简单。 这样,您的代码更具可读性和功能性(因为内部加载器回调的接口实现不再重复)。

例如:

    public class JobListActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<NetworkResult> {

        public static final  int    SUBMIT_RISK_ASSESSMENT_LOADER = 546;
        public static final  int    LOAD_RISK_ASSESSMENT_LOADER   = 1546;

        public Loader<NetworkResult> onCreateLoader(int id, @Nullable Bundle args) {
            if (id == SUBMIT_RISK_ASSESSMENT_LOADER) {
                return new NetworkLoader( this, args.getString( NetworkLoader.URL_EXTRA ), NetworkLoader.POST, args.getString( BODY ), false ));
            } else if (id == LOAD_RISK_ASSESSMENT_LOADER) {
                return new NetworkLoader( this, args.getString( NetworkLoader.URL_EXTRA ), NetworkLoader.GET, null, false ) );
            }

            return null;
        }

        @Override
        public void onLoadFinished(@NonNull Loader<NetworkResult> loader, NetworkResult data) {
            if (data == null) {
                return;
            }

            Crashlytics.log( Log.INFO, TAG, "onLoadFinished with data [" + data + "]" );

            if (loader.getId() == SUBMIT_RISK_ASSESSMENT_LOADER) {
                    doSemethingElse(data);
            } else if (loader.getId() == LOAD_RISK_ASSESSMENT_LOADER) {
                    doSemethingElse(data);
            }
            LoaderManager.getInstance( this ).destroyLoader( loader.getId() );
    }

【讨论】:

    【解决方案4】:

    这不是必需的。实现 LoaderManager.LoaderCallbacks。然后,每次初始化加载程序时,给它一个唯一的 ID。在回调中,您可以检测导致回调的加载程序的 ID 并采取相应的操作。

    那是

    class MyLoader extends Activity implements LoaderManager.LoaderCallbacks<GetSyncDataResult> {
    ...
    private static final int LOADER1 = 1;
    private static final int LOADER2 = 2;
    ...
    getLoaderManager().initLoader(LOADER1, null, this);
    ...
    getLoaderManager().initLoader(LOADER2, null, this);
    ...
    
    public Loader<GetSyncDataResult> onCreateLoader(int loaderId, Bundle args) {
    
        switch (loaderId) {
    
        case LOADER1: ...
        case LOADER2: ...
    }
    ...
    

    等等。

    【讨论】:

    • 这个答案不正确,因为两个加载器的返回类型(如问题中所指定)不同。
    • @AdilHussain 如果两个加载器是自定义加载器怎么办??
    • 道歉艾米,但我不明白你的问题,也看不出它与这个线程中的原始问题有什么关系。这个线程是关于LoaderManager.LoaderCallbacks 接口以及如何设置一个活动来监听 2+ 个具有不同返回类型的加载器。
    猜你喜欢
    • 2011-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-15
    • 1970-01-01
    相关资源
    最近更新 更多