【问题标题】:I am having trouble applying SearchView with RecyclerView我在使用 RecyclerView 应用 SearchView 时遇到问题
【发布时间】:2020-02-19 19:46:47
【问题描述】:

我正在尝试从支持库中实现 SearchView。我希望用户使用 SearchView 过滤 RecyclerView 中的单词列表。

到目前为止,我已经学习了一些教程,并将 SearchView 添加到 ActionBar,但是当应用程序启动时一切正常,但是当我单击搜索图标时。该应用程序在 Logcat 中显示以下错误一秒钟并自动重新启动应用程序并且错误消失。但是搜索功能不起作用

我收到的错误 Error Image

这是我的 SearchActivity:

在此处输入代码


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;
    }
}

这是我的 RecyclerView 适配器类

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);
    }
}

}

如果我做错了什么请纠正我

【问题讨论】:

  • 您看到的错误是内存泄漏。这通常发生在上下文变量没有被垃圾回收时。我在您的适配器类中看不到任何使用 mContext 变量。尝试删除它,看看它是否有效。在您的活动类中还有一个错字,其中适配器被写为 adpater,尽管它必须在这篇文章中,否则它只是编译错误,但请检查。
  • 非常感谢您的回复,但我正在使用 mContext 变量来实例化适配器类中的 MediaPlayer 对象。
  • 查看我的回答,了解如何在本地使用上下文。另外,哪一行是 RecyclerViewAdapter:java:105?
  • mChineseLanguages.clear(); 是 RecyclerViewAdapter:java:105

标签: java android performance android-studio android-recyclerview


【解决方案1】:

您的泄漏很可能发生,因为您的适配器即使在活动死亡后仍然存在,并且它携带活动的上下文导致内存泄漏。不需要通过活动传递上下文,您可以从类中获取它。这里不是在适配器类中声明全局 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);
  }
}

然后在你的 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...
}

编辑:我还建议检查您的 publishResults 方法。要查看问题是否出在 notifydatasetchanged() 中,请尝试在方法中重新初始化 mChineseLanguages 列表。此外,在适配器的构造函数中初始化 mChineseLanguages 的方式与 mChineseLanguagesAll 相同。

【讨论】:

  • 我从适配器类中删除了 mContext 但问题仍然存在。
猜你喜欢
  • 1970-01-01
  • 2020-12-23
  • 2021-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多