使用SQLite的搜索结果更新RecyclerView

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用SQLite的搜索结果更新RecyclerView相关的知识,希望对你有一定的参考价值。

我在用Fragment中的SearchView结果更新RecyclerView时遇到问题。在我逐步浏览了“ performFiltering”处的代码并且“ publishResults”具有正确的列表后,进行实际搜索似乎正常。但是我似乎无法弄清楚如何更新RecyclerView。我已经盯着这段代码三天了,可能是我忽略的一个简单解决方案。

MyMoviesFragment

public class MyMoviesFragment extends Fragment {

private SearchView searchView = null;
private SearchView.OnQueryTextListener queryTextListener;

private static final boolean DEFAULT_SORT_ORDER_IS_ASC = false;
private static final int MY_MOVIES_LOADER_ID = 173201;

private ArrayList<Movie> _movies = new ArrayList();
private ArrayList<Movie> _moviesRaw = new ArrayList();
private Button _btnMoviesNotFound;
private DBHandler _repository;
private MyMoviesAdapter _myMoviesAdapter;
private ProgressBar _progressBar;
private RecyclerView _rvMovies;
private SharedPreferences _preferences;
private View _view;

public MyMoviesFragment() {
    // Required empty public constructor
}

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    //        inflater.inflate(R.menu.main, menu);
    MenuItem searchItem = menu.findItem(R.id.action_search);
    SearchManager searchManager = (SearchManager) getActivity().getSystemService(Context.SEARCH_SERVICE);

    if (searchItem != null) {
        searchView = (SearchView) searchItem.getActionView();
    }
    if (searchView != null) {
        searchView.setSearchableInfo(searchManager.getSearchableInfo(getActivity().getComponentName()));

        queryTextListener = new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextChange(String newText) {
                Log.i("onQueryTextChange", newText);
                _myMoviesAdapter.getFilter().filter(newText);
                return true;
            }

            @Override
            public boolean onQueryTextSubmit(String query) {
                Log.i("onQueryTextSubmit", query);

                return true;
            }
        };
        searchView.setOnQueryTextListener(queryTextListener);
    }
    super.onCreateOptionsMenu(menu, inflater);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    this._view = inflater.inflate(R.layout.fragment_my_movies, container, DEFAULT_SORT_ORDER_IS_ASC);
    getActivity().setTitle(R.string.movies_fragment_title);
    this._repository = DBHandler.getInstance(getActivity());
    this._progressBar = (ProgressBar) this._view.findViewById(R.id.progressBar2);
    this._progressBar.setVisibility(View.VISIBLE);
    this._rvMovies = (RecyclerView) this._view.findViewById(R.id.rvMovies);
    this._rvMovies.setLayoutManager(new LinearLayoutManager(getActivity()));
    this._myMoviesAdapter = new MyMoviesAdapter(this._movies, this);
    this._rvMovies.setAdapter(this._myMoviesAdapter);
    this._btnMoviesNotFound = (Button) this._view.findViewById(R.id.btnMoviesNotFound);
    if (savedInstanceState == null) {
        loadMyMoviesList();
    }
    return this._view;
}

public void loadMyMoviesList() {

    getLoaderManager().initLoader(MY_MOVIES_LOADER_ID, null, new LoaderManager.LoaderCallbacks<ArrayList<Movie>>() {

        @NonNull
        @Override
        public Loader<ArrayList<Movie>> onCreateLoader(int id, Bundle args) {
            return new MyMoviesLoader(MyMoviesFragment.this.getContext());
        }

        public void onLoadFinished(Loader<ArrayList<Movie>> loader, ArrayList<Movie> movies) {

            if (movies != null) {
                MyMoviesFragment.this._movies.clear();
                Iterator it = movies.iterator();
                while (it.hasNext()) {
                    MyMoviesFragment.this._movies.add((Movie) it.next());
                }
                MyMoviesFragment.this._moviesRaw = new ArrayList(MyMoviesFragment.this._movies);
                MyMoviesFragment.this._myMoviesAdapter.notifyDataSetChanged();
                MyMoviesFragment.this.displayListState();
            }
        }

        public void onLoaderReset(Loader<ArrayList<Movie>> loader) {
        }
    }).forceLoad();
}

public void displayListState() {
    this._progressBar.setVisibility(View.GONE);
    if (this._movies.size() < 1) {
        this._rvMovies.setVisibility(View.GONE);
        this._btnMoviesNotFound.setVisibility(View.VISIBLE);
        return;
    }
    this._btnMoviesNotFound.setVisibility(View.GONE);
    this._rvMovies.setVisibility(View.VISIBLE);
}

}

