【问题标题】:ArrayList loses dataArrayList 丢失数据
【发布时间】:2014-11-27 18:02:30
【问题描述】:

在我的应用程序中,我有一个 ListViewCheckboxes,并且有一个扩展 BaseAdapter 以填充 ListView 的适配器。列表的基本功能是显示债务,用户可以通过选中复选框来选择要支付的债务,当用户添加/删除项目时,列表底部的总数会更新。现在,一些债务与另一个债务相关,如果用户选中一个债务,则任何其他相关债务也应标记为相同,如果您取消选中债务则相同。我还有一个按钮可以清除列表中所有选定的债务,这就是我的问题所在。

我在ArrayList 上记录了选定的债务,它似乎适用于所有程序,但清除按钮除外。当按下按钮时,选定的债务列表似乎总是空的。知道会发生什么吗?

这是我的适配器:

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;
    }
}

这是我的片段代码:

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() {

        ...
    }
}

【问题讨论】:

  • 这是一个告诉我的主要活动更新总计值的接口。我根据适配器中选定的债务计算总计的值,然后通过该接口将该值发送到活动
  • 如果我理解得很好,您遇到的问题是在函数“unMarkDebts”中,debtsList 的大小始终为 0。那是对的吗?还是监听器调用没有收到正确信息的问题?
  • 你是对的,除了不是debtsList,它是selectedDebts那个下降到0的那个。debtsList是我保存所有Debts对象的地方,selectedDebts记录了用户选择的对象。
  • 我仔细检查了您的代码,我认为是正确的。您是否检查过 unMarkDebts(在 for 之前) selectedDebts.size() 是否为 0?如果是这种情况,我看到的唯一选择是您的听众正在修改 selectedDebts。
  • 是的,我也检查过,大小保持正确,直到我调用 unMarkDebts。我不知道发生了什么改变了它

标签: android android-listview arraylist baseadapter


【解决方案1】:

聊天中断了。我认为一项调查可能是:

每次调用 reload 时,都是从头开始使用新对象(调用方法 new)启动适配器。删除该行并仅使用以前的适配器(注意在 onCreate 上启动适配器)。请注意,可变的 selectedDebts 是适配器本地的,您没有在构造函数中传递它。

【讨论】:

  • 解决了!那部分代码就是问题所在!非常感谢!
猜你喜欢
  • 2012-03-05
  • 1970-01-01
  • 2019-08-02
  • 2011-08-09
  • 1970-01-01
  • 2020-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多