Implementing Loaders in Android
Connecting to the internet is an important feature in an android application. It boosts user experience especially when done efficiently and reliably.
Network querying in android is a heavy task and is capable of blocking the android main thread, therefore it should always be done in background threads. One method of doing this is by using the Java Asynctask class, a brief explanation of the Asynctask class can be found in a previous tutorial i did on inner classes here. A better and more efficient method of network querying is using Asynctask Loaders and this is what this tutorial is about.
What Will I Learn?
- How the Loader Class operates
- How to perform network querying in the background with Asynctask Loaders
Requirements
- Android Studio 2.3 and above
- Basic Knowledge of native Android development using Java
Difficulty
- Intermediate
Tutorial Contents
The Loader class is a java class in android that helps in querying the network (Asynctask Loader) or loading data from a content provider(Cursor Loader) in a background thread to avoid blocking the main android UI thread. The Asynctask can also be used to perform background network querying but it is very inefficient and quite tasking to manage as the developer has to manage both the UI thread and the background thread using various lifecycle methods.
Also, a new Asynctask is constantly executed each time the host activity is recreated and this poses a problem when for example the device screen is constantly rotated to change orientation. The loader however eliminates all these inefficiencies by
- Providing a callback interface for managing both UI and background threads
- Having just a single instance across configuration changes
To use the Asynctask loader for network querying, a class is created that extends AsynctaskLoader. This class being a generic class can have object type parameters passed into it for use when performing the operation. See code below,
public class MyFirstLoader extends AsynctaskLoader<Object>{
public MyFirstLoader(Context context){
}
@Override
public Object doInBackground(){
//perform network querying
}
@Override
public void deliverResult(Object o){
//
}
}
The asynctask loader class has an implemented method called doInBackground() in which all the heavy operations are done. This method runs in a background thread and performs the load, then returns the result to the UI thread for processing. The result can also be processed by a call to the deliverResult() method which has the result of the load as a parameter.
A constructor is also added to the class that is used for instantiating the class and passing in the context from which the class was instantiated such as an activity or fragment.
For best practices, a progress indicator to indicate loading may be added to the loader so as to make the user aware of an ongoing background task, the code below shows how this is done,
public class MyFirstLoader extends AsynctaskLoader<Object>{
private ProgressDialog progressDialog;
private Context context;
public MyFirstLoader(Context context){
this.context = context;
}
@Override
protected void onStartLoading() {
super.onStartLoading();
dialog = new ProgressDialog(context);
dialog.setMessage("Please wait");
dialog.setTitle("Loading");
dialog.setIndeterminate(true);
dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
dialog.show();
}
@Override
protected void onStopLoading() {
super.onStopLoading();
dialog.dismiss();
}
}
The progress dialog is created in the onStartLoading() method to indicate the commencement of the network query. It is then dismissed in the onStopLoading() method which is called when the loading is complete. It can also be dismissed in the deliverResult() method.
To start the loader it has to be initialized in the activity or fragment from which it is called. The LoaderManager callbacks have to be used and three methods are implemented when this callback is used in the calling context, see code below,
public class MyActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Object>{
@Override
public MyFirstLoader onCreateLoader(int id, Bundle args) {
return new MyFirstLoader(MyActivity .this);
}
@Override
public void onLoadFinished(Loader loader, Object object) {
//code to process delivered result
}
@Override
public void onLoaderReset(Loader loader) {
loader.reset();
}
}
The code shows the three methods to be implemented for the loader callback. The onCreateLoader() method is used to create the loader and returns an instance of the loader class to the activity.
The onLoadFinished() method receives the results from the loading for processing or UI updating by the activity. Finally the onLoaderReset() method is called when a previously created loader is being reset leading to absence of its data.
To initialize the loader, a unique integer loader id is needed and a loader manager instance is called in the onCreate() or onResume() methods depending on the developer preference for initialization, the code below shows this,
@Override
protected void onCreate(Bundle savedInstanceState) {
getLoaderManager().initLoader(0, null, this).startLoading();
}
The LoaderManager instance calls the initLoader() method passing in a loader ID of 0 (can be any number as long as it is unique to that loader), an optional argument which is null in this code snippet and the context from which the loader is initialized. The initialized loader then calls the startLoading() method and then loading begins.
Depending on how fast the developer wants loading to begin, an alternative method called forceLoad() can be used, this ensures the loading starts almost instantaneously,
getLoaderManager().initLoader(0, null, this).forceLoad();
CONCLUSION
In conclusion, the loader class gives the android developer an efficient way of loading data from a source. It is worthy to note that another type of loader called the CursorLoader can be used to load huge amount of data from a content provider ensuring better user experience.
Thanks for reading, i hope you learned something.
Posted on Utopian.io - Rewarding Open Source Contributors
Thank you for the contribution. It has been approved.
You can contact us on Discord.
[utopian-moderator]
Hey @cha0s0000, I just gave you a tip for your hard work on moderation. Upvote this comment to support the utopian moderators and increase your future rewards!
Hey @davidemi I am @utopian-io. I have just upvoted you!
Achievements
Community-Driven Witness!
I am the first and only Steem Community-Driven Witness. Participate on Discord. Lets GROW TOGETHER!
Up-vote this comment to grow my power and help Open Source contributions like this one. Want to chat? Join me on Discord https://discord.gg/Pc8HG9x