Best practice to implement Retrofit callback to recreated activity? Best practice to implement Retrofit callback to recreated activity? android android

Best practice to implement Retrofit callback to recreated activity?


For potential long running server calls i use an AsyncTaskLoader. For me, the main advantage of Loaders are the activity-lifecycle handling. onLoadFinished is only called if your activity is visible to the user. Loaders are also shared between activity/fragment and orientation changes.

So i created an ApiLoader which uses retrofits synchronous calls in loadInBackground.

abstract public class ApiLoader<Type> extends AsyncTaskLoader<ApiResponse<Type>> {    protected ApiService service;    protected ApiResponse<Type> response;    public ApiLoader(Context context) {        super(context);        Vibes app = (Vibes) context.getApplicationContext();        service = app.getApiService();    }    @Override    public ApiResponse<Type> loadInBackground() {        ApiResponse<Type> localResponse = new ApiResponse<Type>();        try {            localResponse.setResult(callServerInBackground(service));        } catch(Exception e) {            localResponse.setError(e);        }        response = localResponse;        return response;    }    @Override    protected void onStartLoading() {        super.onStartLoading();        if(response != null) {            deliverResult(response);        }        if(takeContentChanged() || response == null) {            forceLoad();        }    }    @Override    protected void onReset() {        super.onReset();        response = null;    }    abstract protected Type callServerInBackground(SecondLevelApiService api) throws Exception;}

In your activity you init this loader like this:

getSupportLoaderManager().initLoader(1, null, new LoaderManager.LoaderCallbacks<ApiResponse<DAO>>() {        @Override        public Loader<ApiResponse<DAO>> onCreateLoader(int id, Bundle args) {            spbProgress.setVisibility(View.VISIBLE);            return new ApiLoader<DAO>(getApplicationContext()) {                @Override                protected DAO callServerInBackground(ApiService api) throws Exception {                    return api.requestDAO();                }            };        }        @Override        public void onLoadFinished(Loader<ApiResponse<DAO>> loader, ApiResponse<DAO> data) {            if (!data.hasError()) {                DAO dao = data.getResult();                //handle data            } else {                Exception error = data.getError();                //handle error            }        }        @Override        public void onLoaderReset(Loader<ApiResponse<DAO>> loader) {}    });

If you want to request data multiple times use restartLoader instead of initLoader.


I've been using a kind of MVP (ModelViewPresenter) implementation on my Android apps. For the Retrofit request I made the Activity calls it's respective Presenter, which in turn makes the Retrofit Request and as a parameter I send a Callback with a custom Listener attached to it (implemented by the presenter). When the Callback reach onSuccess or onFailure methods I call the Listener's respective methods, which calls the Presenter and then the Activity methods :P

Now in case the screen is turned, when my Activity is re-created it attaches itself to the Presenter. This is made using a custom implementation of Android's Application, where it keeps the presenters' instance, and using a map for recovering the correct presenter according to the Activity's class.

I don't know if it's the best way, perhaps @pareshgoel answer is better, but it has been working for me.

Examples:

public abstract interface RequestListener<T> {    void onSuccess(T response);        void onFailure(RetrofitError error);}

...

public class RequestCallback<T> implements Callback<T> {    protected RequestListener<T> listener;        public RequestCallback(RequestListener<T> listener){        this.listener = listener;    }        @Override    public void failure(RetrofitError arg0){        this.listener.onFailure(arg0);    }    @Override    public void success(T arg0, Response arg1){        this.listener.onSuccess(arg0);    }}

Implement the listener somewhere on the presenter, and on the overrode methods call a presenter's method that will make the call to the Activity. And call wherever you want on the presenter to init everything :P

Request rsqt = restAdapter.create(Request.class);rsqt.get(new RequestCallback<YourExpectedObject>(listener));