Home > Back-end >  How to filter item in RecyclervView connected to firebase with onclick listener android
How to filter item in RecyclervView connected to firebase with onclick listener android

Time:05-21

I am creating an app where users can search items on the search view bar. Firebase Realtime Database, RecyclerView, and SearchView are already set up but I am having a problem. So when the app opens, the items on the firebase database are shown to the RecyclerViewwithout problems. When I click on the item, it shows additional information about the item. Now the problem is when I search an item in the SearchView, the items are perfectly filtered but when I click on the item the data that is shown is not the data that should be displayed, and sometimes it crashes if the item does not have that kind of attribute on the database. I Still don't know how to deal with this so I hope someone can help me.

Here are my codes:

Adapter Code:

public class CarAdapter extends RecyclerView.Adapter<CarAdapter.MyViewHolder>{
    private final RecyclerViewInterface recyclerViewInterface;
    Context context;
    ArrayList<Car> list;


    @SuppressLint("NotifyDataSetChanged")
    public void setFilteredList(ArrayList<Car> filteredList){
        this.list=filteredList;
        notifyDataSetChanged();
    }

    public CarAdapter(Context context, ArrayList<Car> list, RecyclerViewInterface recyclerViewInterface) {
        this.context = context;
        this.list = list;
        this.recyclerViewInterface = recyclerViewInterface;
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(context).inflate(R.layout.car_item,parent,false);
        return new MyViewHolder(v,recyclerViewInterface);
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
        Car car = list.get(position);
        holder.bmy.setText(car.getBmy());
        holder.city.setText(car.getLocation());
        holder.price.setText(car.getPriceRate());
        Glide.with(holder.img.getContext()).load(car.getCarUrl()).into(holder.img);
    }

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

    public static class MyViewHolder extends  RecyclerView.ViewHolder{
        ImageView img;
        TextView bmy, city , price;

        public MyViewHolder(@NonNull View itemView, RecyclerViewInterface recyclerViewInterface) {
            super(itemView);

            img = (ImageView)itemView.findViewById(R.id.ivCarDisplay);
            bmy = (TextView)itemView.findViewById(R.id.tvBMY);
            city = (TextView)itemView.findViewById(R.id.tvLocation);
            price = (TextView)itemView.findViewById(R.id.tvPricing);

            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if(recyclerViewInterface != null){
                        int position = getAdapterPosition();

                        if (position != RecyclerView.NO_POSITION){
                            recyclerViewInterface.onItemClick(position);
                        }
                    }
                }
            });
        }
    }

}

Recyclerview code:

public class ExploreFragmentMenu extends Fragment implements RecyclerViewInterface {

