【问题标题】:RecyclerView won't clear itself on new searchRecyclerView 不会在新搜索中自行清除
【发布时间】:2020-05-10 16:00:30
【问题描述】:

我正在开发这个简单的 Github 用户搜索应用:

每次我进行新搜索时,不是清除 recyclerview,而是简单地将新搜索结果附加到末尾,这不是我想要的。我在进行新搜索之前明确清除了搜索适配器,但似乎不正确。

一些相关代码:

MainActivity.java

@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu_search, menu);

        MenuItem searchItem = menu.findItem(R.id.action_search);
        SearchView searchView = (SearchView) searchItem.getActionView();
        searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                who = query;
                currentPage = 1;
                searchAdapter.clear();
                searchAdapter.notifyDataSetChanged();
                doSearchUser(query, currentPage);
                //searchAdapter.getFilter().filter(query);
                return false;
            }

            @Override
            public boolean onQueryTextChange(String newText) {
                return false;
            }
        });

        return true;
    }

SearchAdapter.java

package com.divbyzero.app.githubusersearch.adapter;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.bumptech.glide.Glide;
import com.divbyzero.app.githubusersearch.R;
import com.divbyzero.app.githubusersearch.model.User;

import java.util.ArrayList;
import java.util.List;

public class SearchAdapter extends RecyclerView.Adapter<SearchAdapter.SearchViewHolder> implements Filterable {
    private List<User> fullSearchResult;
    private List<User> filteredSearchResult;
    private List<User> theData;
    private Context ctxt;

    class SearchViewHolder extends RecyclerView.ViewHolder {
        ImageView github_profile_pic;
        TextView github_login;

       public SearchViewHolder(View itemView) {
            super(itemView);
            github_profile_pic = itemView.findViewById(R.id.github_profile_pic);
            github_login  = itemView.findViewById(R.id.github_login);
        }
    }

    public SearchAdapter(Context ctxt, List<User> list) {
        this.ctxt = ctxt;
        theData = list;
    }

    public void clear() {
        int size = theData.size();
        theData.clear();
        notifyItemRangeRemoved(0, size);
    }

    @NonNull
    @Override
    public SearchViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.search_item,
                parent, false);
        return new SearchViewHolder(v);
    }

    @Override
    public void onBindViewHolder(@NonNull SearchViewHolder holder, int position) {
        User user = theData.get(position);
        Glide.with(ctxt)
                .load(user.getAvatarUrl())
                .override(200, 200)
                .into(holder.github_profile_pic);
        holder.github_login.setText(user.getLogin());
    }

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

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

    private Filter searchFilter = new Filter() {
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            List<User> filteredList = new ArrayList<>();

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

                for (User item : fullSearchResult) {
                    if (item.getLogin().toLowerCase().contains(filterPattern)) {
                        filteredList.add(item);
                    }
                }
            }

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

            return results;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            filteredSearchResult.clear();
            filteredSearchResult.addAll((List) results.values);
            notifyDataSetChanged();
        }
    };

    public void updateData(List<User> newList){
        this.theData.clear();
        this.theData.addAll(newList);
    }
}

完整代码:https://github.com/anta40/GithubUserSearch

更新:

在加载更多数据时,我发现:Cannot call this method in a 滚动回调。滚动回调可能在测量期间运行 & 您无法更改 RecyclerView 数据的布局传递。任何方法 调用可能会改变 RecyclerView 或适配器的结构 内容应该推迟到下一帧

所以数据加载部分本身不正确。

如何解决这个问题?

【问题讨论】:

标签: android android-recyclerview


【解决方案1】:

有几个提示:

首先适配器每次都返回完整列表的大小,但它应该返回过滤列表的大小;并且您需要在没有执行过滤时将过滤后的列表初始化为原始列表(theData)。

所以,改变这个:

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

到:

@Override
public int getItemCount() {
    return filteredSearchResult == null ? 0 : filteredSearchResult.size();
}

并在一开始就初始化filteredSearchResult(在适配器构造函数中)

public SearchAdapter(Context ctxt, List<User> list) {
    this.ctxt = ctxt;
    theData = list;
    filteredSearchResult = list; // <<<<<<<<< here is the change
}

第二,你的onBindViewHolder()从原始列表中得到user(不是过滤后的列表,所以很可能是从未过滤的列表中返回了错误的数据);所以也将其更改为过滤列表。

所以用filteredSearchResult替换theData

@Override
public void onBindViewHolder(@NonNull SearchViewHolder holder, int position) {
    User user = filteredSearchResult.get(position); // <<<<<<<<< here is the change
    ...
}

并且每当您清除/设置原始列表时,更改过滤列表

public void clear() {
    int size = theData.size();
    theData.clear();
    filteredSearchResult.clear(); // <<<<<<<<< here is the change
    notifyItemRangeRemoved(0, size);
}


public void updateData(List<User> newList){
    this.theData.clear();
    this.theData.addAll(newList);
    filteredSearchResult.addAll(newList);  // <<<<<<<<< here is the change
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-11
    • 1970-01-01
    • 1970-01-01
    • 2012-10-03
    • 2016-03-31
    • 1970-01-01
    • 2021-10-12
    相关资源
    最近更新 更多