我怎样才能实现一个简单的AsyncTaskLoader?

在我最近的一个SO问题中,有人build议我使用Loader来解决问题。 所以在这里我想了解如何实现一个简单的AsyncTaskLoader

以下是我想到的:

 public class Scraper extends AsyncTaskLoader<List<Event>> { List<Event> lstEvents; public Scraper(Context context) { super(context); } public List<Event> loadInBackground() { //This is where I will do some work and return the data } } 

这就是我所想到的。 我阅读了AyncTaskLoader的文档,但是我从来没有遇到过如此神秘而杂乱的东西。 有一百万种方法,所有这些方法都是相互矛盾的,看着它们,不可能推断出它们被调用的顺序,甚至是否应该被重写和调用。 这个任务的生命周期是一个该死的噩梦。

我正在寻找的是只是刮一些数据,并返回它。 我也想将它存储在一个类variables中,以便下一次及时返回而不必再次擦除所有的数据。

我没有打开的游标,stream或类似的东西,只是一个简单的variables,称为lstEvents (可能很大)。 我不想泄漏内存和浪费资源,所以我会很高兴,如果有人能解释什么我需要closures/取消何时何地得到这个任务工作。

我应该在哪里存储数据到类variables? Shoudl我在我的loadInBackground方法结束时,或者我应该在deliverResult方法中做到这一点?

在这个简单的场景中,是否真的需要检查任务是否被取消或是否被重置,或者我应该不重写这些方法,并让AsyncTaskLoader处理它。

如果有人知道,一些脚手架代码将是有帮助的。 万分感谢。

Solutions Collecting From Web of "我怎样才能实现一个简单的AsyncTaskLoader?"

在我最近的一个SO问题中,有人build议我使用Loader来解决问题。

这可能不是一个好build议。

这个任务的生命周期是一个该死的噩梦。

更不用说, Loader合同build议您应该能够dynamic地检测数据中的变化,并自动将更新传递给使用Loader ,这对于ContentProvider来说很容易,对于其他设备上的商店来说是困难的,而不是尤其适用于像您这样的场景。

坦率地说,我只是使用一个AsyncTask并称它为好。

也就是说,你可以看看我为SQLite数据库( ContentProvider )和SharedPreferences 所做的Loader实现作为自定义加载器的例子。 你需要实现的唯一方法是loadInBackground()onStartLoading() 。 你可能需要deliverResult()如果内置的实现是不够的 – 在你的情况下,我怀疑内置的将会很好。 您可以添加其他一些方法,就像您在AbstractCursorLoader看到的一样,但是我再次怀疑您不需要它们。

是否有我真的需要检查任务是否被取消或是否被重置的地方,或者我应该不重写这些方法,并让AsyncTaskLoader处理它。

首先让AsyncTaskLoader处理它,并且只有在你确定需要它们时才担心它们。

除了来自CommonsWare的答案的所有好消息外,还有一件事要考虑。 在实现AsyncTaskLoader ,需要在Loader或AsyncTaskLoader的子类上调用forceLoad() 。 否则,你的loadInBackground()方法在我的经验中不会被调用。

从我对文档的理解,一个加载器可以挂在其成员variables的结果,就像你已经在你的问题中剔除。 然后,您可以重写onStartLoading()并检查caching的结果列表。 如果列表为null,则加载器可以在其自身上调用forceLoad()

另外请注意,如果最终实现caching结果,请注意在另一个线程上调用了loadInBackground()因此您可能想要同步对任何成员variables的访问。

这有点迟,但对于正在阅读这个问题的其他人来说可能是有用的。 这是AsyncTaskLoader的一个实现:

 public class EventListLoader extends AsyncTaskLoader<List<Event>> { private List<Event> events; public EventListLoader(Context context) { super(context); events = new ArrayList<Event>(); } @Override public List<Event> loadInBackground(){ //"Simply scrape some data and return it" as a list of events here. } @Override public void deliverResult(List<Event> data) { if (isReset()) { releaseResources(events); return; } List<Event> oldData = events; events = data; if (isStarted()) super.deliverResult(data); releaseResources(oldData); } @Override protected void onStartLoading() { if (events != null && !events.isEmpty()) deliverResult(events); if (takeContentChanged() || events == null || events.isEmpty()) forceLoad(); } @Override protected void onStopLoading() { super.onStopLoading(); cancelLoad(); } @Override public void onCanceled(List<Event> data) { super.onCanceled(data); releaseResources(events); } @Override protected void onReset() { super.onReset(); onStopLoading(); releaseResources(events); } private void releaseResources(List<Event> data) { if (data!= null && !data.isEmpty()) data.clear(); } } 

在ListFragment中使用它:

 public class EventsListFragment extends ListFragment implements LoaderManager.LoaderCallbacks<List<Event>> { private static final int LOADER_ID = 0; ... @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); ... setListAdapter(new EventListAdapter()); if (savedInstanceState == null) getLoaderManager().initLoader(LOADER_ID, null, this); else getLoaderManager().restartLoader(LOADER_ID, null, this); } @Override public Loader<List<Event>> onCreateLoader(int id, Bundle args) { return new EventLoader(getActivity()); } @Override public void onLoadFinished(Loader<List<Event>> loader, List<Event> data) { ((EventListAdapter) getListAdapter()).setData(data); invalidateActionMode(); //Only if Contextual Action Bar (CAB) is used. } @Override public void onLoaderReset(Loader<List<Event>> loader) { ((EventListAdapter) getListAdapter()).clearData(); } 

如果我们将EventListAdapter定义为:我们可以加载并显示一个事件列表(从本地数据库或Internet)作为ListFragment(例如):

 public class EventListAdapter extends BaseAdapter { protected List<Event> mItems = new ArrayList<>(); @Override public boolean isEnabled(int position) { return true; } @Override public boolean hasStableIds() { return true; } @Override public int getCount() { return mItems.size(); } @Override public Object getItem(int position) { return mItems.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ... } public void setData(List<Event> items){ mItems.clear(); mItems.addAll(items); notifyDataSetChanged(); } public void clearData(){ mItems.clear(); notifyDataSetChanged(); } }