Nicholas Cherryholmes
Nicholas Cherryholmes

Reputation: 11

Updating ListView with CursorAdapter after an OnClick changes a value in SQLite database?

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

Answers (5)

Farido mastr
Farido mastr

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

P Fuster
P Fuster

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

Code-Apprentice
Code-Apprentice

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

Nicholas Cherryholmes
Nicholas Cherryholmes

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

Saurabh
Saurabh

Reputation: 1245

try changing

 itemAdapter.changeCursor(mCursor);
 itemAdapter.notifyDataSetChanged();

to

 changeCursor(mCursor);
 notifyDataSetChanged();

it should work.

Upvotes: 0

Related Questions