    RecyclerView recyclerView;
    DatabaseReference database;
    CarAdapter myAdapter;
    ArrayList<Car> list, filteredList;
    SwipeRefreshLayout swipeRefreshLayout;
    String carId,uId;
    DataSnapshot dataSnapshot;
    SearchView searchView;
    Boolean isFiltered;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_explore, container, false);

        String databaseLocation = getString(R.string.databasePath);
        isFiltered = false;
        recyclerView = view.findViewById(R.id.carListRV);
        database = FirebaseDatabase.getInstance(databaseLocation).getReference("vehicle");
        recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
        list = new ArrayList<>();


        swipeRefreshLayout = view.findViewById(R.id.swipeRefresh);
        searchView = view.findViewById(R.id.searchView);
        searchView.setFocusable(false);

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

            @Override
            public boolean onQueryTextChange(String newText) {
                filterList(newText);
                isFiltered = true;
                return true;
            }
        });

        myAdapter = new CarAdapter(getContext(),list,this);
        recyclerView.setAdapter(myAdapter);


        database.addValueEventListener(new ValueEventListener() {
            @SuppressLint("NotifyDataSetChanged")
            @Override
            public void onDataChange(@NonNull DataSnapshot snapshot) {
                dataSnapshot = snapshot;
                list.clear();
                for (DataSnapshot dataSnapshot : snapshot.getChildren()){
                    for(DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()){
                        Car car = dataSnapshot1.getValue(Car.class);
                        list.add(car);
                    }
                }
                myAdapter.notifyDataSetChanged();
            }
            @Override
            public void onCancelled(@NonNull DatabaseError error) { }
        });

        swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                list.clear();
                final Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        database.addValueEventListener(new ValueEventListener() {
                            @SuppressLint("NotifyDataSetChanged")
                            @Override
                            public void onDataChange(@NonNull DataSnapshot snapshot) {
                                for (DataSnapshot dataSnapshot : snapshot.getChildren()){
                                    for(DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()){
                                        Car car = dataSnapshot1.getValue(Car.class);
                                        list.add(car);
                                    }
                                }
                                myAdapter.notifyDataSetChanged();
                            }
                            @Override
                            public void onCancelled(@NonNull DatabaseError error) {

                            }
                        });
                        swipeRefreshLayout.setRefreshing(false);
                    }
                }, 500);
            }
        });
        return view;
    }

    private void filterList(String newText) {
        filteredList = new ArrayList<>();

        database.addValueEventListener(new ValueEventListener() {
            @SuppressLint("NotifyDataSetChanged")
            @Override
            public void onDataChange(@NonNull DataSnapshot snapshot) {
                filteredList.clear();
                for (DataSnapshot dataSnapshot : snapshot.getChildren()){
                    for(DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()){
                        long size = dataSnapshot.getChildrenCount();
                        String city = dataSnapshot1.child("city").getValue().toString();
                        String province = dataSnapshot1.child("province").getValue().toString();
                        String street = dataSnapshot1.child("address1").getValue().toString();
                        String barangay = dataSnapshot1.child("address2").getValue().toString();

                        if(city.toLowerCase().contains(newText.toLowerCase())){
                            Car car = dataSnapshot1.getValue(Car.class);
                            filteredList.add(car);
                        }
                        else if(province.toLowerCase().contains(newText.toLowerCase())){
                            Car car = dataSnapshot1.getValue(Car.class);
                            filteredList.add(car);
                        }
                        else if(street.toLowerCase().contains(newText.toLowerCase())){
                            Car car = dataSnapshot1.getValue(Car.class);
                            filteredList.add(car);
                        }
                        else if(barangay.toLowerCase().contains(newText.toLowerCase())){
                            Car car = dataSnapshot1.getValue(Car.class);
                            filteredList.add(car);
                        }
                    }
                    myAdapter.setFilteredList(filteredList);
                    myAdapter.notifyDataSetChanged();
                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError error) {
            }
        });
    }

    @Override
    public void onItemClick(int position) {
        int index  = 0;
        for(DataSnapshot childSnapshot : dataSnapshot.getChildren()){
            if(index == position){
                DatabaseReference currentReference = childSnapshot.getRef();
                carId = currentReference.getKey();
            }
            for(DataSnapshot childSnapshot2 : childSnapshot.getChildren()){
                if(index == position){
                    DatabaseReference ref2 = childSnapshot2.getRef();
                    uId = ref2.getKey();
                }
            }
            index  ;
        }
        Intent intent = new Intent(getContext(), CarDetails.class);
        intent.putExtra("carId", carId);
        intent.putExtra("userId", uId);
        startActivity(intent);
    }
}

So these are the codes I used to display items and filtered items in recyclerview. What I thought causing this problem is that the items that are displayed are based on the how the data in database is placed or structured or positioned. So when it is displayed in the recyclerview it should have the right position and when the user clicks an item, it should display the correct details about the item. So when I try to filter the items, the items in recyclerview will be jumbled based on the input text thus ruining the position on recyclerview and will give the wrong details about the item because order of the data in database will not change. I have tried other ways to solve this but I really cant. I hope I have explained all the necessary details and I hope someone can help me.

CodePudding user response:

If you need to do some operation with the object on which the user has clicked, then you should not pass to the onItemClick() the position, but the object itself.

So inside your adapter class, instead of setting the values of img, bmy, city and price from inside onBindViewHolder to the ViewHolder class views, pass the entire Car object. That being said, inside the activity, you'll have the correct Car object on which the user clicked and not an incorrect one based on a position.

  • Related