Search code examples
androidlistviewonitemclicklistenerlistview-adapterandroid-filterable

Listview custom filter gives wrong item on-clicked in filtered list


When I filter my list and click on an item in listview it gives the wrong item information. Suppose my list contains X, Y, Z. And when I search the list for things starting with Y, I will get Y, but when I click Y, it returns me X or any random item data. My main activity:

public class exit_Activity extends AppCompatActivity {
    String Show_url = "https://retrieve.php";
    ListView removeView;
    MyAdapter adapter;
    public static ArrayList<Employee> employeeArrayList = new ArrayList<>();
    Employee employee;
   ProgressBar progressBar;
    private SwipeRefreshLayout mSwipeRefreshLayout;
    public static ArrayList<Employee> filterList = new ArrayList<>();
    EditText search;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_exit_);
        retrieveData();
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        ///

        mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.refreshlayout);
        mSwipeRefreshLayout.setColorSchemeResources(R.color.black, R.color.green, R.color.red);
        mSwipeRefreshLayout.setProgressBackgroundColorSchemeColor(getResources().getColor(R.color.main_blue));
        mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                mSwipeRefreshLayout.setRefreshing(true);
                Toast.makeText(getApplicationContext(), "Updating..", Toast.LENGTH_SHORT).show();
                retrieveData();
                // do nothing
            }
        });

        progressBar = (ProgressBar) findViewById(R.id.progressbar);
        Sprite FoldingCube = new Wave();
        progressBar.setIndeterminateDrawable(FoldingCube);
        //time and date
        final Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                exit_time();
                removeView.requestLayout();
                handler.postDelayed(this, 500);
            }
        }, 500);
        //
      
        //
        //exit
        removeView = findViewById(R.id.exit_entry);
        adapter = new MyAdapter(this, employeeArrayList);
        removeView.setAdapter(adapter);
        //end
        removeView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

                ProgressDialog progressDialog = new ProgressDialog(view.getContext());
                startActivity(new Intent(getApplicationContext(), Edit_Activity.class)
                        .putExtra("id", id));
                finish();
            }
        });
//searchView
        search = findViewById(R.id.search);
        search.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
            }

            @Override
            public void afterTextChanged(Editable s) {
                filterList.clear();
                if (s.toString().isEmpty()) {
                    removeView.setAdapter(new MyAdapter(getApplicationContext(), employeeArrayList));
                    adapter.notifyDataSetChanged();
                } else {
                    Filter(s.toString());
                }
            }
        });
        //end


    }

    public void retrieveData() {
        StringRequest request = new StringRequest(Request.Method.POST, Show_url,
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {

                        employeeArrayList.clear();
                        try {

                            JSONObject jsonObject = new JSONObject(response);
                            String sucess = jsonObject.getString("success");

                            JSONArray jsonArray = jsonObject.getJSONArray("veeta_vehicles");

                            if (sucess.equals("1")) {

                                for (int i = 0; i < jsonArray.length(); i++) {

                                    JSONObject object = jsonArray.getJSONObject(i);
                                    String id = object.getString("id");
                                    String number = object.getString("number");
                                    String name = object.getString("name");
                                    String time = object.getString("surnam");
                                    String date = object.getString("dob");
                                    String time = object.getString("die");
                                    String yes = object.getString("yes");
                                    employee = new Employee(id, number, name, time, date, time, yes);
                                    employeeArrayList.add(employee);
                                    adapter.notifyDataSetChanged();
                                }

                                progressBar.setVisibility(View.GONE);
                                mSwipeRefreshLayout.setRefreshing(false);
                                Toast.makeText(getApplicationContext(), "List Updated", Toast.LENGTH_SHORT).show();
                            }


                        } catch (JSONException e) {
                            e.printStackTrace();
                        }


                    }

                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Toast.makeText(exit_Activity.this, error.getMessage(), Toast.LENGTH_LONG).show();
                error.printStackTrace();
            }
        });

        RequestQueue requestQueue = Volley.newRequestQueue(this);
        requestQueue.add(request);

    }

    private void Filter(String text) {
        for (Employee post : employeeArrayList) {
            String filterPattern = text.toLowerCase().trim();
            if (post.getnumber().toLowerCase().contains(filterPattern)) {
                filterList.add(post);
            }
        }
        removeView.setAdapter(new MyAdapter(getApplicationContext(), filterList));
        adapter.notifyDataSetChanged();
    }

MyAdapter.class:

public class MyAdapter extends ArrayAdapter<Employee> implements Filterable{

    Context context;
    List<Employee> arrayListEmployee;


    public MyAdapter(@NonNull Context context, List<Employee> arrayListEmployee) {
        super(context, R.layout.custom_list_item,arrayListEmployee);

        this.context = context;
        this.arrayListEmployee = arrayListEmployee;

    }

    @NonNull
    @Override
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {

        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.custom_list_item,null,true);

        TextView tvID = view.findViewById(R.id.txt_id);
        TextView tvName = view.findViewById(R.id.view_vehicle_number);

        tvID.setText(arrayListEmployee.get(position).getId());
        tvName.setText(arrayListEmployee.get(position).getnumber());

        return view;
    }
    @Override
    public int getCount() {
        return super.getCount();
    }

Pls explain in easy language and provide my solution. I'm new to android studio. thank you x1000 in Advance


Solution

  • I found problem in method (check comments):

    private void Filter(String text) {
            for (Employee post : employeeArrayList) {
                String filterPattern = text.toLowerCase().trim();
                if (post.getnumber().toLowerCase().contains(filterPattern)) {
                    filterList.add(post);
                }
            } 
            //below every time you create new instance of MyAdapter - try comment this line (below) and test it 
            removeView.setAdapter(new MyAdapter(getApplicationContext(), filterList));
            //this is your first instance but you set new adapter for listView
            adapter.notifyDataSetChanged();
        } 
    

    and replace your method with this:

    private void Filter(String text) {
            for (Employee post : employeeArrayList) {
                String filterPattern = text.toLowerCase().trim();
                if (post.getnumber().toLowerCase().contains(filterPattern)) {
                    filterList.add(post);
                }
            }
            adapter.clear()
            adapter.addAll(filterList);
        }
    

    So you don't create a new instance of the adapter every time, just swap data of the existing adapter

    I haven't tested it but it should work fine with OnItemClickListener...

    EDITED

    Also same problem...

    @Override
        public void afterTextChanged(Editable s) {
            filterList.clear();
            if (s.toString().isEmpty()) {
                //you set new instance of adapter and notify old, try comment this line (below) and test it 
                //removeView.setAdapter(new MyAdapter(getApplicationContext(), employeeArrayList)); 
                adapter.notifyDataSetChanged();
            } else {
                Filter(s.toString());
            }
        }
    
          
    

    Change to this

            @Override
            public void afterTextChanged(Editable s) {
                if (!s.toString().isEmpty()) {
                     filterList.clear(); //TODO here is problem, move this to your filter method
                     Filter(s.toString());
                } else {
                   //Do nothing, if the EditText field is empty the list will remain filled
                }
            }
    

    There are other ways to solve this and improve but I don't want to confuse you, because android is new experience for you

    EDITED

    You are using an ArrayAdapter but I thought it is RecyclerView, forget swapData method and try new changes... Sorry

    adapter.clear()
    adapter.addAll(filterList);