Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practice to implement Retrofit callback to recreated activity?

I'm switching to Retrofit and trying to understand proper architecture for using it with async callbacks.

For example I have an interface:

interface RESTService{     @GET("/api/getusername")     void getUserName(@Query("user_id") String userId,                       Callback<Response> callback); } 

And I run this from main activity:

RestAdapter restAdapter = new RestAdapter.Builder()         .setServer("WEBSITE_URL")              .build(); RESTService api = restAdapter.create(RESTService.class); api.getUserName(userId, new Callback<Response> {...}); 

Then user rotates the device and I have newly created activity... What was happen here? How can I get response to the new activity (I assume that api call in background will execute longer than first activity life). Maybe I must use static instance of callback or what? Please show me the right way...

like image 221
lordmegamax Avatar asked Feb 16 '14 13:02

lordmegamax


2 Answers

Use otto. There are a lot of samples to mix otto and retrofit, for example https://github.com/pat-dalberg/ImageNom/blob/master/src/com/dalberg/android/imagenom/async/FlickrClient.java

Or read this post http://www.mdswanson.com/blog/2014/04/07/durable-android-rest-clients.html It answers on almost all questions

like image 138
avgx Avatar answered Sep 28 '22 21:09

avgx


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.

like image 23
Benjamin Avatar answered Sep 28 '22 20:09

Benjamin