【问题标题】:RecyclerView (Custom Adapter) not refreshing the List on searchRecyclerView(自定义适配器)不刷新搜索列表
【发布时间】:2021-10-12 09:37:15
【问题描述】:

这是我在 Stackoverflow 上的第一个问题。我最近才开始进行 Android 开发。


我想做的事:

我有一个人员列表,我想根据用户在我的工具栏(不是 ActionBar)的搜索框中的输入来过滤/搜索 RecyclerView(使用自定义适配器)列表 (Initial List)

我的问题:

最初,什么都没有发生。这份名单根本没有改变。现在,列表发生了变化,但无论输入什么,都只会显示一个固定列表项(Current Search output)。我的回收器适配器没有刷新到新的过滤列表。而且我在 bulid 或 logcat 中没有收到任何错误。

我尝试过的:

经过一整天的调试,并在我的布局管理器和 RecycleView 适配器中修复了一些“NullPointerExceptions”,并尝试了 2 种不同的过滤方法。即使我能够生成filtered array (List values in Logcat),我也无法得到结果。我尝试使用“notifyDataSetChanged()”、“notifyItemRangeChanged()”和“*notifyAll();,但都是徒劳的......

请帮忙.....

公共类 MainActivity 扩展 AppCompatActivity {

ArrayList<Consultant> consultants= new ArrayList<>();
ArrayList<Consultant> allConsultants = new ArrayList<>();
int rating=5;
int price = 10000;

String categoryFilter;
String ratingFilter;

RecyclerView recyclerView;
Consultant_RecyclerAdapter.RecyclerViewClickListener listener;
Consultant_RecyclerAdapter adapter= new Consultant_RecyclerAdapter(consultants,listener);

Spinner s_categories;
Spinner s_rating;

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

    Toolbar toolbar = findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    recyclerView= findViewById(R.id.RecycleView);


    s_categories=findViewById(R.id.Spinner_Category);
    s_rating=findViewById(R.id.Spinner_Rating);

    addToList();
    setUpAdapter();
}

private void setUpAdapter() {
    Log.i("Adapter","Started");
    setOnClickListener();
    Consultant_RecyclerAdapter adapter = new Consultant_RecyclerAdapter(consultants,listener);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    recyclerView.setItemAnimator(new DefaultItemAnimator());
    recyclerView.setAdapter(adapter);
    Log.i("Adapter","Ended");
}
private void addToList(){
    consultants.add(new Consultant("Dr Kapoor", "consultant_id", "profilePic_src", new String[]{"Dentist","Dermatology"}, 1000, 5));
    consultants.add(new Consultant("Dr Pankaj Kumar", "consultant_id", "profilePic_src", new String[]{"Psychology","Respiratory"}, 3000, 1));
    consultants.add(new Consultant("Dr Harsh Jha", "consultant_id", "profilePic_src", new String[]{"Internal Medicine"}, 1500, 5));
    consultants.add(new Consultant("Dr Gaurav Singh", "consultant_id", "profilePic_src", new String[]{"Dentist","Cardiologist"}, 3500, 4));
    consultants.add(new Consultant("Dr Aman", "consultant_id", "profilePic_src", new String[]{"Lungs","Neuro"}, 1000, 2));
    consultants.add(new Consultant("Dr Jatin Chabra", "consultant_id", "profilePic_src", new String[]{"Psychology"}, 5000, 3));
    Log.i("List","Done");
    allConsultants=new ArrayList<>(consultants);
}
private void setOnClickListener() {
    listener = new Consultant_RecyclerAdapter.RecyclerViewClickListener() {
        @Override
        public void onClick(View v, int position) {
           Intent intent = new Intent(getApplicationContext(), ConsultantProfileActivity.class);
            intent.putExtra("consultant_name", consultants.get(position).getName());
            intent.putExtra("pic_src", consultants.get(position).getProfilePic_src());
            intent.putExtra("about", consultants.get(position).getAbout());
            intent.putExtra("consultant_id",consultants.get(position).getConsultant_id());
            intent.putExtra("categories",consultants.get(position).getCategories());

            startActivity(intent);
        }
    };
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.search, menu);

    MenuItem menuItem = menu.findItem(R.id.action_search);
    SearchView searchView = (SearchView) menuItem.getActionView();
    searchView.setQueryHint("Search....");
    searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);

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

        @Override
        public boolean onQueryTextChange(String newText) {
            Log.i("Search","QueryChanged");
            //adapter.getFilter().filter(newText);
            filter(newText);
            return false    ;
        }
    });
    return true;
}

private void filter(String text) {
    // creating a new array list to filter our data.
    ArrayList<Consultant> filteredlist = new ArrayList<>();

    // running a for loop to compare elements.
    for (Consultant item : allConsultants) {
        Log.i("Filter: ",item.getName()+"...."+text);

        // checking if the entered string matched with any item of our recycler view.
        if (item.getName().toLowerCase().contains(text.toLowerCase())) {
            Log.i("Match","Found");
            // if the item is matched we are
            // adding it to our filtered list.
            filteredlist.add(item);
        }
    }
    Log.i("Filter: ",(filteredlist.toString()));

    if (filteredlist.isEmpty()) {
        // if no item is added in filtered list we are
        // displaying a toast message as no data found.
        Toast.makeText(this, "No Data Found..", Toast.LENGTH_SHORT).show();
    } else {
        // at last we are passing that filtered
        // list to our adapter class.
        adapter.filterList(filteredlist);
    }

}

}

