I\'ve converted my AsyncTask
to an AsyncTaskLoader
(mostly to deal with configuration changes). I have a TextView
I am using as a progres
The best method is to use LiveData, 100% Working
Step 1: Add lifecycle dependency or use androidx artifacts as yes during project creation
implementation "androidx.lifecycle:lifecycle-livedata:2.1.0"
Step 2: Create the loader class as follow, in loader create in public method to set the livedata that can be observed from activity or fragment. see the setLiveCount method in my loader class.
package com.androidcodeshop.asynctaskloaderdemo;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.MutableLiveData;
import androidx.loader.content.AsyncTaskLoader;
import java.util.ArrayList;
public class ContactLoader extends AsyncTaskLoader> {
private MutableLiveData countLive = new MutableLiveData<>();
synchronized public void setLiveCount(MutableLiveData observer) {
countLive = (observer);
}
public ContactLoader(@NonNull Context context) {
super(context);
}
@Nullable
@Override
public ArrayList loadInBackground() {
return loadNamesFromDB();
}
private ArrayList loadNamesFromDB() {
ArrayList names = new ArrayList<>();
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
names.add("Name" + i);
countLive.postValue(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return names;
}
@Override
protected void onStartLoading() {
super.onStartLoading();
forceLoad(); // forcing the loading operation everytime it starts loading
}
}
Step 3: Set the live data from activity and observe the change as follows
package com.androidcodeshop.asynctaskloaderdemo;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.MutableLiveData;
import androidx.loader.app.LoaderManager;
import androidx.loader.content.Loader;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity implements
LoaderManager.LoaderCallbacks {
private ContactAdapter mAdapter;
private ArrayList mNames;
private MutableLiveData countLiveData;
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mNames = new ArrayList<>();
mAdapter = new ContactAdapter(this, mNames);
RecyclerView mRecyclerView = findViewById(R.id.recycler_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mRecyclerView.setAdapter(mAdapter);
countLiveData = new MutableLiveData<>();
countLiveData.observe(this, new androidx.lifecycle.Observer() {
@Override
public void onChanged(Integer integer) {
Log.d(TAG, "onChanged: " + integer);
Toast.makeText(MainActivity.this, "" +
integer,Toast.LENGTH_SHORT).show();
}
});
// initialize the loader in onCreate of activity
getSupportLoaderManager().initLoader(0, null, this);
// it's deprecated the best way is to use viewmodel and livedata while loading data
}
@NonNull
@Override
public Loader onCreateLoader(int id, @Nullable Bundle args) {
ContactLoader loader = new ContactLoader(this);
loader.setLiveCount(countLiveData);
return loader;
}
@Override
public void onLoadFinished(@NonNull Loader load, ArrayList data) {
mNames.clear();
mNames.addAll(data);
mAdapter.notifyDataSetChanged();
}
@Override
public void onLoaderReset(@NonNull Loader loader) {
mNames.clear();
}
@Override
protected void onDestroy() {
super.onDestroy();
}
}
Hope this will help you :) happy coding