The Create, Read, Write, Update and Delete function works but when I try to add the searchview that filters recyclerView, my app closes. I know there must be something missing like in dependencies, also checked the manifest, but for sure the code to execute the search filter is the problem (comment block here are the code I tried to execute search filter in the VIewlist activity)
**The inputs are saved using sqlite, thanks guys
heres the logcat
heres the logcat2
line189
line202
heres the code
The main activity just directs the user in/ Onclick listener to add record activity and view list activity using buttons*/
////////////////////////////////////////////PersonDbHelper/////////////////////////////////////////////////
package info.codestart.glinogaprdrecrds.Utils;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.widget.Toast;
import java.util.LinkedList;
import java.util.List;
import info.codestart.glinogaprdrecrds.model.Person;
public class PersonDBHelper extends SQLiteOpenHelper {
public static final String DATABASE_NAME = "people.db";
private static final int DATABASE_VERSION = 3 ;
public static final String TABLE_NAME = "People";
public static final String COLUMN_ID = "_id";
public static final String COLUMN_PERSON_NAME = "name";
public static final String COLUMN_PERSON_AGE = "age";
public static final String COLUMN_PERSON_DATE = "date";
public static final String COLUMN_PERSON_ADDRESS = "address";
public static final String COLUMN_PERSON_NUMBER = "number";
public static final String COLUMN_PERSON_LEFT = "lft";
public static final String COLUMN_PERSON_RIGHT = "rght";
public static final String COLUMN_PERSON_PAYMENT = "payment";
public PersonDBHelper(Context context) {
super(context, DATABASE_NAME , null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(" CREATE TABLE " + TABLE_NAME + " (" +
COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
COLUMN_PERSON_NAME + " TEXT NOT NULL, " +
COLUMN_PERSON_AGE + " NUMBER NOT NULL, " + COLUMN_PERSON_DATE + " TEXT NOT NULL, " +
COLUMN_PERSON_ADDRESS + " TEXT NOT NULL, " + COLUMN_PERSON_NUMBER + " NUMBER NOT NULL, " +
COLUMN_PERSON_LEFT + " TEXT NOT NULL, " + COLUMN_PERSON_RIGHT + " TEXT NOT NULL, " +
COLUMN_PERSON_PAYMENT + " TEXT NOT NULL);"
);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// you can implement here migration process
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
this.onCreate(db);
}
/**create record**/
public void saveNewPerson(Person person) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(COLUMN_PERSON_NAME, person.getName());
values.put(COLUMN_PERSON_AGE, person.getAge());
values.put(COLUMN_PERSON_DATE, person.getDate());
values.put(COLUMN_PERSON_ADDRESS, person.getAddress());
values.put(COLUMN_PERSON_NUMBER, person.getContactnumber());
values.put(COLUMN_PERSON_LEFT, person.getLefteyegrade());
values.put(COLUMN_PERSON_RIGHT, person.getRighteyegrade());
values.put(COLUMN_PERSON_PAYMENT, person.getPayment());
// insert
db.insert(TABLE_NAME,null, values);
db.close();
}
/**Query records, give options to filter results**/
public List<Person> peopleList(String filter) {
String query;
if(filter.equals("")){
//regular query
query = "SELECT * FROM " + TABLE_NAME;
}else{
//filter results by filter option provided
query = "SELECT * FROM " + TABLE_NAME + " ORDER BY "+ filter;
}
List<Person> personLinkedList = new LinkedList<>();
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(query, null);
Person person;
if (cursor.moveToFirst()) {
do {
person = new Person();
person.setId(cursor.getLong(cursor.getColumnIndex(COLUMN_ID)));
person.setName(cursor.getString(cursor.getColumnIndex(COLUMN_PERSON_NAME)));
person.setAge(cursor.getString(cursor.getColumnIndex(COLUMN_PERSON_AGE)));
person.setDate(cursor.getString(cursor.getColumnIndex(COLUMN_PERSON_DATE)));
personLinkedList.add(person);
} while (cursor.moveToNext());
}
return personLinkedList;
}
/**Query only 1 record**/
public Person getPerson(long id){
SQLiteDatabase db = this.getWritableDatabase();
String query = "SELECT * FROM " + TABLE_NAME + " WHERE _id="+ id;
Cursor cursor = db.rawQuery(query, null);
Person receivedPerson = new Person();
if(cursor.getCount() > 0) {
cursor.moveToFirst();
receivedPerson.setName(cursor.getString(cursor.getColumnIndex(COLUMN_PERSON_NAME)));
receivedPerson.setAge(cursor.getString(cursor.getColumnIndex(COLUMN_PERSON_AGE)));
receivedPerson.setDate(cursor.getString(cursor.getColumnIndex(COLUMN_PERSON_DATE)));
receivedPerson.setAddress(cursor.getString(cursor.getColumnIndex(COLUMN_PERSON_ADDRESS)));
receivedPerson.setContactnumber(cursor.getString(cursor.getColumnIndex(COLUMN_PERSON_NUMBER)));
receivedPerson.setLefteyegrade(cursor.getString(cursor.getColumnIndex(COLUMN_PERSON_LEFT)));
receivedPerson.setRighteyegrade(cursor.getString(cursor.getColumnIndex(COLUMN_PERSON_RIGHT)));
receivedPerson.setPayment(cursor.getString(cursor.getColumnIndex(COLUMN_PERSON_PAYMENT)));
}
return receivedPerson;
}
/**delete record**/
public void deletePersonRecord(long id, Context context) {
SQLiteDatabase db = this.getWritableDatabase();
db.execSQL("DELETE FROM "+TABLE_NAME+" WHERE _id='"+id+"'");
Toast.makeText(context, "Deleted successfully.", Toast.LENGTH_SHORT).show();
}
/**update record**/
public void updatePersonRecord(long personId, Context context, Person updatedperson) {
SQLiteDatabase db = this.getWritableDatabase();
//you can use the constants above instead of typing the column names
db.execSQL("UPDATE "+TABLE_NAME+" SET name ='"+ updatedperson.getName() + "', age ='" + updatedperson.getAge()+ "', date ='"+ updatedperson.getDate() + "', address ='"+ updatedperson.getAddress()+ "', number ='"+ updatedperson.getContactnumber()+ "', lft ='"+ updatedperson.getLefteyegrade()+ "', rght ='"+ updatedperson.getRighteyegrade()+ "', payment ='"+ updatedperson.getPayment()+ "' WHERE _id='" + personId + "'");
Toast.makeText(context, "Updated successfully.", Toast.LENGTH_SHORT).show();
}
}
////////////////////////////////////////////////Person Adapter////////////////////////////////////////////////
package info.glinogaprdrecrds.recrdapp.Utils;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import info.codestart.glinogaprdrecrds.R;
import info.codestart.glinogaprdrecrds.UpdateRecordActivity;
import info.codestart.glinogaprdrecrds.Utils.PersonDBHelper;
import info.codestart.glinogaprdrecrds.model.Person;
public class PersonAdapter extends RecyclerView.Adapter<PersonAdapter.ViewHolder> implements Filterable {
private List<Person> mPeopleList;
private List<Person> exampleListFull;
private Context mContext;
private RecyclerView mRecyclerV;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public class ViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public TextView personNameTxtV;
public TextView personAgeTxtV;
public TextView personDateTxtV;
public View layout;
public ViewHolder(View v) {
super(v);
layout = v;
personNameTxtV = (TextView) v.findViewById(R.id.name);
personAgeTxtV = (TextView) v.findViewById(R.id.age);
personDateTxtV = (TextView) v.findViewById(R.id.date);
}
}
public PersonAdapter(List<Person> mPeopleList){
this.mPeopleList = mPeopleList;
exampleListFull = new ArrayList<>(mPeopleList);
}
public void add(int position, Person person) {
mPeopleList.add(position, person);
notifyItemInserted(position);
}
public void remove(int position) {
mPeopleList.remove(position);
notifyItemRemoved(position);
}
// Provide a suitable constructor (depends on the kind of dataset)
public PersonAdapter(List<Person> myDataset, Context context, RecyclerView recyclerView) {
mPeopleList = myDataset;
mContext = context;
mRecyclerV = recyclerView;
}
// Create new views (invoked by the layout manager)
@Override
public PersonAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
LayoutInflater inflater = LayoutInflater.from(
parent.getContext());
View v =
inflater.inflate(R.layout.single_row, parent, false);
// set the view's size, margins, paddings and layout parameters
ViewHolder vh = new ViewHolder(v);
return vh;
}
// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
final Person person = mPeopleList.get(position);
holder.personNameTxtV.setText("Name: " + person.getName());
holder.personAgeTxtV.setText("Age: " + person.getAge());
holder.personDateTxtV.setText("Date: " + person.getDate());
//listen to single view layout click
holder.layout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
builder.setTitle("Choose option");
builder.setMessage("Update or delete user?");
builder.setPositiveButton("Update", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//go to update activity
goToUpdateActivity(person.getId());
}
});
builder.setNeutralButton("Delete", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
PersonDBHelper dbHelper = new PersonDBHelper(mContext);
dbHelper.deletePersonRecord(person.getId(), mContext);
mPeopleList.remove(position);
mRecyclerV.removeViewAt(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, mPeopleList.size());
notifyDataSetChanged();
}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
builder.create().show();
}
});
}
private void goToUpdateActivity(long personId){
Intent goToUpdate = new Intent(mContext, UpdateRecordActivity.class);
goToUpdate.putExtra("USER_ID", personId);
mContext.startActivity(goToUpdate);
}
// Return the size of your dataset (invoked by the layout manager)
@Override
public int getItemCount() {
return mPeopleList.size();
}
@Override
public Filter getFilter(){
return exampleFilter;
}
private Filter exampleFilter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence charSequence) {
List<Person> filteredList = new ArrayList<>();
if(charSequence == null || charSequence.length()==0){
filteredList.addAll(exampleListFull);
}else{
String filterPatern = charSequence.toString().toLowerCase().trim();
for (Person item : exampleListFull){
if(item.getName().toLowerCase().contains(filterPatern)){
filteredList.add(item);
}
}
}
FilterResults results = new FilterResults();
results.values = filteredList;
return results;
}
@Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
mPeopleList.clear();
mPeopleList.addAll((List)filterResults.values);
notifyDataSetChanged();
}
};
}
//////////////////////////////////////////////ViewList////////////////////////////////////////////////
package info.codestart.glinogaprdrecrds;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.widget.SearchView;
import java.util.List;
import info.codestart.glinogaprdrecrds.Utils.PersonDBHelper;
import info.codestart.glinogaprdrecrds.model.Person;
import info.glinogaprdrecrds.recrdapp.Utils.PersonAdapter;
public class viewList extends AppCompatActivity {
private RecyclerView mRecyclerView;
private RecyclerView.LayoutManager mLayoutManager;
private PersonDBHelper dbHelper;
private PersonAdapter adapter;
private String filter = "";
private List<Person> exampleList;
private SearchView searchView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_list);
//initialize the variables
mRecyclerView = (RecyclerView)findViewById(R.id.recyclerView);
mRecyclerView.setHasFixedSize(true);
// use a linear layout manager
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
populaterecyclerView(filter);
}
private void populaterecyclerView(String filter){
dbHelper = new PersonDBHelper(this);
adapter = new PersonAdapter(dbHelper.peopleList(filter), this, mRecyclerView);
mRecyclerView.setAdapter(adapter);
}
@Override
protected void onResume() {
super.onResume();
adapter.notifyDataSetChanged();
}
/*
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.example_menu, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) searchItem.getActionView();
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
adapter.getFilter().filter(newText);
return false;
}
});
return true;
}
*/
}
///////////////////////////////////////////////UpdateRecordActivity//////////////////////////////////////
package info.codestart.glinogaprdrecrds;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import info.codestart.glinogaprdrecrds.Utils.PersonDBHelper;
import info.codestart.glinogaprdrecrds.model.Person;
public class UpdateRecordActivity extends AppCompatActivity {
private EditText mNameEditText;
private EditText mAgeEditText;
private EditText mAddressEditText;
private EditText mDateEditText;
private EditText mContactNumberText;
private EditText mLeftEyeGradeEditText;
private EditText mRightEyeGradeEditText;
private EditText mPaymentEditText;
private Button UpdateUser;
private PersonDBHelper dbHelper;
private long receivedPersonId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_update_record);
mNameEditText = findViewById(R.id.userNameUpdate);
mAgeEditText = findViewById(R.id.userAgeUpdate);
mAddressEditText = findViewById(R.id.userAddressUpdate);
mDateEditText = findViewById(R.id.userDateUpdate);
mContactNumberText = findViewById(R.id.userContactNumberUpdate);
mLeftEyeGradeEditText = findViewById(R.id.userLeftEyeGradeUpdate);
mRightEyeGradeEditText = findViewById(R.id.userRightEyeGradeUpdate);
mPaymentEditText = findViewById(R.id.userPaymentUpdate);
UpdateUser = findViewById(R.id.UpdateUser);
dbHelper = new PersonDBHelper(this);
try {
//get intent to get person id
receivedPersonId = getIntent().getLongExtra("USER_ID", 1);
} catch (Exception e) {
e.printStackTrace();
}
/***populate user data before update***/
Person queriedPerson = dbHelper.getPerson(receivedPersonId);
//set field to this user data
mNameEditText.setText(queriedPerson.getName());
mAgeEditText.setText(queriedPerson.getAge());
mAddressEditText.setText(queriedPerson.getAddress());
mDateEditText.setText(queriedPerson.getDate());
mContactNumberText.setText(queriedPerson.getContactnumber());
mLeftEyeGradeEditText.setText(queriedPerson.getLefteyegrade());
mRightEyeGradeEditText.setText(queriedPerson.getRighteyegrade());
mPaymentEditText.setText(queriedPerson.getPayment());
//listen to add button click to update
UpdateUser.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//call the save person method
updateUser();
}
});
}
private void updateUser(){
String name = mNameEditText.getText().toString().trim();
String age = mAgeEditText.getText().toString().trim();
String address = mAddressEditText.getText().toString().trim();
String date = mDateEditText.getText().toString().trim();
String contactnumber = mContactNumberText.getText().toString().trim();
String lefteyegrade = mLeftEyeGradeEditText.getText().toString().trim();
String righteyegrade = mRightEyeGradeEditText.getText().toString().trim();
String payment = mPaymentEditText.getText().toString().trim();
if(name.isEmpty() && age.isEmpty()&& address.isEmpty()&& date.isEmpty()&& contactnumber.isEmpty()&& lefteyegrade.isEmpty()&& righteyegrade.isEmpty()&& payment.isEmpty() ){
Toast.makeText(this,"You must fill up all fields", Toast.LENGTH_SHORT).show();
}
Person updatedPersonRecord = new Person(name, age, address, date, contactnumber, lefteyegrade, righteyegrade, payment);
dbHelper.updatePersonRecord(receivedPersonId, this, updatedPersonRecord);
gotolist();
}
private void gotolist(){
startActivity(new Intent(this, info.codestart.glinogaprdrecrds.MainActivity.class));
}
}
//I modified this code to add more user inputs and some layout from the original template that I followed in youtube tutorials