简体   繁体   English

我在使用 RecyclerView 应用 SearchView 时遇到问题

[英]I am having trouble applying SearchView with RecyclerView

I am trying to implement the SearchView from the support library.我正在尝试从支持库中实现 SearchView。 I want the user to be to use the SearchView to filter a List of Words in a RecyclerView.我希望用户使用 SearchView 过滤 RecyclerView 中的单词列表。

I have followed a few tutorials so far and I have added the SearchView to the ActionBar, But When the application starts everything works fine but when I click on the Search Icon.到目前为止,我已经遵循了一些教程,并将 SearchView 添加到了 ActionBar,但是当应用程序启动时一切正常,但是当我单击搜索图标时。 The app shows the following Error in the Logcat for a second and automatically app restarts and the error disappears.该应用程序在 Logcat 中显示以下错误一秒钟并自动重新启动应用程序并且错误消失。 But the Search Functionality is not working但是搜索功能不起作用

Error I received Error Image错误我收到错误图片

This is my SearchActivity:这是我的搜索活动:

enter code here在此处输入代码


public class SearchActivity extends AppCompatActivity {

    private Toolbar mToolbar;
    private RecyclerView mRecyclerView;
    private RecyclerViewAdpater mAdpater;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_search);
        mToolbar=findViewById(R.id.toolbarSearch);
        setSupportActionBar(mToolbar);
        mRecyclerView=findViewById(R.id.recyclerViewSearch);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        mAdpater=new RecyclerViewAdpater(DataSevices.mChineseColors,this);
        mRecyclerView.setAdapter(mAdpater);
    }

    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.toolbar_search_menu,menu);
        MenuItem item=menu.findItem(R.id.action_search);
        SearchView searchView=(SearchView) item.getActionView();
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                return false;
            }

            @Override
            public boolean onQueryTextChange(String newText) {
                mAdpater.getFilter().filter(newText);
                return false;
            }
        });
        return true;
    }
}

And this is my RecyclerView Adapter Class这是我的 RecyclerView 适配器 Class

public class RecyclerViewAdpater extends RecyclerView.Adapter<RecyclerViewAdpater.MyViewHolder> implements Filterable {

private List<ChineseLanguage> mChineseLanguages;
private List<ChineseLanguage> mChineseLanguagesFull;
private Context mContext;
private MediaPlayer mMediaPlayer;

public RecyclerViewAdpater(List<ChineseLanguage> chineseLanguages, Context context) {
    mChineseLanguages = chineseLanguages;
    mChineseLanguagesFull=new ArrayList<>(mChineseLanguages);
    mContext = context;
}

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

@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, final int position) {
    holder.txtEnglishWord.setText(mChineseLanguages.get(position).getEnglishAlphabet());
    holder.txtChineseWord.setText(mChineseLanguages.get(position).getChineseAlphabet());
    holder.txtPronunciation.setText(mChineseLanguages.get(position).getPronounciation());

    holder.btnPlay.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            releasaMedia();
            mMediaPlayer=MediaPlayer.create(mContext,mChineseLanguages.get(position).getSound());
            mMediaPlayer.start();
            mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mp) {
                    releasaMedia();
                }
            });

        }
    });

}

private void releasaMedia(){
    if (mMediaPlayer!=null){
        mMediaPlayer.release();
    }
    mMediaPlayer=null;
}

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

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

private Filter filter=new Filter() {
    @Override
    protected FilterResults performFiltering(CharSequence constraint) {
        List<ChineseLanguage> filteredList=new ArrayList<>();
        if (constraint.toString().isEmpty()){
            filteredList.addAll(mChineseLanguagesFull);
        }else {
            for(ChineseLanguage item: mChineseLanguagesFull){
                if (item.getEnglishAlphabet().toLowerCase().contains(constraint.toString().toLowerCase().trim())){
                    filteredList.add(item);
                }
            }
        }
        FilterResults filterResults=new FilterResults();
        filterResults.values=filteredList;
        return filterResults;
    }

    @Override
    protected void publishResults(CharSequence constraint, FilterResults results) {
      mChineseLanguages.clear();
      mChineseLanguages.addAll((Collection<? extends ChineseLanguage>) results.values);
      notifyDataSetChanged();
    }

    };


    public class MyViewHolder extends RecyclerView.ViewHolder {

    TextView txtEnglishWord,txtChineseWord,txtPronunciation;
    ImageButton btnPlay;

    public MyViewHolder(@NonNull View itemView) {
        super(itemView);
        txtEnglishWord=itemView.findViewById(R.id.txtEnglishWord);
        txtChineseWord=itemView.findViewById(R.id.txtChineseWord);
        txtPronunciation=itemView.findViewById(R.id.txtPronunciation);
        btnPlay=itemView.findViewById(R.id.btnPlay);
    }
}

} }

Please correct me if I have done anything wrong如果我做错了什么请纠正我

Your leak is most likely happening because your adapter is still alive even after activity is dead and it carries the activity's context causing the memory leak.您的泄漏很可能发生,因为即使在活动结束后您的适配器仍然存在并且它携带活动的上下文导致 memory 泄漏。 It's not required to pass context through activity, you can get it from within the class.不需要通过活动传递上下文,您可以从 class 中获取它。 Here instead of declaring global mContext variable in the adapter class, you can simply get your context in the following way:此处无需在适配器 class 中声明全局 mContext 变量,您可以通过以下方式简单地获取上下文:

public class MyViewHolder extends RecyclerView.ViewHolder {

  TextView txtEnglishWord,txtChineseWord,txtPronunciation;
  ImageButton btnPlay;
  View mItemView; //declare a global view variable

  public MyViewHolder(@NonNull View itemView) {
      super(itemView);
      mItemView = itemView; //assign itemView to the above declared global field
      txtEnglishWord=itemView.findViewById(R.id.txtEnglishWord);
      txtChineseWord=itemView.findViewById(R.id.txtChineseWord);
      txtPronunciation=itemView.findViewById(R.id.txtPronunciation);
      btnPlay=itemView.findViewById(R.id.btnPlay);
  }
}

Then in your onBindViewHolder get context from itemView然后在你的 onBindViewHolder 从 itemView 获取上下文

@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, final int position) {
Context mContext = holder.itemView.getContext(); //access the declared field through the holder instance here
// your method here...
}

EDIT: I'd also suggest to check your publishResults method.编辑:我还建议检查您的 publishResults 方法。 To see if the problem is in notifydatasetchanged() try to re-initialize the mChineseLanguages list in the method.要查看问题是否出在 notifydatasetchanged() 中,请尝试在方法中重新初始化 mChineseLanguages 列表。 Also, in the constructor of adapter initialize the mChineseLanguages the same way as mChineseLanguagesAll.此外,在适配器的构造函数中初始化 mChineseLanguages 的方式与 mChineseLanguagesAll 相同。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM