Search code examples
androidasynctaskloader

Asynctaskloader restart loading when the activity restart


Hi I'm implementing a custom asynctaskloader to load data in the background. The problem is when the user goes back to the activity after he minimizes the app(or pick photo from gallary), all the asynctaskloaders associated with the activity and asynctaskloaders associated with the fragments in the activity start all over again.

How can I prevent the loader to restart the loading process when the activity restarts?

My baseAsynctaskLoader class:

import android.content.Context;

import android.support.v4.content.AsyncTaskLoader; import android.util.Log;

public abstract class BaseAsyncTaskLoader extends AsyncTaskLoader{

private static final String TAG = "BaseAsyncTaskLoader";

protected Context context;
protected Object mData;

public BaseAsyncTaskLoader( Context context ) {
    super(context);
    Log.d(TAG, "BaseLoader");
    this.context = context.getApplicationContext();
}

@Override
public abstract Object loadInBackground();

@Override
public void deliverResult(Object data){
    Log.d( TAG, "deliverResult" );
    if (isReset()) {
        return;
    }
    mData = data;

    if (isStarted()) {
        super.deliverResult(data);
    }

}

@Override
protected void onStartLoading(){
    Log.d( TAG, "onStartLoading" );

    if (mData != null) {
        deliverResult(mData);
    }

    if (takeContentChanged() || mData == null) {
        forceLoad();
    }
}

@Override
protected void onStopLoading(){
    Log.d( TAG, "onStopLoading" );
    cancelLoad();
}

@Override
protected void onReset(){
    Log.d( TAG, "onReset" );
    super.onReset();
    onStopLoading();
    if(mData !=null){
        mData=null;
    }
}

@Override
public void onCanceled(Object data){
    Log.d( TAG, "onCanceled" );
    super.onCanceled(data);
}

}

Loader class sample:

public class AddDetailService extends BaseAsyncTaskLoader{

Activity activity;
Bundle bundle;

String outputstringrespone="";

public AddCarService(Activity activity, Bundle bundle){
    super(activity);
    this.activity = activity;
    this.bundle = bundle;
}
@Override
public Object loadInBackground(){
    try{

        int userId = bundle.getInt(USER_ID);
        int modelId = bundle.getInt(MODEL_ID);
        outputstringrespone = addDetails(userId, modelId);

    }catch(Exception e){
        Log.d(TAG, e.toString());
    }
    return null;
}

@Override
public void deliverResult(Object data){
    super.deliverResult(data);
    Log.d(TAG,"output--"+outputstringrespone);
    if(outputstringrespone.equalsIgnoreCase("Success")){
        Toast.makeText(activity, "Details Added Successfully", Toast.LENGTH_SHORT).show();

    }else {
        Toast.makeText(activity, "Details not added",Toast.LENGTH_SHORT).show();
    }

}

}

LoaderCallback in activity:

getLoaderManager().initLoader(LoaderId.ADD_DETAIL, bundle, addDetailsCallbacks);

LoaderManager.LoaderCallbacks addDetailsCallbacks = new LoaderManager.LoaderCallbacks(){
    @Override
    public Loader onCreateLoader(int id, Bundle args){
        return new AddDetailService(getActivity(), args);
    }

    @Override
    public void onLoadFinished(Loader loader, Object data){
        getLoaderManager().destroyLoader(LoaderId.ADD_DETAIL);
    }

    @Override
    public void onLoaderReset(Loader loader){

    }
};

Solution

  • This is the desired behavior of LoaderManager framework - it takes care of reloading the data with the initiated Loaders in case the enclosing Activity or Fragment get re-created.

    In fact, some implementations of Loaders do not reload the data, but simply provide access to the latest data that has been cached internally.

    Bottom line: you observe correct behavior of LoaderManager framework.

    It is not clear what it is you're trying to accomplish with your Loader, but it looks like you chose an incorrect tool. If your goal is to perform the action just once, then you should use AsyncTask instead of Loaders.