Ayoub MESBAHI
Ayoub MESBAHI

Reputation: 19

The retrofit API call is initiated after i try to display the results

I'm using the MVVM architecture, i have my model class "Category" and my ViewModel class and the MainActivity and Adapter for Recyclerview , All is works fine if i set the adapter inside the activity (inside onResponse methode of the Retrofit Call), but if i do it this way im not respecting the separation of the MVVM architecture, here is the methode that use to excute the call :

 public List<Category> getcategories() {

    RestInterface restInterface = rest.getInterfaceService();
    Call<List<Category>> productService = restInterface.getCategories();
    productService.enqueue(new Callback<List<Category>>() {
        @Override
        public void onResponse(Call<List<Category>> call, Response<List<Category>> response) {
            if (response.body() == null){
                Log.e(TAG, "responce Call response is null ");
            }else{
                Log.e(TAG, "repo : "+response.body().toString());
                categories = (ArrayList<Category>) response.body();

            }
        }

        @Override
        public void onFailure(Call<List<Category>> call, Throwable t) {
            Log.e(TAG, "Call Fail  : " + t.getMessage());
        }
    });
    Log.e(TAG, "repo 2: "+categories.toString());
    return categories;
}

here is the logcat results :

07-11 20:18:34.325 24369-24369/com.instadom E/DataRepository: repo 2: []

07-11 20:18:35.399 24369-24369/com.instadom E/DataRepository: repo : [exemple.com.models.Category@1df175e, exemple.com.models.Category@5cfc73f, exemple.com.models.Category@1e7380c, exemple.com.models.Category@7ceb555, exemple.com.models.Category@3014b6a, exemple.com.models.Category@a83985b, exemple.com.models.Category@3d5c8f8, exemple.com.models.Category@d1251d1]

what i can't understand is why i don't get any result in the "Log.e(TAG, "repo 2: "+categories.toString());" even tho "categories" is a class object

I would apreciate any help, thanks in advance,


Here is the code :

public List getcategories(final Callback> callback) { RestInterface restInterface = rest.getInterfaceService(); Call> productService = restInterface.getCategories(); productService.enqueue(new retrofit2.Callback>() { @Override public void onResponse(Call> call, Response> response) { if (response.body() == null){ Log.e(TAG, "responce Call response is null "); }else{ Log.e(TAG, "repo : "+response.body().toString()); categories = (ArrayList) response.body(); callback.onSuccess(categories); } }

        @Override
        public void onFailure(Call<List<Category>> call, Throwable t) {
            Log.e(TAG, "Call Fail  : " + t.getMessage());
            callback.onFailure(t.getMessage());
        }
    });
    Log.e(TAG, "result : "+categories.toString());
    return categories;
}
public interface Callback<T> {
    void onSuccess(ArrayList<Category> data);
    void onFailure(String reason);
}

here is the error :

java.lang.NullPointerException: Attempt to invoke interface method 'void instadom.com.repositories.DataRepository$Callback.onSuccess(java.util.ArrayList)' on a null object reference

Upvotes: 0

Views: 271

Answers (1)

Sony
Sony

Reputation: 7196

That is because productService.enqueue is an asynchronous call, The statement Log.e(TAG, "repo 2: "+categories.toString()); will be executed right after the call is is enqued and the onResponse or onFailure will be executed after a network call. pass in a callback to the getCategories() to get the category list like this

public interface Callback<List<Categories>> callback{
   void onSuccess(List<Categories> data);
   void onFailure(String reason);
}

or you can use a generic callback interface to use in all your network requests like this

public interface Callback<T> callback{
   void onSuccess(List<T> data);
   void onFailure(String reason);
}

then implement the callback functionality

public List<Category> getcategories(Callback<List<Category>> callback) {

    RestInterface restInterface = rest.getInterfaceService();
    Call<List<Category>> productService = restInterface.getCategories();
    productService.enqueue(new Callback<List<Category>>() {
        @Override
        public void onResponse(Call<List<Category>> call, Response<List<Category>> response) {
            if (response.body() == null){
                Log.e(TAG, "responce Call response is null ");
            }else{
                Log.e(TAG, "repo : "+response.body().toString());
                categories = (ArrayList<Category>) response.body();
                callback.onSuccess(categories);

            }
        }

        @Override
        public void onFailure(Call<List<Category>> call, Throwable t) {
            Log.e(TAG, "Call Fail  : " + t.getMessage());
            callback.onError(t.getMessage());
        }
    });
}

Upvotes: 2

Related Questions