简体   繁体   中英

Updating an ArrayAdapter from inside an onClickListener in getView

I am making a shopping cart app where users can add and remove items from the cart. When a user views their cart, a list of items they have added appear. This list is made using an ArrayAdapter. Each row contains a remove button where the user can remove the item from the cart. I have successfully been able to remove the item from the Cart object. However, I am running into trouble when it comes to updating the screen when the user clicks the remove button. I have heard of the notifydatasetchanged() method for adapters, but I am not sure how to implement that from inside the OnClickListener in getView. Here is the code:

CartScreen.java

package com.livilatenight.livilatenight;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ListView;
import android.widget.Toast;

import com.parse.ParseException;
import com.parse.ParseUser;
import com.parse.SaveCallback;

public class CartScreen extends ActionBarActivity {

    ListView items;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_cart_screen);

        final ParseUser current = ParseUser.getCurrentUser();

        try{
            Cart userCart = (Cart) current.fetchIfNeeded().get("cart");
            String[] itemNames = userCart.getItems();
            String[] itemPrices = userCart.getPrices();
            int[] quantities = userCart.getQuantities();
            Integer[] itemPictures = userCart.getPictures();

            CartListAdapter adapter = new CartListAdapter(CartScreen.this, itemNames,itemPrices,quantities,itemPictures);
            items = (ListView) findViewById(R.id.listView);
            items.setAdapter(adapter);
        }catch(ParseException e){
            Toast.makeText(CartScreen.this, e.toString(),Toast.LENGTH_LONG).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_cart_screen, 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);
    }
}

CartListAdapter.java

package com.livilatenight.livilatenight;

import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.parse.ParseUser;

public class CartListAdapter extends ArrayAdapter<String> {

    private final Activity context;
    private final String[] items;
    private final String[] prices;
    private final int[] quantities;
    private final Integer[] pictures;

    public CartListAdapter(Activity context, String[] itemnames, String[] prices, int[] quantities, Integer[] pictures) {
        super(context, R.layout.item_list, itemnames);

        this.context=context;
        this.items=itemnames;
        this.prices=prices;
        this.quantities=quantities;
        this.pictures=pictures;
    }

    public View getView(final int position,View view,ViewGroup parent) {
        LayoutInflater inflater=context.getLayoutInflater();
        View rowView=inflater.inflate(R.layout.cart_item, null,true);

        TextView itemName = (TextView) rowView.findViewById(R.id.tvItemName);
        TextView itemPrice = (TextView) rowView.findViewById(R.id.tvPrice);
        ImageView itemPicture = (ImageView) rowView.findViewById(R.id.ivItemPicture);
        View blankView = (View) rowView.findViewById(R.id.blankView);
        Button removeCart = (Button) rowView.findViewById(R.id.btnRemoveCart);

        final Spinner spinner = (Spinner) rowView.findViewById(R.id.spinnerQty);
        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(context, R.array.spinner_numbers, android.R.layout.simple_spinner_item);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spinner.setAdapter(adapter);


        spinner.setSelection(quantities[position]-1);

        itemName.setText(items[position]);
        itemPrice.setText(prices[position]);
        itemPicture.setImageResource(pictures[position]);

        removeCart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ParseUser current = ParseUser.getCurrentUser();
                int quantity = spinner.getSelectedItemPosition()+1;

                Cart userCart = (Cart) current.get("cart");
                boolean success = userCart.removeFromCart(items[position]);

                if(success){
                    Toast.makeText(getContext(), "Removed from Cart", Toast.LENGTH_LONG).show();
                }else{
                    Toast.makeText(getContext(), "Item is already in your shopping cart", Toast.LENGTH_LONG).show();
                }

                current.saveInBackground();
            }
        });
        return rowView;
    };
}

I want to update the cart list when a user clicks the removeCart button. How could I do this?

UPDATE

I did a workaround where I just set a new adapter each time an item is removed. Not what I wanted to do but it works so I'll keep it the way it is.

In your custom adapter call this.notifyDataSetChanged(); where you are performing delete functionality and deleting that element from arrayList which is set to that adapter. You have to remove that record from the ArrayList too that you have set to your adapter if you know which record it is you can use ArrayList.remove(index); and then use notifyDataSetChanged();

EDIT: Go to your adapter and add a method delete();

public void delete(int position){
data.remove(position);
notifyItemRemoved(position);
}

In your onClick(); method add this:

delete(getPosition());

try this

if (success) {
                    Toast.makeText(getContext(), "Removed from Cart", Toast.LENGTH_LONG).show();
                    final String s = items[position];
                    List<String> list = new ArrayList<String>(Arrays.asList(items));
                    list.remove(s);
                    items = list.toArray(array);
                    this.notifyDataSetChanged()
                }

Here is the solution that worked in my case.

In your CartListAdapter override remove method of Array Adapter.

@Override
public void remove(String var){
    // Call your utility methods you defined to delete the item
    // Notify ListView that their is a change
    notifyDataSetChanged();
}

Make the following changes in your Click Listener

    removeCart.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // Call this.remove(var) with String you want to delete
        }
    });

notifyDataSetChanged() works only in case of add() , insert() , remove() , and clear() . Read this

HTH

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM