ANSWER
#Override
public void categoryLoadComplete(Cursor cursor) {
data = cursor;
categoryAdapter.swapCursor(cursor);
categoryAdapter.notifyDataSetChanged();
}
#Override
public void transactionLoadComplete(Cursor cursor) {
data = cursor;
categoryAdapter.swapCursor(cursor);
categoryAdapter.notifyDataSetChanged();
}
ORIGINAL POST
I've been at this for hours now and I can't seem to figure it out, but I have narrowed the problem down to the fact that my Cursor object is returning null. I can't figure out why and was hoping to enlist the help of more experienced coders on this site.
I borrowed a Database package from this tutorial on SQLite: http://partisanapps.com/2015/08/really-useful-notes-saving-and-loading-with-a-local-database-i/
I added a second table as well as added Add, Load, Delete, and Save classes for the new table.
I can confirm that there is data in the database by exporting the file and viewing it in SQLite Broweser.
I'm attempting to populate a a spinner with data from the database as you can see in AddTransaction.class
Thank you for your time.
AddTransaction.class:
public class AddTransaction extends AppCompatActivity
implements CategoryLoad.categoryLoadComplete,
TransactionLoad.LoadComplete {
Spinner currencySpinner, recurringSpinner;
EditText itemName, itemPrice, itemNote;
Time today = new Time(Time.getCurrentTimezone());
Snackbar snackbar;
private Cursor data = null;
LinearLayout transactionLayout;
SimpleCursorAdapter categoryAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_transaction);
transactionLayout = (LinearLayout) findViewById(R.id.transactionLayout);
itemName = (EditText) findViewById(R.id.itemName);
itemPrice = (EditText) findViewById(R.id.itemPrice);
itemNote = (EditText) findViewById(R.id.note);
Toolbar toolbar = (Toolbar) findViewById(R.id.app_bar);
setSupportActionBar(toolbar);
getSupportActionBar().setTitle("Add a Transaction");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
CategoryLoad categoryLoad = new CategoryLoad(this);
categoryLoad.execute();
categoryAdapter = new SimpleCursorAdapter(getBaseContext(),
android.R.layout.simple_spinner_item,
data,
new String[] {DatabaseHelper.CATEGORY_NAME},
new int[] {android.R.id.text1},
0);
final Spinner categorySpinner = (Spinner) findViewById(R.id.categorySpinner);
categoryAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
categoryAdapter.swapCursor(data);
categoryAdapter.notifyDataSetChanged();
categorySpinner.setAdapter(categoryAdapter);
currencySpinner = (Spinner) findViewById(R.id.currencySpinner);
ArrayAdapter<CharSequence> currencyAdapter = ArrayAdapter.createFromResource(this,
R.array.currency, android.R.layout.simple_spinner_item);
currencyAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
currencySpinner.setAdapter(currencyAdapter);
recurringSpinner = (Spinner) findViewById(R.id.recurringSpinner);
ArrayAdapter<CharSequence> recurringAdapter = ArrayAdapter.createFromResource(this,
R.array.recurring, android.R.layout.simple_spinner_item);
recurringAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
recurringSpinner.setAdapter(recurringAdapter);
if (data == null) {
snackbar.make(transactionLayout, "Category data failed to load", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_add_category, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
itemPrice = (EditText) findViewById(R.id.itemPrice);
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
if (id == R.id.delete) {
Toast.makeText(getBaseContext(), "Transaction data lost!", Toast.LENGTH_LONG).show();
NavUtils.navigateUpFromSameTask(this);
return true;
}
if (id == R.id.save) {
if (TextUtils.isEmpty(itemPrice.getText().toString())) {
snackbar.make(transactionLayout, "Please input a price.", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
} else {
today.setToNow();
TransactionAdd transactionAdd = new TransactionAdd(this);
transactionAdd.execute(
itemName.getText().toString(),
itemPrice.getText().toString(),
// categorySpinner.getSelectedItem().toString(),
null,
currencySpinner.getSelectedItem().toString(),
recurringSpinner.getSelectedItem().toString(),
itemNote.getText().toString(),
today.format("%Y-%m-%d %H:%M:%S")
);
Toast.makeText(getBaseContext(), "Transaction added!", Toast.LENGTH_LONG).show();
NavUtils.navigateUpFromSameTask(this);
}
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void categoryLoadComplete(Cursor cursor) {
data = cursor;
}
#Override
public void transactionLoadComplete(Cursor cursor) {
}
}
CategoryLoad:
public class CategoryLoad extends AsyncTask<Void, Void, Cursor> {
private static final String TAG = "LoadTask";
private categoryLoadComplete loadComplete;
private WeakReference<Context> categoryWeakReference;
private DatabaseHelper db;
public interface categoryLoadComplete {
void categoryLoadComplete(Cursor cursor);
}
public CategoryLoad(Context context) {
categoryWeakReference = new WeakReference<>(context);
db = DatabaseHelper.getInstance(categoryWeakReference.get());
try {
loadComplete = (categoryLoadComplete) categoryWeakReference.get();
} catch (ClassCastException e) {
Log.e(TAG, context.toString() + " must implement LoadComplete");
}
}
#Override
protected Cursor doInBackground(Void... params) {
Cursor result = db.getReadableDatabase().query(
DatabaseHelper.CATEGORIES_TABLE,
null, null, null, null, null, DatabaseHelper.CATEGORY_KEY_ID);
result.getCount();
return result;
}
#Override
protected void onPreExecute() {
}
#Override
protected void onPostExecute(Cursor cursor) {
loadComplete.categoryLoadComplete(cursor);
}
}
TransactionLoad:
public class TransactionLoad extends AsyncTask<Void, Void, Cursor> {
private static final String TAG = "LoadTask";
private LoadComplete loadComplete;
private WeakReference<Context> transactionWeakReference;
private DatabaseHelper tt;
public interface LoadComplete {
void transactionLoadComplete(Cursor cursor);
}
public TransactionLoad(Context context) {
transactionWeakReference = new WeakReference<>(context);
tt = DatabaseHelper.getInstance(transactionWeakReference.get());
try {
loadComplete = (LoadComplete) transactionWeakReference.get();
} catch (ClassCastException e) {
Log.e(TAG, context.toString() + " must implement LoadComplete");
}
}
#Override
protected Cursor doInBackground(Void... params) {
Cursor result = tt.getReadableDatabase().query(
DatabaseHelper.TRANSACTIONS_TABLE,
null, null, null, null, null, DatabaseHelper.TRANSACTION_KEY_ID);
result.getCount();
return result;
}
#Override
protected void onPreExecute() {
}
#Override
protected void onPostExecute(Cursor cursor) {
loadComplete.transactionLoadComplete(cursor);
}
}
DatabaseHelper:
public class DatabaseHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "budgets.db";
private static final int SCHEMA = 1;
public static final String KEY_ID = "_id";
// ~~~~~~~~~~~~~~~~~~~Categories~~~~~~~~~~~~~~~~~~~~~~~~~~~
public static final String CATEGORIES_TABLE = "categories";
// ~~~~~~~~~~~~~~~~~~~~~Columns~~~~~~~~~~~~~~~~~~~~~~~~~~~
public static final String CATEGORY_KEY_ID = "_id_cat";
public static final String CATEGORY_NAME = "cat_name";
public static final String CATEGORY_AMOUNT = "cat_amount";
public static final String CATEGORY_CURRENCY = "cat_currency";
public static final String CATEGORY_FREQUENCY = "cat_frequency";
public static final String CATEGORY_DURATION_VALUE = "cat_duration_value";
public static final String CATEGORY_DURATION_MODIFIER = "cat_duration_modifier";
public static final String CATEGORY_OVERAGE = "cat_overage";
public static final String CATEGORY_SURPLUS = "cat_surplus";
public static final String CATEGORY_DATE = "cat_date";
// ~~~~~~~~~~~~~~~~~~~Transactions~~~~~~~~~~~~~~~~~~~~~~~~~~~
public static final String TRANSACTIONS_TABLE = "transactions";
// ~~~~~~~~~~~~~~~~~~~~~Columns~~~~~~~~~~~~~~~~~~~~~~~~~~~
public static final String TRANSACTION_KEY_ID = "_id_trans";
public static final String TRANSACTION_NAME = "trans_name";
public static final String TRANSACTION_PRICE = "trans_price";
public static final String TRANSACTION_CATEGORY = "trans_category";
public static final String TRANSACTION_CURRENCY = "trans_currency";
public static final String TRANSACTION_RECURRING = "trans_recurring";
public static final String TRANSACTION_NOTES = "trans_notes";
public static final String TRANSACTION_DATE = "trans_date";
private static DatabaseHelper mInstance = null;
public static synchronized DatabaseHelper getInstance(Context context) {
if (mInstance == null) {
mInstance = new DatabaseHelper(context.getApplicationContext());
}
return mInstance;
}
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, SCHEMA);
}
public DatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory,
int version) {
super(context, name, factory, version);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE categories (_id_cat INTEGER PRIMARY KEY AUTOINCREMENT, " +
"cat_name TEXT, cat_amount TEXT, cat_currency TEXT, cat_frequency TEXT," +
"cat_duration_value TEXT, cat_duration_modifier TEXT, cat_overage TEXT, " +
"cat_surplus TEXT, cat_date TEXT);");
db.execSQL("CREATE TABLE transactions (_id_trans INTEGER PRIMARY KEY AUTOINCREMENT, " +
"trans_name TEXT, trans_price TEXT, trans_category TEXT, trans_currency TEXT, " +
"trans_recurring TEXT, trans_notes TEXT, trans_date TEXT, " +
"FOREIGN KEY(trans_category) REFERENCES categories(cat_name));");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
int upgradeTo = oldVersion + 1;
while (upgradeTo <= newVersion) {
switch (upgradeTo) {
case 2:
break;
}
upgradeTo++;
}
}
}
You need to set the cursor on the adapter in your categoryLoadComplete() and transactionLoadComplete() methods, and then call adapter.notifyDataSetChanged().
Your cursor is null because it has not been assigned by the time you pass if off you your adapter. Try not creating your adapter until "categoryLoadComplete".
#Override
public void categoryLoadComplete(Cursor cursor) {
data = cursor;
categoryAdapter = new SimpleCursorAdapter(this,
android.R.layout.simple_spinner_item,
data,
new String[] {DatabaseHelper.CATEGORY_NAME},
new int[] {android.R.id.text1},
0);
categorySpinner.setAdapter(categoryAdapter);
}
Related
I have a problem with recycler, the problem is: I have AsyncTask which query data from my db, and then updating recycler by CursorLoader, but adapter doesn't fill recycler, Logs says that the data from db is successfully reading and then Adapter constructor successfully takes ArrayList with data, but that's all, logs says that adapter's methods doesn't call.
MainActivity :
public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor> {
private SQLiteDatabase db;
private SimpleCursorLoader loader;
private MySimpleAdapter adapter;
private RecyclerView recycler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recycler = (RecyclerView) findViewById(R.id.recycler);
new SimpleTask(SimpleTask.OPEN, null).execute();
}
private class SimpleTask extends AsyncTask<Void, Void, Void> {
public static final int INSERT = 0;
public static final int DELETE = 1;
public static final int OPEN = 2;
private int task;
private String name;
public SimpleTask(int task, String name) {
this.task = task;
this.name = name;
}
#Override
protected Void doInBackground(Void... params) {
switch (task) {
case INSERT :
ContentValues values = new ContentValues();
values.put(SimpleHelper.KEY_NAME, name);
db.insert(SimpleHelper.TABLE_NAME, null, values);
break;
case DELETE :
db.delete(SimpleHelper.TABLE_NAME, SimpleHelper.KEY_NAME + " = ? ", new String[]{name});
break;
case OPEN :
if (db == null) {
try {
db = new SimpleHelper(MainActivity.this).getWritableDatabase();
} catch (SQLiteException e) {
e.printStackTrace();
}
}
break;
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
if (loader == null) {
loader = new SimpleCursorLoader(MainActivity.this, db);
loader.setQueryParams(SimpleHelper.TABLE_NAME, new String[]{SimpleHelper.KEY_NAME},
null, null);
getSupportLoaderManager().initLoader(0, null, MainActivity.this);
}
getSupportLoaderManager().getLoader(0).forceLoad();
}
}
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return loader;
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
Log.i("MyLog", "onLoadFinished cursor size is " + data.getCount());
List<String> items = new ArrayList<>();
data.moveToFirst();
do {
items.add(data.getString(0));
Log.i("MyLog", data.getString(0));
} while (data.moveToNext());
Log.i("MyLog", "onLoadFinished items size is " + items.size());
if (adapter == null) {
adapter = new MySimpleAdapter(items);
recycler.setAdapter(adapter);
} else {
adapter.updateAdapter(items);
}
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
}
private class MySimpleAdapter extends RecyclerView.Adapter<MySimpleAdapter.MyHolder> {
private List<String> items;
public MySimpleAdapter(List<String> items) {
Log.i("MyLog", "Constructor called with items size " + items.size());
this.items = items;
}
public class MyHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView tvText;
public MyHolder(View itemView) {
super(itemView);
tvText = (TextView) itemView.findViewById(android.R.id.text1);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
new SimpleTask(SimpleTask.DELETE, tvText.getText().toString());
}
}
public void updateAdapter(List<String> items) {
this.items = items;
notifyDataSetChanged();
}
#Override
public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Log.i("MyLog", "onCreateViewHolder");
View view = LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_1, null, false);
return new MyHolder(view);
}
#Override
public void onBindViewHolder(MyHolder holder, int position) {
holder.tvText.setText(items.get(position));
Log.i("MyLog", "onBindViewHolder setText : " + items.get(position));
}
#Override
public int getItemCount() {
Log.d("MyLog", "getItemCount called with size : " + items.size());
return items.size();
}
}
SimpleCursorLoader :
public class SimpleCursorLoader extends CursorLoader {
private SQLiteDatabase db;
private String tableName;
private String[] columns;
public SimpleCursorLoader(Context context, SQLiteDatabase db) {
super(context);
this.db = db;
}
public void setQueryParams(String tableName, String[] columns, String selection, String[] selectionArgs) {
this.tableName = tableName;
this.columns = columns;
setSelection(selection);
setSelectionArgs(selectionArgs);
}
#Override
public Cursor loadInBackground() {
Cursor cursor = db.query(tableName, columns, getSelection(), getSelectionArgs(),
null, null, null);
return cursor;
}
DBHelper :
public class SimpleHelper extends SQLiteOpenHelper{
public static final String TABLE_NAME = "users";
public static final String KEY_NAME = "name";
public static final String KEY_ID = "_id";
private static final int DB_VERSION = 1;
private static final String DB_NAME = "SimpleDB";
public SimpleHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table " + TABLE_NAME + "("
+ KEY_ID + " integer primary key autoincrement, "
+ KEY_NAME + " text)");
for (int i = 0; i < 5; i ++) {
ContentValues values = new ContentValues();
values.put(KEY_NAME, "name" + i+1);
db.insert(TABLE_NAME, null, values);
Log.i("MyLog", "inserted");
}
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
activity_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Use this.
recycler.setLayoutManager(new LinearLayoutManager(this));
recycler.setHasFixedSize(true);
recycler.setNestedScrollingEnabled(false);
Whenever I run the code application crashes after instantiating the helper class. I am new at this and can't figure out the error.
My contract class
public final class PetContract {
private PetContract(){}
public static class PetEntry implements BaseColumns{
public static final String TABLE_NAME = "pets";
public static final String _ID = BaseColumns._ID;
public static final String COLUMN_NAME = "name";
public static final String COLUMN_BREED = "breed";
public static final String COLUMN_GENDER = "gender";
public static final String COLUMN_WEIGHT = "weight";
// constants for gender
public static final int GENDER_UNKNOWN = 0;
public static final int GENDER_MALE = 1;
public static final int GENDER_FEMALE = 2;
}
}
My SQLiteHelperClass
public class PetDbHelper extends SQLiteOpenHelper {
public static final int DATABASE_VERSION = 1;
public static final String DATABASE_NAME = "pets.db";
public static final String SQL_CREATE_ENTRIES = "CREATE TABLE " + PetEntry.TABLE_NAME + " ( "
+ PetEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ PetEntry.COLUMN_NAME + " TEXT NOT NULL, "
+ PetEntry.COLUMN_BREED + " TEXT NOT NULL, "
+ PetEntry.COLUMN_GENDER + " INTEGER NOT NULL, "
+ PetEntry.COLUMN_WEIGHT + " FLOAT NOT NULL "
+ ")";
private static final String SQL_DELETE_ENTRIES =
"DROP TABLE IF EXISTS " + PetEntry.TABLE_NAME;
public PetDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(SQL_CREATE_ENTRIES);
onCreate(db);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
Main activity
public class CatalogActivity extends AppCompatActivity {
PetDbHelper mDbHelper = new PetDbHelper(this);
public void insertDummyData(){
SQLiteDatabase db = mDbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
String name = "DOG";
String breed = "dkdsbk";
float weight = (float) 55.5;
values.put(PetEntry.COLUMN_NAME,name);
values.put(PetEntry.COLUMN_BREED, breed);
values.put(PetEntry.COLUMN_GENDER,PetEntry.GENDER_MALE);
values.put(PetEntry.COLUMN_WEIGHT,weight);
long newRowId = db.insert(PetEntry.TABLE_NAME,null,values);
}
public Cursor displayRowCount(){
SQLiteDatabase db = mDbHelper.getReadableDatabase();
String[] projection = {PetEntry._ID};
String selection = PetEntry.TABLE_NAME;
return db.query(PetEntry.TABLE_NAME,projection,null,null,null,null,null);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_catalog);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(CatalogActivity.this,EditorialActivity.class );
startActivity(intent);
}
});
Cursor c = displayRowCount();
TextView view = (TextView) findViewById(R.id.text);
view.setText("The row count is" + c.getCount());
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_catalog, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
switch (id){
case R.id.delete_all_the_pets:
break;
case R.id.insert_dummy_data:
insertDummyData();
break;
}
return super.onOptionsItemSelected(item);
}
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(SQL_CREATE_ENTRIES);
onCreate(db);
}
this is A recursive function!!
don't call onCreate Inside onCreate
I have implemented a recyclerView and a SQLite database to save/retrieve data for the recylerview, but the data I get on the recyclerView is not the data that should show. The recyclerView worked as it should without the SQLite db.
When the plus sign is clicked, a dialog will popup with editext fields, where the user can type the information:
Here is the DialogFragment class where the user shall write their information:
public class DialogAdd extends DialogFragment {
private Button okButton;
private EditText name, quantity, location, normalPrice, offerPrice;
private List<ShopListItem> shopListItem;
private Context context;
DatabaseHelper dbHelper;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dbHelper = new DatabaseHelper(getContext());
shopListItem = new ArrayList<>();
context = getActivity();
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.add_productdialog,container, false);
getDialog().setCanceledOnTouchOutside(false);
getDialog().setTitle("Add to shoplist");
name = (EditText) rootView.findViewById(R.id.dialog_productname);
quantity = (EditText) rootView.findViewById(R.id.dialog_qantity);
location = (EditText) rootView.findViewById(R.id.dialog_location);
normalPrice = (EditText) rootView.findViewById(R.id.dialog_normalPrice);
offerPrice = (EditText) rootView.findViewById(R.id.dialog_offerPrice);
okButton = (Button) rootView.findViewById(R.id.dialog_okButton);
okButton.getBackground().setColorFilter(Color.parseColor("#2fbd4b"), PorterDuff.Mode.MULTIPLY);
okButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (name.getText().toString().isEmpty()) {
Toast.makeText(context, "You must add a name", Toast.LENGTH_LONG).show();
} else {
dbHelper.insertData(name.toString() ,quantity.toString(),location.toString(),normalPrice.toString(),offerPrice.toString());
getDialog().dismiss();
}
}
});
return rootView;
}
This is the mainActivity class where I create the recylerview, adapters and Database:
public class MainActivity extends AppCompatActivity{
private ImageButton addbutton;
private DialogAdd dialogAdd;
public static RecyclerView recyclerView;
private List<ShopListItem> shopListItems;
private SQLiteDatabase db;
private Cursor cursor;
private DatabaseHelper databaseHelper;
private ShoplistAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.shoppinglist_mainactivity);
databaseHelper = new DatabaseHelper(this);
addbutton = (ImageButton) findViewById(R.id.addbtn);
addbutton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialogAdd = new DialogAdd();
dialogAdd.show(getSupportFragmentManager(), "addDialog");
}
});
//RecyclerView
recyclerView = (RecyclerView)findViewById(R.id.rv_shoppinglist);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(App.getAppContex());
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(linearLayoutManager);
initializeData();
adapter = new ShoplistAdapter(shopListItems);
recyclerView.setAdapter(adapter);
}
private void initializeData(){
shopListItems = new ArrayList<>();
Cursor resultset = databaseHelper.getAllData();
if (resultset.moveToFirst()){
while(!resultset.isAfterLast()){
shopListItems.add(new ShopListItem(resultset.getString(1), resultset.getString(2), resultset.getString(3), resultset.getString(4), resultset.getString(5)));
resultset.moveToNext();
}
}
resultset.close();
shopListItems.add(new ShopListItem("Potato", "2 KG", "MALL", "7 kr", ""));
}
This class is where the database is defined:
public class DatabaseHelper extends SQLiteOpenHelper {
public static final String DATABASE_NAME ="dbshoplist.db";
public static final String TABLE_NAME ="product_table";
public static final String COL_ID = "ID";
public static final String COL_NAME ="NAME";
public static final String COL_QTY ="QUANTITY";
public static final String COL_LOCATION ="LOCATION";
public static final String COL_PRICE1 ="PRICE1";
public static final String COL_PRICE2 ="PRICE2";
/*
This constructor creates the database
*/
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, 1);
SQLiteDatabase db = this.getWritableDatabase();
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + TABLE_NAME + " (ID INTEGER PRIMARY KEY AUTOINCREMENT,NAME TEXT,QUANTITY TEXT,LOCATION TEXT,PRICE1 TEXT,PRICE2 TEXT)");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(db);
}
public boolean insertData(String name, String qty, String location, String price1, String price2){
SQLiteDatabase db = this.getWritableDatabase();
// content value is a row, and we fill it with the put();
ContentValues contentValues = new ContentValues();
contentValues.put(COL_NAME, name);
contentValues.put(COL_QTY, qty);
contentValues.put(COL_LOCATION, location);
contentValues.put(COL_PRICE1, price1);
contentValues.put(COL_PRICE2, price2);
long result = db.insert(TABLE_NAME, null,contentValues);
if(result == -1) {
return false;
}else{
return true;
}
}
public Cursor getAllData(){
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursorResults = db.rawQuery("SELECT * FROM " + TABLE_NAME, null);
return cursorResults;
}
My recyclerView adapter class:
public class ShoplistAdapter extends RecyclerView.Adapter<ShoplistAdapter.ViewHolder>{
List<ShopListItem> shopListItems;
public ShoplistAdapter(List<ShopListItem> shopListItems) {
this.shopListItems = shopListItems;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
View shoplist_itemView = inflater.inflate(R.layout.shop_list_item, parent, false);
ViewHolder viewHolder = new ViewHolder(shoplist_itemView);
return viewHolder;
}
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
holder.location.setText(shopListItems.get(position).location.toString());
holder.normalPrice.setText(shopListItems.get(position).normalprice.toString());
holder.offerPrice.setText(shopListItems.get(position).offerprice.toString());
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(shopListItems.get(position).quantity + " " + shopListItems.get(position).name);
holder.productname.setText(stringBuilder);
if(!shopListItems.get(position).offerprice.toString().isEmpty()){
holder.normalPrice.setPaintFlags(holder.normalPrice.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
}
if(shopListItems.get(position).normalprice.isEmpty()){
holder.normalPrice.setVisibility(View.GONE);
}
holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked == true){
holder.productname.setPaintFlags(holder.productname.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
holder.productname.setTextColor(Color.parseColor("#40000000"));
}else{
holder.productname.setPaintFlags(0 | Paint.ANTI_ALIAS_FLAG);
holder.productname.setTextColor(Color.BLACK);
}
}
});
}
#Override
public int getItemCount() {
return shopListItems.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder{
private CheckBox checkBox;
private TextView productname, quantity, location, normalPrice, offerPrice;
private ImageButton edit_icon, delete_icon;
public ViewHolder(View itemView) {
super(itemView);
productname = (TextView)itemView.findViewById(R.id.product_name);
location = (TextView)itemView.findViewById(R.id.product_location);
normalPrice = (TextView)itemView.findViewById(R.id.product_price);
offerPrice = (TextView)itemView.findViewById(R.id.product_offer_price);
edit_icon = (ImageButton)itemView.findViewById(R.id.editShopItem_Icon);
delete_icon = (ImageButton)itemView.findViewById(R.id.shopitem_delete_icon);
checkBox = (CheckBox) itemView.findViewById(R.id.bought_checkbox);
}
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
This is happening because you're calling the toString() method of fields of the ShopListItem object: shopListItems.get(position).location.toString().
Instead, create getter methods for the fields of your ShopListItem class, e.g.
public getLocation() {
return location;
}
and just call these to get the data.
hey guys currently Im studying recyclerview and sqlite on how to fetch data from sqlite then show it to recyclerview. I made it working but Im not confident that it is the right way. here is my code.
MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Toolbar mToolBar;
private NavigationView mDrawer;
private ActionBarDrawerToggle mdrawerToggle;
private DrawerLayout mDrawerLayout;
private Button alarmButton;
private AlarmManager alarmManager;
private PendingIntent sender;
private RecyclerView listReminder;
private RemindersAdapter adapter;
List<ListInfo> data;
ListInfo infoData;
Button addReminderBtn;
MyDBHandler dbHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_PROGRESS);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initDrawer();
initView();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mdrawerToggle.onConfigurationChanged(newConfig);
}
public void initDrawer(){
mToolBar = (Toolbar) findViewById(R.id.app_bar);
mDrawer = (NavigationView) findViewById(R.id.main_drawer);
setSupportActionBar(mToolBar);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mdrawerToggle = new ActionBarDrawerToggle(
this,
mDrawerLayout,
mToolBar,
R.string.drawer_open,
R.string.drawer_close);
mDrawerLayout.setDrawerListener(mdrawerToggle);
// indicator based on whether the drawerlayout is in open or closed
mdrawerToggle.syncState();
}
public void initView(){
listReminder = (RecyclerView) findViewById(R.id.listData);
dbHandler = new MyDBHandler(this);
adapter = new RemindersAdapter(this, dbHandler.getAllData_a());
listReminder.setAdapter(adapter);
listReminder.setLayoutManager(new LinearLayoutManager(this));
addReminderBtn = (Button) findViewById(R.id.addBtn);
addReminderBtn.setOnClickListener(this);
}
#Override
public void onClick(View v) {
switch (v.getId()){
case R.id.addBtn:
Intent addReminder = new Intent(this, AddReminderActivity.class);
startActivity(addReminder);
break;
}
}
}
MyDBHandler.java
public class MyDBHandler extends SQLiteOpenHelper{
private static final int DATABASE_VERSION = 6;
private static final String DATABASE_NAME = "paroah.db";
public static final String TABLE_REMINDER = "reminders";
public static final String COLUMN_ID = "_id";
public static final String COLUMN_TITLE_REMINDER = "title";
public static final String COLUMN_DESC_REMINDER = "desc";
public static final String COLUMN_DATE_REMINDER = "date_created";
public MyDBHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
String query = " CREATE TABLE "
+TABLE_REMINDER+ "(" +
COLUMN_ID +" INTEGER PRIMARY KEY AUTOINCREMENT,"+
COLUMN_TITLE_REMINDER + " TEXT ,"+
COLUMN_DESC_REMINDER + " TEXT ,"+
COLUMN_DATE_REMINDER + " TEXT "+
");";
db.execSQL(query);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// db.execSQL("DROP TABLE IF EXIST " + TABLE_REMINDER); // onCreate(db);
Log.d("aoi", "Upgrading database from version " + oldVersion + " to "
+ newVersion + ", which will destroy all old data");
try {
db.execSQL("DROP TABLE IF EXISTS "+TABLE_REMINDER);
onCreate(db);
} catch (SQLException e) {
Log.d("aoi", "getting exception "
+ e.getLocalizedMessage().toString());
}
}
public void addReminder(ListInfo reminder ){
ContentValues values = new ContentValues();
values.put(COLUMN_TITLE_REMINDER, reminder.getTitle());
values.put(COLUMN_DESC_REMINDER, reminder.getDesc());
values.put(COLUMN_DATE_REMINDER, reminder.getDate());
SQLiteDatabase db = getWritableDatabase();
db.insert(TABLE_REMINDER, null, values);
db.close();
}
public void printDatabase(){
SQLiteDatabase db = getWritableDatabase();
}
public List<ListInfo> getAllData_a(){
SQLiteDatabase db = getWritableDatabase();
String query = "SELECT * FROM "+TABLE_REMINDER;
Cursor cursor=db.rawQuery(query, null);
List<ListInfo> data=new ArrayList<>();
while (cursor.moveToNext()){
int _id=cursor.getInt(cursor.getColumnIndex(COLUMN_ID));
String title = cursor.getString(cursor.getColumnIndex(COLUMN_TITLE_REMINDER));
String desc = cursor.getString(cursor.getColumnIndex(COLUMN_DESC_REMINDER));
String date = cursor.getString(cursor.getColumnIndex(COLUMN_DATE_REMINDER));
ListInfo current = new ListInfo();
current.set_id(_id);
current.title = title;
current.desc = desc;
current.date = date;
data.add(current);
}
return data;
}
}
RemindersAdapter.java
public class RemindersAdapter extends RecyclerView.Adapter<RemindersAdapter.ItemViewHolder> {
private final LayoutInflater inflater;
List<ListInfo> data = Collections.emptyList();
public RemindersAdapter(Context context, List<ListInfo> data){
inflater = LayoutInflater.from(context);
this.data = data;
}
#Override
public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.reminder_item, parent, false);
ItemViewHolder holder = new ItemViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(ItemViewHolder holder, int position) {
ListInfo current = data.get(position);
holder.title.setText(current.title);
}
#Override
public int getItemCount() {
return data.size();
}
class ItemViewHolder extends RecyclerView.ViewHolder{
TextView title;
public ItemViewHolder(View itemView) {
super(itemView);
title = (TextView) itemView.findViewById(R.id.reminderTitle);
}
}
}
is there any other way to make this code clean? What I need are the concepts and examples if you do have, or what I need to learn to make it clean. TIA!!
I am building an app that displays items in a ListFragment. Right now each item displays the title and creation date. There are two other fragments. One that creates an item and has a EditText field where i can edit the title. Another simply displays an individual items contents.
The issue I am having is that every time I enter a character in the EditText field the app closes. The error messages indicate that the error occurs at onTextChanged in the TextChangedListener. Since I had this feature working when I was storing everything as a JSON file the error must occur because of the way i am updating the database and updating my model layer.
This file performs all the database operations and creates a custom Cursor.
public class SnapDatabaseHelper extends SQLiteOpenHelper {
private static final String TAG = "FeedFragment";
private static final String DB_NAME = "snap.sqlite";
private static final int VERSION = 1;
private static final String TABLE_SNAP = "snap";
private static final String COLUMN_SNAP_ID = "_id";
private static final String COLUMN_SNAP_DATE = "snap_date";
private static final String COLUMN_SNAP_UUID = "snap_uuid";
private static final String COLUMN_SNAP_TITLE = "snap_title";
public SnapDatabaseHelper(Context context){
super(context, DB_NAME, null, VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
// Create SNAP table
db.execSQL("create table snap(" +
"_id integer primary key autoincrement, " +
//"snap_uuid text, " +
"snap_date integer, " +
"snap_title text) ");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//
}
public long insertSnap(Snap snap){
ContentValues cv = new ContentValues();
//cv.put(COLUMN_SNAP_UUID, snap.getUniqueId().toString());
cv.put(COLUMN_SNAP_DATE, snap.getDate().getTime());
cv.put(COLUMN_SNAP_TITLE, "");
return getWritableDatabase().insert(TABLE_SNAP, null, cv);
}
public boolean updateTitle(long snapId, String text)
{
ContentValues cv = new ContentValues();
cv.put(COLUMN_SNAP_ID, snapId);
cv.put(COLUMN_SNAP_TITLE, text);
int i= getWritableDatabase().update(TABLE_SNAP, cv, COLUMN_SNAP_ID+ "=" + snapId, null);
return i>0;
}
public SnapCursor querySnap(long id) {
Cursor wrapped = getReadableDatabase().query(TABLE_SNAP,
null, // all columns
COLUMN_SNAP_ID + " = ?", // look for a run ID
new String[]{ String.valueOf(id) }, // with this value
null, // group by
null, // order by
null, // having
"1"); // limit 1 row
return new SnapCursor(wrapped);
}
public SnapCursor querySnaps() {
// equivalent to "select * from run order by start_date asc"
Cursor wrapped = getReadableDatabase().query(TABLE_SNAP,
null, null, null, null, null, COLUMN_SNAP_DATE + " asc");
return new SnapCursor(wrapped);
}
public static class SnapCursor extends CursorWrapper{
public SnapCursor(Cursor c){
super(c);
}
public Snap getSnap() {
if (isBeforeFirst() || isAfterLast())
return null;
Snap s = new Snap();
s.setId(getLong(getColumnIndex(COLUMN_SNAP_ID)));
//s.setUniqueId(UUID(getString(getColumnIndex(COLUMN_SNAP_UUID))));
s.setDate(new Date(getLong(getColumnIndex(COLUMN_SNAP_DATE))));
s.setTitle(getString(getColumnIndex(COLUMN_SNAP_TITLE)));
return s;
}
}
}
This file links the fragments to the DatabaseHelper.
public class SnapLab {
private static SnapLab sSnapLab;
private Context mAppContext;
private SnapDatabaseHelper mHelper;
// private constructor
private SnapLab(Context appContext){
mAppContext = appContext;
mHelper = new SnapDatabaseHelper(mAppContext);
}
public static SnapLab get(Context c){
if(sSnapLab == null){
sSnapLab = new SnapLab(c.getApplicationContext());
}
return sSnapLab;
}
public Snap insertSnap() {
Snap s = new Snap();
s.setId(mHelper.insertSnap(s));
return s;
}
public boolean updateTitle(long snapId, String text){
return mHelper.updateTitle(snapId, text);
}
public SnapCursor querySnaps() {
return mHelper.querySnaps();
}
public Snap getSnap(long id) {
Snap s = null;
SnapCursor cursor = mHelper.querySnap(id);
cursor.moveToFirst();
// if we got a row, get a run
if (!cursor.isAfterLast())
s = cursor.getSnap();
cursor.close();
return s;
}
}
Here is the fragment with the EditText field
public class EditPageFragment extends Fragment {
private static final String TAG = "EditPageFragment";
public static final String EXTRA_SNAP_ID = "SNAP_ID";
private SnapLab mSnapLab;
private Snap mSnap;
private SnapDatabaseHelper mHelper;
private EditText mSnapText;
private Button mUploadButton;
private TextView mDateText;
private Long snapId;
public static EditPageFragment newInstance(Long snapId){
Bundle args = new Bundle();
args.putLong(EXTRA_SNAP_ID, snapId);
EditPageFragment fragment = new EditPageFragment();
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
mSnapLab = SnapLab.get(getActivity());
Bundle args = getArguments();
if (args != null){
long snapId = args.getLong(EXTRA_SNAP_ID, -1);
if (snapId != -1){
mSnap = mSnapLab.getSnap(snapId);
}
}
mSnap = new Snap();
mSnap = mSnapLab.insertSnap();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState){
View v = inflater.inflate(R.layout.edit_fragment, parent, false);
mDateText = (TextView)v.findViewById(R.id.edit_dateText);
mDateText.setText(mSnap.getDate().toString());
mSnapText = (EditText)v.findViewById(R.id.edit_snapText);
mSnapText.addTextChangedListener(new TextWatcher(){
#Override
public void afterTextChanged(Editable s) {
//leave blank for now
}
#Override
public void beforeTextChanged(CharSequence c, int start, int count,
int after) {
//leave blank for now
}
#Override
public void onTextChanged(CharSequence c, int start, int before,
int count) {
mSnap.setTitle(c.toString());
mSnapLab.updateTitle(snapId, c.toString());
Log.i(TAG, "text saved");
}
});
return v;
}
}
The import bits of code are the updateTitle() functions. What could I be doing wrong. Do you have a suggestion on how to better update a database. Everything works great except for the updating of the title. I appreciate any bit of help.
Looks like snapId is not assigned
private Long snapId; //field
few lines later
long snapId = args.getLong(EXTRA_SNAP_ID, -1); //local variable
few lines later
mSnapLab.updateTitle(snapId, c.toString()); //field
Please add stacktrace next time.