What does AsyncTaskLoader.deliverResult() actually do?

旧时模样 提交于 2019-12-18 11:34:07

问题


I am trying to understand some finer points of AsyncTaskLoaders. This may be obvious, to others but I can't find an unambiguous example or definition that demonstrates and exmplains what happens when you override the deliverResult() method. What actually gets delivered ? How does this interact with the calling object ? I can see use of super.deliverResult, which passes a private object from the class. So, does the loader automatically know what to associate with the "delivered result". I am totally confused.


回答1:


Seems I'm a bit late to the party, but anyway...

One of the main advantages of this intermediary step between the background loading and the UI thread's callback onLoadFinished() getting called

  1. loadInBackground()
  2. deliverResult() and
  3. the callback onLoadFinished()

is that it gives us a means of shortcutting the whole loading process from within the AsyncTaskLoader class. And this can be put to good use for caching the loading result within your AsyncTaskLoader and preventing the background loading from happening if there is cached data.

And why would we want to do this? Isn't the whole point of loaders dealing with those dreaded activity lifecycle issues (e.g. rotating the device), maintaining state (like, caching data) and having a means to get updated when underlying data changes (CursorLoader)?
Well, yes, but this isn't the whole story.

Consider this use case:
You've got your app (the one with the AsynTaskLoader) up-and-running and it already has loaded data into your UI. Then, you switch over to your Twitter app to check on some news and return to you app. Without caching, upon returning to your app, the loader would do its reloading. This behavior is different from the one after configuration changes, e.g. rotating your device, in which case no reloading would take place.

So, how would we then prevent the loader from re-fetching data in case we're just sending our app to the background and, later, return to it again?

Solution

  1. Create a cache member variable in your AsyncTaskLoader implementation.
  2. Override deliverResult() so that you save your fetched data in your cache first, before you call the superclass's implementation of deliverResult().
  3. In onStartLoading() check if there's cached data, and if so, let your AsyncTaskLoader just deliver that. Otherwise, start loading.

Here's a link to a sample app which implements this behaviour. It's just a "Toy app" and as such part of Udacity's current version of the "Developing Android Apps" fundamentals course. And here is the link to the respective video within that course that deals with this issue. (The course is free, but you'll still have to sign-up w/ Udacity).

In short, what this app demonstrates, is a UI in which the user can input a search query for searching GitHub's repos (via the GitHub API), showing the resulting search URL in a TextView and also the raw JSON fetched from GitHub in another TextView.
The whole action happens in just MainActivity.java and the relevant part here is within the AsyncTaskLoader that's implemented as an anonymous inner class:

  • For step 1, just introduce a member variable in your AsyncTaskLoader implementation that's meant to serve as your data cache.

    /* This String will contain the raw JSON
       from the results of our Github search */
    String mGithubJson;
    
  • For step 2, override deliverResult() as to cache the loading result.
    When loadInBackground() has finished, it passes its return value to deliverResult(). It does so anyway, but now that we've overridden deliverResult() we can step right in and store our fetched data into the cache member variable which we've created with just so good foresight. And finally, we chain up to the super class implementation of deliverResult() with super.deliverResult() which will pass-on the result to the callback method onLoadFinished(), running on the UI thread.

    @Override
    public void deliverResult(String githubJson) {
        mGithubJson = githubJson;
        super.deliverResult(githubJson);
    }
    
  • For step 3, check in onStartLoading() whether or not we've got cached data.
    If we don't have cached data (yet), just force the loading to begin with a call to forceLoad(). But if we do have cached data, just call deliverResult(yourCachedDataGoesHere) and pass-in the cached data as argument.

    if (mGithubJson != null) {
        deliverResult(mGithubJson);
    } else {
        forceLoad();
    }
    

    So, if you now switch back and forth between your app and some other app(s), you'll notice that no reloading takes place, as the loader will just use your cached data.




回答2:


suppose when data are loading in the background, at this time, user press HOME button and exist the app, when user comes back to the app, loading has been finished. So we have already have the data, then AsyncTaskLoader will call the deliverResult() method, deliver the data to the onLoadFinished() method for displaying.

When the user come back to app, onStartLoading() is being called before loadInBackground(). In this method, we could check if our data if empty or not, if not empty, we call deliverResult() and send the result to onLoaderFinished(), so it could prevent to reload data.

When we press HOME exist the app and then come back, it will not create a new Loader, instead the old loader will try to load data.




回答3:


The only answer I can find that makes any sense is based on a decription in this link.

"A registered listener to receive the Loader's results when it completes a load. For each of its Loaders, the LoaderManager registers an OnLoadCompleteListener which will forward the Loader’s delivered results to the client with a call to onLoadFinished(Loader loader, D result). Loaders should deliver results to these registered listeners with a call to Loader#deliverResult(D result)."

deliverResult appears to be used when you have listeners to the AsyncTask and want to send the results back to them. I would say it's uncommon. The Android documentation is even less descriptive:

"Sends the result of the load to the registered listener. Should only be called by subclasses. Must be called from the process's main thread.

Parameters

data : the result of the load"




回答4:


deliverResult works after doInbackground completes. It sends the result D (returned by doInBackground) to the calling thread. You may wish to override it for cleaning data, but you can do clean-up in doInBackground instead without overriding deliverResult.



来源:https://stackoverflow.com/questions/25234581/what-does-asynctaskloader-deliverresult-actually-do

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!