MyMoviesAdapter

public class MyMoviesAdapter extends RecyclerView.Adapter<MyMoviesAdapter.ViewHolder> implements Filterable {

private Activity _activity;
private ArrayList<Movie> _movieListFull;
private ArrayList<Movie> _movieListFiltered;
private DBHandler _repository = DBHandler.getInstance(this._activity);
private Fragment _fragment;

public MyMoviesAdapter(ArrayList<Movie> movies, Fragment fragment) {
    this._activity = fragment.getActivity();
    this._fragment = fragment;
    this._movieListFull = movies;
}

protected class ViewHolder extends RecyclerView.ViewHolder {

    private CardView cardMovie;
    private TextView lblMovieTitle;

    public ViewHolder(View itemView) {
        super(itemView);

        this.cardMovie = (CardView) itemView.findViewById(R.id.cardMovie);
        this.lblMovieTitle = (TextView) itemView.findViewById(R.id.lblMovieTitle);
    }
}

// Create new views (invoked by the layout manager)
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_movie, parent, false));
}

// Replace the contents of a view (invoked by the layout manager)
// Binds the data to the Views in each row
@Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
    // Get the data model based on position
    Movie movie = _movieListFull.get(position);

    viewHolder.lblMovieTitle.setText(String.valueOf(movie.getTitle()));
}

// Return the size of your dataset (invoked by the layout manager)
@Override
public int getItemCount() {
    return this._movieListFull.size();
}

@Override
public Filter getFilter() {

    return new Filter() {
        @Override
        protected FilterResults performFiltering(CharSequence charSequence) {

            String charString = charSequence.toString();

            if (charString.isEmpty()) {
                _movieListFiltered = _movieListFull;
            } else {
                ArrayList<Movie> filteredList = new ArrayList<>();

                for (Movie movie : _movieListFull) {
                    if (movie.getTitle().toLowerCase().contains(charString)) {
                        filteredList.add(movie);
                    }
                }
                _movieListFiltered = filteredList;
            }

            FilterResults filterResults = new FilterResults();
            filterResults.values = _movieListFiltered;
            filterResults.count = _movieListFiltered.size();
            return filterResults;
        }

        @Override
        protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
            _movieListFiltered = (ArrayList<Movie>) filterResults.values;
            notifyDataSetChanged();
        }
    };
}

}

答案
_ movieListFull已设置完整数据,则应使用

_ movieListFiltered进行显示。因此getItemCount()onBindViewHolder()应该引用_ movieListFiltered

尝试以下更改:public MyMoviesAdapter(ArrayList<Movie> movies, Fragment fragment) { this._activity = fragment.getActivity(); this._fragment = fragment; this._movieListFiltered = movies; _movieListFull = new ArrayList<>(); _movieListFull.addAll(movies); } // Replace the contents of a view (invoked by the layout manager) // Binds the data to the Views in each row @Override public void onBindViewHolder(ViewHolder viewHolder, int position) { // Get the data model based on position Movie movie = _movieListFiltered.get(position); viewHolder.lblMovieTitle.setText(String.valueOf(movie.getTitle())); } // Return the size of your dataset (invoked by the layout manager) @Override public int getItemCount() { return this._movieListFiltered.size(); } @Override protected FilterResults performFiltering(CharSequence charSequence) { String charString = charSequence.toString(); if (charString.isEmpty()) { //_movieListFiltered = _movieListFull; _movieListFiltered.addAll(_movieListFull); } else { ArrayList<Movie> filteredList = new ArrayList<>(); for (Movie movie : _movieListFull) { if (movie.getTitle().toLowerCase().contains(charString)) { filteredList.add(movie); } } _movieListFiltered = filteredList; } FilterResults filterResults = new FilterResults(); filterResults.values = _movieListFiltered; filterResults.count = _movieListFiltered.size(); return filterResults; }

希望有帮助!

以上是关于使用SQLite的搜索结果更新RecyclerView的主要内容,如果未能解决你的问题,请参考以下文章

如何使用搜索和替换查询更新 SQLite 数据库?

Apollo GraphQL 突变结果不使用 PostgreSQL 更新,但适用于 SQLite

Xamarin.Forms Sqlite(有时)在更新后获取错误结果

Sqlite的多表连接更新

SQLite 中的更新数据不更新

使用 SimpleCursorAdapter 基于 sqlite 查询更新列表视图