请忽略下面Recycler Adapter中的搜索方式,我目前正在使用mainActivity中的搜索方式

公共类 Consultant_RecyclerAdapter 扩展 RecyclerView.Adapter{ ArrayList 顾问; ArrayList AllConsultants,preFilteredList;

private RecyclerViewClickListener listener;

public Consultant_RecyclerAdapter(ArrayList<Consultant> consultants, RecyclerViewClickListener listener) {
    this.consultants = consultants;
    this.listener = listener;
    //AllConsultants = new ArrayList<>(consultants);
    //preFilteredList = new ArrayList<>(consultants);
}


//NOTIFYING THE ADAPTER ABOUT UPDATE


public void filterList(ArrayList<Consultant> filteredlist) {

    consultants.clear();

    consultants.addAll(filteredlist);

    notifyDataSetChanged();


}



public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {


    private TextView name, rating, price, category;
    private ImageView profile;

    public MyViewHolder(@NonNull View view) {
        super(view);
        name = view.findViewById(R.id.textView_Name);
        profile = view.findViewById(R.id.imageView_ProfilePic);
        category = view.findViewById(R.id.textView_Category);
        rating = view.findViewById(R.id.textView_Rating);
        price = view.findViewById(R.id.textView_Price);
        view.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {listener.onClick(view, getAdapterPosition()); }
}

@NonNull
@Override
public Consultant_RecyclerAdapter.MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.consultant_list_item, parent, false);
    return new MyViewHolder(itemView);
}

@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
    String name = consultants.get(position).getName();
    String profilePic_src = consultants.get(position).getProfilePic_src();
    float rating = consultants.get(position).getRating();
    String categories = "";
    //Converting Array to string
    for (String i : consultants.get(position).getCategories()) {
        categories = i + ", " + categories;
    }
    int price = consultants.get(position).getPrice();

    holder.name.setText(name);
    holder.category.setText(categories);
    holder.price.setText(String.valueOf(price));
    holder.rating.setText(String.valueOf(rating));
    holder.profile.setImageResource(R.drawable.consultant);}

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

public interface RecyclerViewClickListener {
    void onClick(View v, int position);
}

    public void listUpdate(String categoryFilter, String ratingFilter) {
    preFilteredList = new ArrayList<>();

    if (categoryFilter != null || ratingFilter != null) {
        for (Consultant item : AllConsultants) {
            if (String.valueOf(item.getRating()).toLowerCase(Locale.ROOT).contains(ratingFilter) && item.getCategories().toString().toLowerCase(Locale.ROOT).contains(categoryFilter)) {
                preFilteredList.add(item);
            }
        }
    }else{
        preFilteredList= new ArrayList<Consultant>(AllConsultants);
    }
    consultants.clear();
    consultants.addAll(preFilteredList);
    getFilter();

}

@Override
public Filter getFilter() {
    return theFilter;
}

public Filter theFilter = new Filter() {
    @Override
    protected FilterResults performFiltering(CharSequence constraint) {
        List<Consultant> filteredList = new ArrayList<>();

        if (constraint == null || constraint.length() == 0) {
            filteredList.addAll(AllConsultants);
        } else {
            String filterPattern = constraint.toString().toLowerCase().trim();

            for (Consultant item : AllConsultants) {
                Log.i("Filter: ",item.getName()+"...."+filterPattern);
                if (item.getName().toLowerCase().contains(filterPattern)) {
                    Log.i("Match","Found");
                    filteredList.add(item);
                }
            }
        }

        FilterResults results = new FilterResults();
        results.values = filteredList;

        return results;
    }

    @Override
    protected void publishResults(CharSequence constraint, FilterResults results) {
        Log.i("Filter ","Published");
        consultants.clear();
        consultants.addAll((List) results.values);
        notifyDataSetChanged();

    }
};

}

【问题讨论】:

    标签: java android android-studio android-recyclerview custom-adapter


    【解决方案1】:

    不要使用活动来过滤结果,这会降低性能。在 Adapter 中使用 Filterable 接口,它在后台线程上执行过滤并将结果发布到主线程上。我看到你已经实现了。

    通过查看您的适配器代码,我认为它应该可以工作,因为您维护了两个列表 completefiltered 的不同引用。

    我的罪魁祸首是您已将适配器初始化为全局变量,但您设置为 RecyclerView 的适配器是您在本地创建的另一个适配器。解决这个问题,它应该可以工作。

    private Consultant_RecyclerAdapter adapter ; // Global variable
    
    
    private void setUpAdapter() {
    Log.i("Adapter","Started");
    setOnClickListener();
    adapter = new Consultant_RecyclerAdapter(consultants,listener);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    recyclerView.setItemAnimator(new DefaultItemAnimator());
    recyclerView.setAdapter(adapter);
    Log.i("Adapter","Ended");
    }
    

    【讨论】:

    • 刚刚试过这个。错误:java.lang.NullPointerException: at java.util.ArrayList.addAll(ArrayList.java:588) at (Consultant_RecyclerAdapter.java:157) Consultant_RecyclerAdapter.java:157=> advisors.addAll((List) results.values); RecyclerView 适配器中的最后 6 行。我是android dev的新手,如果您能进一步指导我,那将非常有帮助
    • 尝试将适配器中的consulatant ArrayList 设置为私有/公共。还是不行
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多