Home > OS >  Cannot get items to show in a recycler view in Android Java
Cannot get items to show in a recycler view in Android Java

Time:10-25

I have this layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".fragments.InAppSettingsFragment"
    android:orientation="vertical">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@ id/rv_fare_matrix"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="10dp" />

</LinearLayout>

And an Adapter class as so:

public class FareMatrixAdapter extends RecyclerView.Adapter<FareMatrixAdapter.ViewHolder> {
    private List<FareMatrix> matrixList;

    public FareMatrixAdapter(List<FareMatrix> fareMatrices) { matrixList = fareMatrices; }

    @NonNull
    @NotNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull @NotNull ViewGroup parent, int viewType) {
        Context context = parent.getContext();
        LayoutInflater inflater = LayoutInflater.from(context);

        View FareMatrixItemView = inflater.inflate(R.layout.fare_matrix_item, parent, false);
        ViewHolder viewHolder = new ViewHolder(FareMatrixItemView);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(@NonNull @NotNull ViewHolder holder, int position) {
        FareMatrix fareMatrix = matrixList.get(position);

        TextView tvEntryPlaza = holder.tvEntryPlaza;
        TextView tvExitPlaza = holder.tvExitPlaza;
        TextView tvTotalAmount = holder.tvTotalAmount;

        tvEntryPlaza.setText(fareMatrix.getEntryPlaza());
        tvExitPlaza.setText(fareMatrix.getExitPlaza());
        tvTotalAmount.setText(String.valueOf(fareMatrix.getTotalAmount()));
    }

    @Override
    public int getItemCount() {
        return matrixList.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        public TextView tvEntryPlaza, tvExitPlaza, tvTotalAmount;
        public ViewHolder(View itemView) {
            super(itemView);

            tvEntryPlaza = itemView.findViewById(R.id.tv_item_entry_plaza);
            tvExitPlaza = itemView.findViewById(R.id.tv_item_exit_plaza);
            tvTotalAmount = itemView.findViewById(R.id.tv_item_total_amount);
        }
    }
}

And a fragment that uses this as so:

public class InAppSettingsFragment extends Fragment {

    private InAppSettingsViewModel viewModel;
    private ArrayList<FareMatrix> fareMatrices;
    private FareMatrixAdapter fareMatrixAdapter;
    private RecyclerView rvFareMatrix;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        viewModel = ViewModelProviders.of(this).get(InAppSettingsViewModel.class);
        fareMatrices = new ArrayList<>();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
       return inflater.inflate(R.layout.fragment_in_app_settings, container, false);
    }

    @Override
    public void onViewCreated(@NonNull @NotNull View view, @Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) {
        setupComponents();
        setupRecyclerView();
        setupLiveData();
        viewModel.getAllFareMatrices();
    }

    private void setupComponents() {
        rvFareMatrix = (RecyclerView) getView().findViewById(R.id.rv_fare_matrix);
    }

    private void setupRecyclerView() {
        fareMatrixAdapter = new FareMatrixAdapter(fareMatrices);
        rvFareMatrix.setLayoutManager(new LinearLayoutManager(getActivity().getApplicationContext()));
        rvFareMatrix.setAdapter(fareMatrixAdapter);
    }

    private void setupLiveData() {
        viewModel.MutableLiveDataFareMatrices().observe(getActivity(), new Observer<List<FareMatrix>>() {
            @Override
            public void onChanged(List<FareMatrix> list) {
                fareMatrices = (ArrayList<FareMatrix>) new ArrayList(Arrays.asList(list));
                fareMatrixAdapter.notifyDataSetChanged();
            }
        });
    }
}

The dataSet is a MutableLiveData that I load to the adapter when it changes. Somehow, I do not see my data in the recyclerview, though, upon debug, I get data. Thank you.

CodePudding user response:

       fareMatrices = (ArrayList<FareMatrix>) new ArrayList(Arrays.asList(list));
        fareMatrixAdapter.notifyDataSetChanged();

The problem is that you're setting fareMatrices to a new list. This doesn't update the list reference already in the adapter. It creates a new one that only the Activity knows about. So calling notifyDataSetChanged does nothing, because you didn't update the list the adapter has.

There's 2 ways to fix this. The first is that you can add it to the original list like this:

fareMatrices.clear()       
fareMatrices,addAll(Arrays.asList(list));
fareMatrixAdapter.notifyDataSetChanged();

The other way would be to add a setList function to the adapter, and have that function replace the list reference with the new one, then call notifyDataSetChanged().

I personally prefer method two, because it makes it impossible to forget to call notifyDataSet changed, makes it easy to move to a DiffUtil implementation that calls more performant notifyItemChanged, notifyItemAdded, and notifyItemDelete calls, and makes it explicit that you're changing the adapter values in the Activity, rather than do it via hidden side effect. You also make it easier to avoid race conditions, if that becomes a possibility in your code.

  • Related