Home > database >  Retrofit RecyclerViewAdapter List not assigned
Retrofit RecyclerViewAdapter List not assigned

Time:03-18

I am stuck in something

List is null as you see but I want to assign it to the response from API before the pass it to the Adapter. But the List passed as null and throw null exception. I call the API method in onCreate() method before the Adapter initialization but it does not work somehow.

I could not understand what I miss here. How can the List is not assigned. I tried to initialize new ArrayList and it did not throw any error but this time the RecyclerView is empty.

Any help?

Code:

public class InventoryInfoActivity extends AppCompatActivity {


InventoryInfoRecyclerViewAdapter inventoryInfoRecyclerViewAdapter;
RecyclerView recyclerView;
ProductService productService;
List<Product> productList;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_inventory_info);

    productService = new ProductService(this);
    // CALL METHOD
    this.getProductList();

    recyclerView  = findViewById(R.id.recycler_inventory);
    recyclerView.setLayoutManager(new LinearLayoutManager(InventoryInfoActivity.this));
    inventoryInfoRecyclerViewAdapter = new InventoryInfoRecyclerViewAdapter(productList,this);
    recyclerView.setAdapter(inventoryInfoRecyclerViewAdapter);
}

// API REQUEST
private void getProductList() {
    productService.getProducts().enqueue(new Callback<List<Product>>() {
        @Override
        public void onResponse(Call<List<Product>> call, Response<List<Product>> response) {
            if (response.isSuccessful()) {
                Log.i("REQUEST","OK");
               // ASSIGN
                productList = response.body();
            }else {
                Log.i("REQUEST","BAD");
                productList = new ArrayList<>();
            }
        }

        @Override
        public void onFailure(Call<List<Product>> call, Throwable t) {
            Log.i("REQUEST","FAILED");
            productList = new ArrayList<>();
        }
    });
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.search_action,menu);
    MenuItem menuItem = menu.findItem(R.id.action_search);

    SearchView searchView = (SearchView) menuItem.getActionView();
    searchView.setQueryHint("Ara");

    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String query) {
            return false;
        }

        @Override
        public boolean onQueryTextChange(String newText) {
            filter(newText);
            return false;
        }
    });


    return super.onCreateOptionsMenu(menu);
}

private void filter(String text) {
    ArrayList<Product> filteredlist = new ArrayList<>();
    for (Product item : productList) {
        if (item.getProductName().toLowerCase().contains(text.toLowerCase())) {
            filteredlist.add(item);
        }
    }
    if (filteredlist.isEmpty()) {
        Toast.makeText(this, "Böyle bir ürün yok", Toast.LENGTH_SHORT).show();
    } else {
        inventoryInfoRecyclerViewAdapter.filterList(filteredlist);
    }
}
}

LogCat:

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.tempter.stoktakip, PID: 32165
java.lang.NullPointerException: Attempt to invoke interface method 'int java.util.List.size()' on a null object reference

CodePudding user response:

The problem is here that after you get your response you should inform your adapter that you have a new List. There are many cool methods in RecyclerView called notifiyDataSetChanged.

What you did is not all wrong. Let me explain what you can do in your code:

  1. The variable that you define is a list which doesn’t have any value so its null.

private List<Product> items = new ArrayList<Product>();

or you should fix the getItems method in your adapter like below:

 public int getItems() {
    return items == null || items.isEmpty() ? 0 : items.size();
}
  1. After you get your response, please pass the new list to adapter. First you need to create in adapter a method that pass those data like below
    //  in your adapter
    public void setData(List<String> newItems) {
        adapterItems.clear();
        adapterItems.addAll(newItems);
        notifyDataSetChange();
    }

and then after your successfull api call you should do it like below:

private void getProductList() {
        productService.getProducts().enqueue(new Callback<List<Product>>() {
            @Override
            public void onResponse(Call<List<Product>> call, Response<List<Product>> response) {
                if (response.isSuccessful()) {
                    Log.i("REQUEST", "OK");
                    // ASSIGN
                    productList = response.body();
        
                    //!! This is here important

                    inventoryInfoRecyclerViewAdapter.setData(productList);

                    //!! This is here important 

                } else {
                    Log.i("REQUEST", "BAD");
                    productList = new ArrayList<>();
                }
            }

            @Override
            public void onFailure(Call<List<Product>> call, Throwable t) {
                Log.i("REQUEST", "FAILED");
                productList = new ArrayList<>();
            }
        });
    }

Now that’s it. You should now have you recyclerView updated with the new list.

CodePudding user response:

First, call the getProductListat the end of onCreate.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState); 
    List<Product> productlist = new ArrayList<Product>();
    setContentView(R.layout.activity_inventory_info);
    productService = new ProductService(this);
    recyclerView  = findViewById(R.id.recycler_inventory);
    recyclerView.setLayoutManager(new LinearLayoutManager(InventoryInfoActivity.this));
    inventoryInfoRecyclerViewAdapter = new InventoryInfoRecyclerViewAdapter(productList,this);
    recyclerView.setAdapter(inventoryInfoRecyclerViewAdapter);
    this.getProductList();
}

Then I presume that getProductList should be return a List of Product or a List of your another class.

private ArrayList<Product> getProductList() {
    productService.getProducts().enqueue(new Callback<List<Product>>() {
        @Override
        public void onResponse(Call<List<Product>> call, Response<List<Product>> response) {
            if (response.isSuccessful()) {
                Log.i("REQUEST","OK");
               // ASSIGN
                productList = response.body();
            }else {
                Log.i("REQUEST","BAD");
                productList = new ArrayList<>();
            }
        }

        @Override
        public void onFailure(Call<List<Product>> call, Throwable t) {
            Log.i("REQUEST","FAILED");
            productList = new ArrayList<>();
        }
    });
}
return productList;
  • Related