1

I have used Square / Retrofit Restful framework to get data from a Restful service, and it works like a charm, code snippet is like below:

FooService restInterface =  new RestAdapter.Builder().setEndpoint(FooService.URL).build().create(FooService.class);
    restInterface.getAllFoos(new Callback<FooModel>() {
        @Override
        public void success(FooModel model, Response response) {
                //get a list of Foo instances.
            }
            updateUI();
        }

        @Override
        public void failure(RetrofitError error) {
                //log errors.
        }

    });

I understand this is an async call, however can I have a spinning icon on the top while retrofit is busy working on the background? In case the network is not available.

Also is it possible to set a timeout so when the time is up, a prompt of options to continue waiting or abort the mission?

I noticed there was something close on this site: Is it possible to show progress bar when upload image via Retrofit 2 , but still couldn't figure it out how to do it. Besides, my requirement might be simpler.

Community
  • 1
  • 1
J.E.Y
  • 1,173
  • 2
  • 15
  • 37

2 Answers2

3

Yes, this is perfectly possible.

You can make a call to some sort of startSpinner() function just before or even just after the call to the endpoint. Then, in success() and failure(), you can make a call to some sort of stopSpinner() function.

As for the timeout functionality, you sould set the timeout on the underlying HTTP client rather than on Retrofit. If you do not want to use the default timeout, you can read more about setting a custom one here.

Community
  • 1
  • 1
M.S.
  • 1,091
  • 1
  • 11
  • 27
  • Although this works, it is a pretty basic solution. This does not consider the case where multiple requests happen at the same time, and It requires to write the functions every time you have a new api service method. – WilliamX Nov 17 '22 at 23:59
0

A better approach is to consolidate this piece of logic into a central location. For this you can use an interceptor and just broadcast a local intent on any request your app makes.

Take a look to this Interceptor class written in Kotlin (Same works on Java):

internal class BusyInterceptor constructor(val appContext: Context) : Interceptor {
  @Throws(IOException::class)
  override fun intercept(chain: Interceptor.Chain): Response {
    val request = chain.request()
    val t1 = System.nanoTime()

    // Times are different, so it does handle request and response at the same time
    Log.d("REQUEST BUSY INTERCEPTOR------------>","request time: " + t1)

    val intent = Intent()
    intent.action = "IS_BUSY"
    intent.putExtra("isBusy", true)
    LocalBroadcastManager.getInstance(appContext).sendBroadcast(intent)



    val response: Response = chain.proceed(request)
    val t2 = System.nanoTime()
    Log.d("RESPONSE BUSY INTERCEPTOR------------>","request time: " + t2)

    val intent2 = Intent()
    intent2.action = "IS_BUSY"
    intent2.putExtra("isBusy", false)
    LocalBroadcastManager.getInstance(appContext).sendBroadcast(intent2)

    return response
  }
}

Then you just add the interceptor to your okhttp client:

// Add Busy Interceptor 
val busyInterceptor = BusyInterceptor(appContext)
okHttpClient.addInterceptor(busyInterceptor)

This way, you are not dependent on any specific activity/fragment anymore, you just have to make sure you are using an Application file, and registering for the broadcast.

i.e. MyApplication.java:

@Override
    public void onCreate() {
        super.onCreate();

        BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if(intent.getBooleanExtra("isBusy", false)){
                    ProgressHUD.showDummyProcessing(getCurrentActivity());
                } else {
                    ProgressHUD.hideDummyProcessing(getCurrentActivity());
                }
            }
        };

        IntentFilter filter = new IntentFilter("IS_BUSY");
        LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, filter);

This gives you the flexibility to decide what you want to do every time a request is made regardless where the user is currently at.

For simplicity I didn't include a queue logic to manage multiple/parallel requests, but its fairly simple to keep track of this at the same file using ArrayList or similar.

Also, some this supports "silent" requests where you don't want to display any feedback to the user (analytics, logging, etc), just pass additional "extras" in the intent :)

WilliamX
  • 357
  • 4
  • 17