How to turn this code of AsyncTask to AsyncTaskLoader since movieListFetcher.listType is an enum?
class LoadMovieList extends AsyncTask<movieListFetcher.listType, Void, Void> {
@Override
protected Void doInBackground(movieListFetcher.listType... params) {
movies = null;
switch (params[0]) {
case TOP_RATED:
movies = new movieListFetcher().getTopRatedList();
break;
case MOST_POPULAR:
movies = new movieListFetcher().getMostPopularList();
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
if (movies != null) {
adapter.notifyDataSetChanged();
recyclerView.setAdapter(adapter);
}
}
}
General Steps for Using AsyncTaskLoader:
o Step 1: Create a custom Loader class which extends AsyncTaskLoader<D>
;
D: is the list of objects that are returned back from the background task which is implemented using loadInBackground()
method; and then override below methods:
loadInBackground()
>> runs in background to load the heavy work .. similar to doInBackground()
of AsyncTask
onStartLoading()
>> runs once the loader is created and just before loadInBackground()
; can be used to return previous loaded results using deliverResult()
or to load new results by running the background task again using forceLoad()
o Step 2: Implement LoaderCallbacks<D>
in your Activity that requires the background process. This requires to implement 3 methods:
onCreateLoader()
>> runs in main thread to create a loader instanceonLoadFinished()
>> runs in main thread to submit background results & update UI .. similar to onPostExecute()
of AsyncTask
onLoaderReset()
>> reset loader data
o Step 3: use the LoaderManager to start your loader whenever you need that in your activity:
To apply this in your example:
Step 1:
public class MovieLoader extends AsyncTaskLoader<List<Movie>> { // STEP 1
private List<Movie> movies;
private int mMovieType;
MovieLoader(@NonNull Context context, Integer movieType) {
super(context);
mMovieType = movieType;
}
@Override
public List<Movie> loadInBackground() {
switch (mMovieType) {
case TOP_RATED:
movies = new movieListFetcher().getTopRatedList();
break;
case MOST_POPULAR:
movies = new movieListFetcher().getMostPopularList();
}
return movies;
}
@Override
protected void onStartLoading() {
super.onStartLoading();
if (movies != null) {
// To skip loadInBackground() call
deliverResult(movies);
} else {
// to run loadInBackground()
forceLoad();
}
}
}
Step 2 & 3:
public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<List<Movie>> { // STEP 2
final int LOADER_ID = 1;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// initialize RecyclerView Adapter
// Set RecyclerView mAdapter
mAdapter = new CustomAdapter(...);
RecyclerView recyclerView = findViewById(...);
recyclerView.setAdapter(mAdapter);
// Loading data in background by instantiating a new loader
getSupportLoaderManager().initLoader(LOADER_ID, null, this); // STEP 3
}
@NonNull
@Override
public Loader<List<Movie>> onCreateLoader(int id, Bundle args) {
return new MovieLoader(MainActivity.this, TOP_RATED);
}
@Override
public void onLoadFinished(@NonNull Loader<List<Movie>> loader, List<Movie> movies) {
// Update UI
if (movies != null) {
mAdapter.notifyDataSetChanged();
}
}
@Override
public void onLoaderReset(@NonNull Loader<List<Movie>> loader) {
mAdapter.setMovies(new ArrayList<Movie>()); // create this custom method in your recyclerView adapter
}
}
Please note that Loaders are now deprecated and replaced by LiveData & ViewModels
Hope this satisfies your need, and you can check this tutorial for more info