简体   繁体   中英

Wait for retrofit asynchronous call response on an adapter?

I need to make a RetrofitCall in an adapter so I can run a loop inside of a onBindViewHolder like this:

public void checkguardadas(int id_usuario) {

    RetrofitService retrofitService = RetrofitService.getInstance();
    PabloAPI api = retrofitService.getApiProxyServer();
     Call<ArrayList<Oferta>> call = api.getGuardadas(1);

     call.enqueue(new Callback<ArrayList<Oferta>>() {
        @Override
        public void onResponse(Call<ArrayList<Oferta>> call, Response<ArrayList<Oferta>> response) {

            Log.d("traza", "por aqui");
            Log.d("traza", response.body().toString());
            guardadas = response.body();


        }

        @Override
        public void onFailure(Call<ArrayList<Oferta>> call, Throwable t) {
            Log.d("traza", "por alla");
            Log.d("traza", t.toString());
        }
    }); 

So I can call this:

public void onBindViewHolder(final OfertasAdapter.MyViewHolder viewHolder, 
int i) {
    Iterator it = guardadas.iterator();
    while (it.hasNext()) {
        if (ofertaList.get(i).getId() == guardadas.get(i).getId()) {
            viewHolder.guardar.setChecked(true);
        }
    }

The issue is that the retrofit call is not done before that code runs, so it gives null pointer exception and the app crashes. Any guess of what I can do? I've tried with several answers with no luck(Asynctask and a dependency called Rxjava).
Please keep in mind I'm a beginner, so try to be as much precise as you can.

In order to wait for Retrofit, load your Adapter entirely within onResponse .

Don't just assign the list content, actually create the adapter with the response body, and set it up to a RecyclerView

Also, this is how to properly set an Adapter contents. You don't want to dereference the Adapter's list object

guardadas.clear();
guardadas.addAll(response.body());
adapter.notifyDataSetChanged();

And remove the while loop. You're not using it.next() and your onBind should be responsible for only one view in the list

I got an answer in spanish StackOverflow:

Retrofit executes the onResponse method asynchronous so you need and event that executes when the onResponse method obtains the answer.

Create an interface, call it OnOfertasResponse :

public interface OnOfertasResponse
{
    void ofertas(ArrayList<Oferta> ofertas);
}

The 'ofertas' method will execute when you get the server's response. This is known as callback

Now modify the 'checkguardadas' method so it accepts the callback, and in the onResponse execute the 'ofertas' method

public void checkguardadas(int id_usuario, OnOfertasResponse callback) {
    RetrofitService retrofitService = RetrofitService.getInstance();
    PabloAPI api = retrofitService.getApiProxyServer();
    Call<ArrayList<Oferta>> call = api.getGuardadas(1);

    call.enqueue(new Callback<ArrayList<Oferta>>() {
        @Override
        public void onResponse(Call<ArrayList<Oferta>> call, Response<ArrayList<Oferta>> response) {

            Log.d("traza", "por aqui");
            Log.d("traza", response.body().toString());

            // ejecutamos el callback
            callback.ofertas(response.body());
        }

        @Override
        public void onFailure(Call<ArrayList<Oferta>> call, Throwable t) {
            Log.d("traza", "por alla");
            Log.d("traza", t.toString());
        }
    }); 
}

So to use it you just need to send the callback to 'checkguardadas' method

public void onBindViewHolder(final OfertasAdapter.MyViewHolder viewHolder, int i) {

    // le enviamos el callback al metodo checkguardadas
    checkguardadas(11,new OnOfertasResponse(){

        @Override
        public void ofertas(ArrayList<Oferta> ofertas){
            // este metodo se ejecutara cuando onResponse se ejecute
            Iterator it = ofertas.iterator();
            while (it.hasNext()) {
                if (ofertaList.get(i).getId() == ofertas.get(i).getId()) {
                    viewHolder.guardar.setChecked(true);
                }
            }
        }
    })

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM