问题
I am trying to implement a search filter on complex object data in recyclerview when I type in the Edit text
first-time it works properly, but whenever I try to delete characters by pressing back-space in order to modify our search- I am repeatedly failing in this regard.
I can only search once !!
etSearch = (EditText) findViewById(R.id.edittext);
etSearch.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) {
myAdapter.filter(s);
}
@Override
public void afterTextChanged(Editable s) {
}
});
now the filter code
public void filter(CharSequence sequence) {
ArrayList<user> temp = new ArrayList<>();
if (!TextUtils.isEmpty(sequence)) {
for (user s : arr) {
Log.d("users ",s.getName());
if (s.getName().toLowerCase().contains(sequence)) {
temp.add(s);
}
}
} else {
temp.addAll(arrcopy);
}
arr.clear();
arr.addAll(temp);
notifyDataSetChanged();
temp.clear();
}
Whats the issue, I cannot search more than once-any help is appreciated
Here is my Adapter class
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyHolder>
{
Context cxt;
ArrayList<user> arr;
ArrayList<user> arrcopy;
DatabaseReference dref;
MyAdapter myAdapter;
public MyAdapter(Context context, ArrayList<user> arrayList)
{
cxt = context;
arr = arrayList;
arrcopy=new ArrayList<>(arr);
Log.d("Very start arr",arr.toString());
notifyDataSetChanged();
dref = FirebaseDatabase.getInstance().getReference("users");
}
@NonNull
@Override
public MyHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(cxt).inflate(R.layout.item_chatroom,viewGroup,false);
myAdapter = new MyAdapter(cxt, arr);
Log.d("Inside MyHolder arr",arr.toString());
return new MyHolder(view);
}
@Override
public void onBindViewHolder(@NonNull final MyHolder myHolder,final int i) {
final String name = arr.get(i).getUsername();
String pic=arr.get(i).getPic();
final String mail=arr.get(i).getEmail();
myHolder.name.setText(name);
Glide.with(myHolder.profile.getContext())
.load(pic)
.into(myHolder.profile);
myHolder.name.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(cxt,MainActivity.class);
intent.putExtra("Id",arr.get(i).getId());
intent.putExtra("Name",arr.get(i).getUsername());
cxt.startActivity(intent);
}
});
myHolder.info.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final SweetAlertDialog pDialog = new SweetAlertDialog(cxt, SweetAlertDialog.SUCCESS_TYPE);
pDialog.setTitleText("User Information e-mail ID");
pDialog.setContentText("Name: "+name+"\n\n E-mail: "+mail);
pDialog.setConfirmText("Ok");
pDialog.show();
}
});
}
@Override
public int getItemCount() {
return arr.size();
}
class MyHolder extends RecyclerView.ViewHolder
{
TextView name;
ImageView profile,info;
public MyHolder(@NonNull View itemView) {
super(itemView);
name = itemView.findViewById(R.id.txv);
profile=itemView.findViewById(R.id.profile);
info=itemView.findViewById(R.id.profileinfo);
}
}
public void filter(CharSequence sequence) {
ArrayList<user> temp = new ArrayList<>();
if (!TextUtils.isEmpty(sequence)) {
for (user s : arr) {
if (s.getName().toLowerCase().contains(sequence)) {
temp.add(s);
}
}
} else {
temp.addAll(arrcopy);
}
arr.clear();
arr.addAll(temp);
notifyDataSetChanged();
temp.clear();
}
}
回答1:
I assume the arrcopy is the copy of arr like:
ArrayList<User> arrcopy = new ArrayList<>(arr);
If you modify arr, it also change the content of arrcopy. And when no result matches, the arr is empty, so is the arrcopy.
else {
temp.addAll(arrcopy);
}
arr.clear();
arr.addAll(temp);
Now temp is empty, the arr data you set for adapter is empty, so issues happens.
Please try:
In MyAdapter:
Context cxt;
ArrayList<user> arr;
public MyAdapter(Context context) {
cxt = context;
dref = FirebaseDatabase.getInstance().getReference("users");
}
public void setData(ArrayList<User> arrayList) {
arr = arrayList;
notifyDataSetChanged();
}
Also put the filter() in your activity/fragment:
protected void onCreate(final Bundle savedInstanceState) {
etSearch = (EditText) findViewById(R.id.edittext);
etSearch.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
etSearch.requestFocus();
}
});
etSearch.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) {
filter(etSearch.getText().toString());
}
@Override
public void afterTextChanged(Editable s) {
}
});
etSearch.clearFocus();
mAdapter = new MyAdapter(this);
mAdapter.setData(arrayList);
mRecyclerView.setAdapter(mAdapter);
...
}
public void filter(String input) {
if (!TextUtils.isEmpty(input)) {
ArrayList<User> temp = new ArrayList<>();
for (user s : arr) {
if (s.getName().toLowerCase().contains(input)) {
temp.add(s);
}
}
mAdapter.setData(temp);
} else {
mAdapter.setData(arr);
}
mAdapter.notifyDataSetChanged();
}
回答2:
Implement Filterable
in your MyAdapter
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyHolder>
implements Filterable {
// change MyObject to user class
//replace myObjects with arr and reservedList with arrcopy
Context cxt;
ArrayList<MyObject> myObjects;
ArrayList<MyObject> reservedList;
DatabaseReference dref;
public MyAdapter(Context context, ArrayList<MyObject> arrayList){
cxt = context;
myObjects = arrayList;
reservedList = arrayList
Log.d("Very start arr",myObjects.toString());
// notifyDataSetChanged();
dref = FirebaseDatabase.getInstance().getReference("users");
}
//...
@Override
public Filter getFilter() {
return new Filter() {
@Override
protected FilterResults performFiltering(CharSequence charSequence) {
String charString = charSequence.toString().toLowerCase();
if (!charString.isEmpty()) {
List<MyObject> filteredList = new ArrayList<>();
for (MyObject row : reservedList) {
if (row.getName().toLowerCase().contains(charString)){
filteredList.add(row);
}
}
myObjects = filteredList;
} else {
myObjects = reservedList;
}
FilterResults filterResults = new FilterResults();
filterResults.values = myObjects;
return filterResults;
}
@Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
myObjects = (ArrayList<MyObject>) filterResults.values;
notifyDataSetChanged();
}
};
}
and from your activity
etSearch = (EditText) findViewById(R.id.edittext);
etSearch.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) {
myAdapter.getFilter().filter(s);
}
@Override
public void afterTextChanged(Editable s) {
}
});
来源:https://stackoverflow.com/questions/56640206/implementing-search-filter-causing-problem-when-pressed-backspace