我想为我的自定义数据源实现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();
}
});
}
}
答案 0 :(得分:5)
在与你的非常相似的情况下,我使用本地广播取得了很大的成功。该方法涉及AsyncTaskLoader
实现,该实现将注册BroadcastReceiver
侦听描述更改内容的特定字符串。此BroadcastReceiver
会保留对Loader
的引用并调用onContentChanged
。当数据需要刷新时,使用前面提到的字符串进行本地广播,BroadcastReceiver
将听到它并触发加载。这是一些示例代码,如果你放入它可能不会完美,我已经推广了一些类名,但希望你能得到这个想法:
广播接收器:
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()
处取消注册接收器。如果在评论中有任何不清楚的地方,请告诉我,我会尽力澄清。