У меня проблемы с применением SearchView с RecyclerView - PullRequest
0 голосов
/ 23 октября 2019

Я пытаюсь реализовать SearchView из библиотеки поддержки. Я хочу, чтобы пользователь использовал SearchView для фильтрации списка слов в RecyclerView.

До сих пор я следовал нескольким учебникам и добавил SearchView в ActionBar, но когда приложение запускает всеработает нормально, но когда я нажимаю на значок поиска. Приложение отображает следующую ошибку в Logcat на секунду, автоматически перезагружается и ошибка исчезает. Но функция поиска не работает

Ошибка, которую я получил Изображение ошибки

Это моя поисковая активность:

введите здесь код


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 голосов
/ 25 октября 2019

Скорее всего, утечка произошла из-за того, что ваш адаптер все еще жив, даже если активность мертва, и он переносит контекст действия, вызывающий утечку памяти. Не обязательно передавать контекст через действие, вы можете получить его из класса. Здесь вместо объявления глобальной переменной 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...
}

EDITЯ бы также предложил проверить ваш метод publishResults. Чтобы убедиться, что проблема в notifydatasetchanged (), попробуйте повторно инициализировать список mChineseLanguages ​​в методе. Кроме того, в конструкторе адаптера инициализируйте mChineseLanguages ​​так же, как и mChineseLanguagesAll.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...