正确通知AsyncTaskLoader关于来自后台线程的数据更改

时间:2013-09-24 14:55:58

标签: android android-loader

我想为我的自定义数据源实现AsyncTaskLoader

public class DataSource {
    public interface DataSourceObserver {
        void onDataChanged();
    }
    ...
}

DataSource将保留已注册观察员的名单,并将通知他们有关更改的信息。 CustomLoader将实施DataSourceObserver。问题是如何正确通知CustomLoader,因为必须从UI线程调用Loader.onContentChanged(),但在我的情况下DataSource操作(以及对DataSourceObserver.onDataChanged()的调用)将从后台线程完成

更新了Selvin提示的提示

public class CustomLoader extends AsyncTaskLoader<...> implements DataSource.DataSourceObserver {
    private final Handler observerHandler;

    public CustomLoader(Context context) {
        super(context);
        observerHandler = new Handler()
    }

    @Override
    public void onDataChanged() {
        observerHandler.post(new Runnable() {
            @Override
            public void run() {
                onContentChanged();
            }
        });
    }
}

1 个答案:

答案 0 :(得分:5)

在与你的非常相似的情况下,我使用本地广播取得了很大的成功。该方法涉及AsyncTaskLoader实现,该实现将注册BroadcastReceiver侦听描述更改内容的特定字符串。此BroadcastReceiver会保留对Loader的引用并调用onContentChanged。当数据需要刷新时,使用前面提到的字符串进行本地广播,BroadcastReceiver将听到它并触发加载。这是一些示例代码,如果你放入它可能不会完美,我已经推广了一些类名,但希望你能得到这个想法:

在您的Loader Implmentation中使用

广播接收器

public class LoaderBroadcastReceiver extends BroadcastReceiver
{
    private Loader loader;

    public LoaderBroadcastReceiver(Loader loader)
    {
        this.loader = loader;
    }

    @Override
    public void onReceive(Context context, Intent intent)
    {
        loader.onContentChanged();
    } 
}

加载程序实施onStartLoading()

中注册接收方
private LoaderBroadcastReceiver loaderBroadcastReceiver = null;

@Override
protected void onStartLoading()
{
     //... some code here

    if(loaderBroadcastReceiver == null)
    {
        loaderBroadcastReceiver = new LoaderBroadcastReceiver(this);
        LocalBroadcastManager.getInstance(getContext()).registerReceiver(loaderBroadcastReceiver, new IntentFilter("NEWDATASTRING"));
    }

    //... some more code here
}

最后,这里是 onDataChanged in DataSource 将如何进行广播。它需要一个Context来帮助发送广播。由于可以从任意线程调用,因此我将使用您的ApplicationContext,因为如果Activity被销毁,来自Activity的Context可能会导致问题。

public class DataSource 
{
    public interface DataSourceObserver 
    {
        void onDataChanged(Context applicationContext)
        {
            LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("NEWDATASTRING"));
        }
    }
    ...
}

你可能想稍微玩一下,看看它对你有用。您可以使用不同的字符串来区分需要加载的不同数据。您还需要在onReset()处取消注册接收器。如果在评论中有任何不清楚的地方,请告诉我,我会尽力澄清。