Reputation: 11
First time asking a question on this site, however I have used the site to
solve most of my other problems through the course of making my project for
Udacity.
I have an inventory App that stores and displays items in a SQLite Database, all the functionality is complete except for a Sale Button that is paired with every item. Here is a screenshot, including the sale button
The Sale button currently will reduce the quantity in the database by 1, but it will not update the Listview quantity that is also in the screenshot, the only way it updates is if you click the item to enter a detail item screen and then hit the back button.
I believe the answer lies with either changeCursor() or notifyDataSetChanged() from my researching, but I have been unable to apply it to my code to any effect.
ItemCursorAdapter
public ItemCursorAdapter(Context context, Cursor c) {
super(context, c, 0);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.list_layout, parent, false);
}
@Override
public void bindView(final View view, final Context context, final Cursor mCursor) {
TextView itemName = (TextView) view.findViewById(R.id.list_item_name);
TextView itemQty = (TextView) view.findViewById(R.id.list_ItemQty);
TextView locText = (TextView) view.findViewById(R.id.list_ItemLocation);
TextView priceText = (TextView) view.findViewById(R.id.list_ItemPrice);
final Button saleButton = (Button) view.findViewById(R.id.list_salebutton);
//get values from cursor
int nameColumnIndex = mCursor.getColumnIndex(DBhelper.KEY_NAME);
int qtyColumnIndex = mCursor.getColumnIndex(DBhelper.KEY_QUANTITY_HAVE);
int locColumnIndex = mCursor.getColumnIndex(DBhelper.KEY_LOCATION);
int priceColumnIndex = mCursor.getColumnIndex(DBhelper.KEY_QUANTITY_WANT);
int idColumnIndex = mCursor.getColumnIndex(DBhelper.KEY_ID);
//Populate fields with values
String itemNameString = mCursor.getString(nameColumnIndex);
QUANTITY_HAVESTRING = mCursor.getString(qtyColumnIndex);
String locationString = mCursor.getString(locColumnIndex);
String priceString = mCursor.getString(priceColumnIndex);
SELECTEDITEM_SOLD_BUTTON = mCursor.getString(idColumnIndex);
//Adds tags to the Sale Buttons as they are created, Quantity and ID
saleButton.setTag(R.id.tagQuantity, mCursor.getString(qtyColumnIndex));
saleButton.setTag(R.id.tagID, mCursor.getString(idColumnIndex));
itemName.setText(itemNameString);
itemQty.setText(QUANTITY_HAVESTRING);
locText.setText(locationString);
priceText.setText("$" + priceString);
saleButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String tagID = (String) saleButton.getTag(R.id.tagID);
String tagQuantity = (String) saleButton.getTag(R.id.tagQuantity);
if (Integer.parseInt(tagQuantity) > 0) {
DBhelper mDBhelper = new DBhelper(mContext);
SQLiteDatabase db = mDBhelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(DBhelper.KEY_QUANTITY_HAVE, (Integer.parseInt(tagQuantity) - 1));
db.update(DBhelper.TABLE_INVENTORY, values, "_id = " + tagID, null);
Toast.makeText(mContext, itemAdapter.toString(), Toast.LENGTH_SHORT).show();
itemAdapter.changeCursor(mCursor);
itemAdapter.notifyDataSetChanged();
}
}
});
//todo add on destroy db close
}
}
MainActivity
public class MainActivity extends AppCompatActivity {
private DBhelper mDBhelper;
public Cursor cursor;
public static ItemCursorAdapter itemAdapter;
public static ListView lvItems;
// ON CREATE
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDBhelper = new DBhelper(this);
}
// ON CREATE OPTIONS MENU
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu options from the res/menu/menu_catalog.xml file.
// This adds menu items to the app bar.
getMenuInflater().inflate(R.menu.inventory_menu_main, menu);
return true;
}
//ACTION BAR MENU when clicked
@Override
public boolean onOptionsItemSelected(MenuItem item) {
SQLiteDatabase db = mDBhelper.getWritableDatabase();
// User clicked on a menu option in the app bar overflow menu
switch (item.getItemId()) {
// Respond to a click on the "Delete all entries" menu option
case R.id.action_delete_all_entries:
db.delete(DBhelper.TABLE_INVENTORY, null, null);
onStart();
return true;
//Populate Standard Items, that the app is primarily designed to track.
case R.id.action_add_standard_entries_entries:
String[] INSERT_ROWS = getResources().getStringArray(R.array.artilleryEquipmentRows);
for (int i = 0; i < 33; i++)
db.execSQL(INSERT_ROWS[i]);
onStart();
return true;
//ABOUT APP INFO
case R.id.action_display_appInfo:
AlertDialog aboutDialog = new AlertDialog.Builder(MainActivity.this).create();
aboutDialog.setTitle(MainActivity.this.getString(R.string.aboutDialogTitle));
aboutDialog.setMessage(MainActivity.this.getString(R.string.aboutDialogMessage));
//TODO set a icon
aboutDialog.setButton(AlertDialog.BUTTON_NEUTRAL, MainActivity.this.getString(R.string.confirmDialogOk),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
aboutDialog.show();
return true;
// Add new Item Button (Shows up as a + sign)
case R.id.action_additem:
Intent intent = new Intent(MainActivity.this, AddItemActivity.class);
startActivity(intent);
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onStart() {
super.onStart();
displayDatabaseInfo();
}
// Populates the list
public void displayDatabaseInfo() {
// Create and/or open a database to read from it
SQLiteDatabase db = mDBhelper.getReadableDatabase();
// Define a projection that specifies which columns from the database
// you will actually use after this query.
String[] projection = {
DBhelper.KEY_ID,
DBhelper.KEY_NAME,
DBhelper.KEY_QUANTITY_HAVE,
DBhelper.KEY_QUANTITY_WANT,
DBhelper.KEY_LOCATION,
DBhelper.KEY_ISSUED_BOOLEAN};
// Perform a query on the pets table
cursor = db.query(
DBhelper.TABLE_INVENTORY, // The table to query
projection, // The columns to return
null, // The columns for the WHERE clause
null, // The values for the WHERE clause
null, // Don't group the rows
null, // Don't filter by row groups
null); // The sort order
ListView lvItems = (ListView) findViewById(R.id.main_list_view);
itemAdapter = new ItemCursorAdapter(this, cursor);
lvItems.setAdapter(itemAdapter);
//Assigns Empty View for when no items in Database
View emptyView = findViewById(R.id.empty_view);
lvItems.setEmptyView(emptyView);
lvItems.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long passID) {
Intent intent = new Intent(MainActivity.this, AddItemActivity.class);
intent.putExtra("itemPosition", passID);
startActivity(intent);
}
});
}
//Closes the cursor on app termination
@Override
protected void onDestroy() {
super.onDestroy();
cursor.close();
Log.d("tag", "Cursor(MainActivity) Closed");
}
}
Upvotes: 1
Views: 909
Reputation: 504
you can do this by a slow way still searching for a better solution but i couldn't find
use restartLoader
getLoaderManager().restartLoader(0, null, Activity.this);
mAdapter.notifyDataSetChanged();
Upvotes: 1
Reputation: 2334
I have been doing the course too and encountered the same problem, albeit I think I went a different route, and maybe it is a bit more elegant? The trick is to use the TextView text to get the quantity value.
This is from my custom CursorAdapter:
// Quantity Button
ImageButton button = (ImageButton) view.findViewById(R.id.sales_button);
// Get the current items ID
int currentId = cursor.getInt(cursor.getColumnIndex(InventoryEntry._ID));
// Make the content uri for the current Id
final Uri contentUri = Uri.withAppendedPath(InventoryEntry.CONTENT_URI, Integer.toString(currentId));
// Change the quantity when you click the button
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
TextView quantityView = (TextView) view.findViewById(R.id.quantity);
int quantity = Integer.valueOf(quantityView.getText().toString());
if (quantity > 0) {
quantity = quantity - 1;
}
// Content Values to update quantity
ContentValues values = new ContentValues();
values.put(InventoryEntry.COLUMN_QUANTITY, quantity);
// update the database
context.getContentResolver().update(contentUri, values, null, null);
}
});
You don't notify changes in the adapter, do it in the Provider as you are supposed to, and use the mAdapter.swapCursor() function to change the cursor in the LoaderManager Callbacks of the MainActivity.
Upvotes: 0
Reputation: 83537
Since the code for onClick()
is inside ItemCursorAdapter
, you only need to call
notifyDataSetChanged();
You don't need to call changeCursor()
since the current cursor can be reused.
Upvotes: 0
Reputation: 11
I solved it somewhat, good enough to turn in for the project.
saleButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
TextView itemQty = (TextView) view.findViewById(R.id.list_ItemQty);
String itemQtyString = itemQty.getText().toString();
int itemQtyInt = Integer.parseInt(itemQtyString);
String tagID = (String) saleButton.getTag(R.id.tagID);
String tagQuantity = (String) saleButton.getTag(R.id.tagQuantity);
if (itemQtyInt > 0) {
itemQtyInt = itemQtyInt - 1;
itemQtyString = Integer.toString(itemQtyInt);
DBhelper mDBhelper = new DBhelper(mContext);
SQLiteDatabase db = mDBhelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(DBhelper.KEY_QUANTITY_HAVE, itemQtyInt);
db.update(DBhelper.TABLE_INVENTORY, values, "_id = " + tagID, null);
itemQty.setText(itemQtyString);
Upvotes: 0
Reputation: 1245
try changing
itemAdapter.changeCursor(mCursor);
itemAdapter.notifyDataSetChanged();
to
changeCursor(mCursor);
notifyDataSetChanged();
it should work.
Upvotes: 0