Reputation: 3045
On my app I have a ListView
with Checkboxes
and have an adapter that extends BaseAdapter
to populate the ListView
. The basic function of the list is to show debts and the user can choose which ones to pay by checking the boxes, you have the total at the bottom of the list that gets updated when the user adds/removes an item. Now, some debts are related to another and if the user checks one, any other related debt should be marked as well and same if you uncheck a debt. I also have a button that should clear all the selected debts on the list, and that's where my problem is.
I keep record of the selected debts on an ArrayList
and it seems to work for all the program but the clear button. When the button is pressed the selected debts list seems to be always empty. Any idea on what could be happening?
Here is my adapter:
public class ServicesFinancialStatusAdapter extends BaseAdapter implements CompoundButton.OnCheckedChangeListener{
private Context context;
private List<Debts> debtsList;
private List<Debts> selectedDebts;
private LayoutInflater inflater;
private int tabPosition;
private float total;
private OnTotalChangedListener listener;
public ServicesFinancialStatusAdapter(Context context, List<Debts> debtsList, int tabPosition) {
this.context = context;
this.debtsList = debtsList;
this.tabPosition = tabPosition;
this.total = 0;
this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.selectedDebts = new ArrayList<Debts>();
}
@Override
public int getCount() {
return debtsList.size();
}
@Override
public Object getItem(int i) {
return debtsList.get(i);
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewHolder holder;
if (view == null) {
holder = new ViewHolder();
view = inflater.inflate(R.layout.item_services_financial_status, viewGroup, false);
holder.concept = (TextView) view.findViewById(R.id.payment_concept);
holder.descriptionOrDate = (TextView) view.findViewById(R.id.payment_description_date);
holder.amount = (TextView) view.findViewById(R.id.payment_amount);
holder.expirationDate = (TextView) view.findViewById(R.id.payment_expiration_date);
if (tabPosition > 4) {
holder.checkBox = (CheckBox) view.findViewById(R.id.check_box);
holder.checkBox.setOnCheckedChangeListener(this);
}
view.setTag(holder);
} else
holder = (ViewHolder) view.getTag();
Debts item = debtsList.get(i);
holder.concept.setText(item.getConcept());
holder.amount.setText(item.getAmountToString());
if (item.isExpired())
holder.expirationDate.setText(context.getString(R.string.expired_status_indicator));
else
holder.expirationDate.setText(context.getString(R.string.debts_expiration_date_indicator) + item.getExpirationDate());
if (tabPosition < 3)
holder.descriptionOrDate.setText(item.getDescription());
else if (tabPosition < 5)
holder.descriptionOrDate.setText(item.getDate());
else {
holder.descriptionOrDate.setVisibility(View.GONE);
holder.checkBox.setVisibility(View.VISIBLE);
holder.checkBox.setTag(i);
holder.checkBox.setChecked(item.isSelected());
}
return view;
}
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
//Get the position of the item clicked and the data object
Integer position = (Integer) buttonView.getTag();
Debts item = debtsList.get(position);
//Change the status ob the object
item.setSelected(isChecked);
for (Debts debts : debtsList) {
//Check on the list for related objects and marks them as well
if (debts.getConceptId() == item.getRelatedDebt())
debts.setSelected(isChecked);
//Get the amount of the debt and add/remove it from
//the selectedDebts list and update the total
float amount = debts.getAmount();
if (debts.isSelected()) {
if (!selectedDebts.contains(debts)) {
selectedDebts.add(debts);
listener.onTotalChanged(addToTotal(amount), selectedDebts);
}
}
else {
if (selectedDebts.contains(debts)) {
selectedDebts.remove(debts);
listener.onTotalChanged(removeFromTotal(amount), selectedDebts);
}
}
}
//Finally update the UI
notifyDataSetChanged();
}
//Anywhere else in the code selectedDebts has the right data but here
//Here the size of the list is always 0
public void unMarkDebts() {
for (Debts debts : debtsList) {
//Get the amount of the debt and remove it from
//the selectedDebts list, set the data object as unselected
//and update the total
float amount = debts.getAmount();
if (selectedDebts.contains(debts)) {
debts.setSelected(false);
selectedDebts.remove(debts);
listener.onTotalChanged(removeFromTotal(amount), selectedDebts);
}
}
//Update the UI
notifyDataSetChanged();
}
private float addToTotal(float value) {
return total += value;
}
private float removeFromTotal(float value) {
return total -=value;
}
public interface OnTotalChangedListener{
public void onTotalChanged(float total, List<Debts> selectedDebts);
}
public void setOnTotalChangedListener(OnTotalChangedListener listener) {
this.listener = listener;
}
private class ViewHolder {
TextView concept, descriptionOrDate, amount, expirationDate;
CheckBox checkBox;
}
}
And here is my fragment code:
public class CheckoutFragment extends BaseFragment implements View.OnClickListener, ServicesFinancialStatusAdapter.OnTotalChangedListener {
public static final String TAG = CheckoutFragment.class.getSimpleName();
private List<Debts> debtsList;
private List<Debts> selectedDebts;
private ServicesFinancialStatusAdapter adapter;
private TextView totalView, positiveBalanceView;
private View noDebtsView, header, footer;
private LinearLayout mainLayout;
private float total, positiveBalance;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
debtsList = new ArrayList<Debts>();
adapter = new ServicesFinancialStatusAdapter(getActivity(), debtsList, 5);
adapter.setOnTotalChangedListener(this);
webServices = ((MainActivity) getActivity()).getNetworkInstance();
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//Initialize the views
...
reloadData();
onTotalChanged(0, null);
return view;
}
@Override
public void onClick(View view) {
reloadData();
}
@Override
public void onTotalChanged(float total, List<Debts> selectedDebts) {
this.total = total == 0 ? total : total - positiveBalance;
this.selectedDebts = selectedDebts;
totalView.setText(getString(R.string.total_indicator) + Utilities.formatNumberAsMoney(this.total));
getActivity().invalidateOptionsMenu();
}
private void reloadData() {
debtsList.clear();
adapter = new ServicesFinancialStatusAdapter(getActivity(), debtsList, 5);
adapter.setOnTotalChangedListener(this);
loadData();
}
private void loadData() {
//Load debts from server
...
}
private void saveSelectedDebts() {
for (Debts selectedDebt : selectedDebts) {
long id = Debts.insert(getActivity(), selectedDebt);
//Log.d(TAG, "Inserted " + selectedDebt.getConcept() + " with ID " + id);
}
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
if (!((MainActivity) getActivity()).drawerIsOpen) {
inflater.inflate(R.menu.checkout, menu);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.clear:
adapter.unMarkDebts();
break;
case R.id.checkout:
selectPaymentMode();
break;
}
return super.onOptionsItemSelected(item);
}
private void selectPaymentMode() {
...
}
}
Upvotes: 0
Views: 128
Reputation: 940
The chat broke. I think one investigation could be:
Everytime you call reload, you are initiating from scracth the adapter with a new object, (call method new). Remove that line and just use the previous adapter (taking care of initiating the adapteer on onCreate). Notice that the vairable selectedDebts is local to the adapter and you are not passing it in the constructor.
Upvotes: 1