我在将RecyclerView应用于SearchView时遇到问题

时间:2019-10-23 14:17:33

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

我正在尝试从支持库中实现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);
    }
}

}

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

1 个答案:

答案 0 :(得分:0)

您的泄漏很可能发生,因为即使活动终止后适配器仍然处于活动状态,并且适配器承载活动的上下文导致内存泄漏。不需要通过活动传递上下文,您可以从类中获取它。在这里,您无需在适配器类中声明全局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列表。同样,在适配器的构造函数中,与mChineseLanguagesAll一样,初始化mChineseLanguages。