Search code examples
androidsqliteandroid-recyclerviewsearchview

SearchView doesn't work with RecyclerView & SQLite


I have a Fragment with a RecyclerView. users input data and they will store in a SQLite DataBase. i am trying to Search in the items of this RecyclerView but it does not work,

here is my Fragment :

public class FragmentOne extends Fragment {

private RecyclerView mDetailRecyclerView;
private DetailAdapter mAdapter;
private boolean mNumberVisible;
private SearchView sv;
private ArrayList<Detail> mDetails=new ArrayList<>();

private View view;

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

@Override
public View onCreateView(LayoutInflater inflater,
                         ViewGroup container,
                         Bundle savedInstanceState) {
    view = inflater.inflate(R.layout.fragment_one_layout,
            container, false);

    mDetailRecyclerView = (RecyclerView) view.findViewById(R.id.detail_recycler_view);

    LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
    layoutManager.setReverseLayout(true); //This will reverse the data order but not scroll the RecyclerView to the last item
    layoutManager.setStackFromEnd(true); //For keeping data order same and simply scrolling the RecyclerView to the last item
    mDetailRecyclerView.setLayoutManager(layoutManager);

    if (savedInstanceState != null) {
        mNumberVisible =
                savedInstanceState.getBoolean(SAVED_NUMBER_VISIBLE);
    }

    sv = (SearchView) view.findViewById(R.id.sv);
    mAdapter = new DetailAdapter(mDetails);

    sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit (String query) {
            return false;
        }

        @Override
        public boolean onQueryTextChange(String query) {
            getDetailsSearch(query);
            return false;
        }
    });

    initViews();
    updateUI();
    return view;


}

@Override
public void onResume() {
    super.onResume();
    updateUI();
}



   @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putBoolean(SAVED_NUMBER_VISIBLE, mNumberVisible);
    }

..
..
private class DetailHolder extends RecyclerView.ViewHolder
        implements View.OnClickListener, View.OnLongClickListener {
    private TextView mTitleTextView;
    //        private TextView mDateTextView;
    private Detail mDetail;
    private RatingBar mRatingBar;

    public DetailHolder(LayoutInflater inflater, ViewGroup parent) {
        super(inflater.inflate(R.layout.list_item_detail,
                parent, false));

        itemView.setOnClickListener(this);
        itemView.setOnLongClickListener(this);
        mTitleTextView = (TextView) itemView.findViewById(R.id.detail_title);
        mRatingBar = (RatingBar) itemView.findViewById(R.id.ratingBar);
    }

    public void bind(Detail detail) {
        mDetail = detail;
        mTitleTextView.setText(mDetail.getTitle());
        mRatingBar.setRating(mDetail.getRate());
    }

    @Override
    public void onClick(View view) {
        Intent intent = DetailPagerActivity.newIntent(getActivity(),
                mDetail.getId());
        startActivity(intent);
    }
}


private class DetailAdapter extends RecyclerView.Adapter<DetailHolder> {
    private List<Detail> mDetails;
    private Detail mDetail;

    public DetailAdapter(List<Detail> details) {
        mDetails = details;
    }

    @Override
    public DetailHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
        return new DetailHolder(layoutInflater, parent);
    }

    @Override
    public void onBindViewHolder(DetailHolder holder, int position) {
        Detail detail = mDetails.get(position);
        holder.bind(detail);
    }

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

    public void setDetails(final List<Detail> details) {
        mDetails = details;
    }

    ..
    ..

}

public void initViews(){
    mDetailRecyclerView.setAdapter(mAdapter);
    initSwipe();
}

..
..

private void getDetailsSearch (String searchTerm) {
    mDetails.clear();

    DBAdapter db = new DBAdapter(getActivity());
    db.openDB();
    Detail p = null;
    Cursor c = db.retrieve(searchTerm);

    while (c.moveToNext()) {
        String title = c.getString(2);

        p = new Detail();
        p.setTitle(title);

        mDetails.add(p);
    }

    db.closeDB();
    mDetailRecyclerView.setAdapter(mAdapter);
}
}

and this is my Database Adapter:

public class DBAdapter {
    Context c;
    SQLiteDatabase db;
    DetailBaseHelper helper;

    public DBAdapter (Context c) {
        this.c = c;
        helper = new DetailBaseHelper(c);
    }

    public void openDB() {
        try {
            db = helper.getWritableDatabase();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public void closeDB() {
        try {
            helper.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public Cursor retrieve (String searchTerm) {
        String[] columns = {
            "_id",
            "uuid",
            "title",
            "des",
            "date",
            "rate"
        Cursor c = null;

        if (searchTerm != null && searchTerm.length()>0) {
            String sql ="SELECT * FROM " +DetailDbSchema.DetailTable.NAME+
                    " WHERE "+DetailDbSchema.DetailTable.Cols.TITLE+
                    " LIKE '%"+searchTerm+"%'";
            c = db.rawQuery(sql, null);
            return c;
        }

        c = db.query(DetailDbSchema.DetailTable.NAME, columns,
                null, null, null, null, null);
        return c;
    }
}

and here is DataBase Helper:

public class DetailBaseHelper extends SQLiteOpenHelper{
    private static final int VERSION = 1;
    private static final String DATABASE_NAME = "detailBase.db";

    public DetailBaseHelper (Context context) {
        super(context, DATABASE_NAME, null, VERSION);
    }

    @Override
    public void onCreate (SQLiteDatabase db) {
        db.execSQL("create table " + DetailTable.NAME +
                "(" +
                " _id integer primary key autoincrement," +
                DetailTable.Cols.UUID + ", " +
                DetailTable.Cols.TITLE + ", " +
                DetailTable.Cols.DES + ", " +
                DetailTable.Cols.DATE + ", " +
                DetailTable.Cols.RATE +
                ")"
        );
    }

    @Override
    public void onUpgrade (SQLiteDatabase db,
                           int oldVersion, int newVersion) {
    }
}

here is the tutorial that i used for this, I'll be appreciate if u have any idea for helping me.


Solution

  • I think that the main problem is here you're changing the adapter, but the new adapter was never modified by the data of the results, and also you have to notify your recycler that the data set changed. so

    private void getDetailsSearch (String searchTerm) {
    mDetails.clear();
    /// the loop wiith the cursor
    
    /// change the dataset
    mAdapter = new DetailAdapter(mDetails);
    
    mDetailRecyclerView.setAdapter(mAdapter);
    
    /// tell the recycler there is a different data to display
    mDetailRecyclerView.notifyDataSetChanged();
    
    }