如何处理CustomArrayAdapter中的复选框

时间:2016-09-05 12:14:49

标签: java android checkbox android-arrayadapter gson

我正在尝试处理'检查/取消选中' CustomArrayAdapter中的一组复选框。

要求是当我检查'一个复选框,其他复选框应根据特定条件保持选中/取消选中。

我计划的方法是,我将存储所有的复选框' ArrayList中的对象,并使用' gson'将它们添加到我的SharedPreferences文件中。当我检查'我将检索每一个复选框,并根据我的标准更改复选框的状态。

出于某种原因存储“复选框”' SharedPreferences中的对象将编译器发送到无限循环,我得到以下堆栈日志:

09-05 07:52:20.186 1560-1600/millennia.sniffbt I/OpenGLRenderer: Initialized EGL, version 1.4
09-05 07:52:20.187 1560-1600/millennia.sniffbt D/OpenGLRenderer: Swap behavior 1
09-05 07:52:44.803 1560-1565/millennia.sniffbt I/art: Do partial code cache collection, code=124KB, data=100KB
09-05 07:52:44.804 1560-1565/millennia.sniffbt I/art: After code cache collection, code=124KB, data=100KB
09-05 07:52:44.804 1560-1565/millennia.sniffbt I/art: Increasing code cache capacity to 512KB
09-05 07:52:46.339 1560-1567/millennia.sniffbt W/art: Suspending all threads took: 16.280ms
09-05 07:52:48.700 1560-1571/millennia.sniffbt I/art: Background partial concurrent mark sweep GC freed 284903(5MB) AllocSpace objects, 20(1932KB) LOS objects, 37% free, 26MB/42MB, paused 4.525ms total 115.535ms
09-05 07:52:49.627 1560-1571/millennia.sniffbt I/art: Background sticky concurrent mark sweep GC freed 517140(8MB) AllocSpace objects, 31(3MB) LOS objects, 25% free, 31MB/42MB, paused 5.249ms total 97.072ms
09-05 07:52:49.976 1560-1567/millennia.sniffbt W/art: Suspending all threads took: 15.674ms
09-05 07:52:50.410 1560-1571/millennia.sniffbt I/art: Background sticky concurrent mark sweep GC freed 368915(6MB) AllocSpace objects, 20(2MB) LOS objects, 16% free, 35MB/42MB, paused 5.346ms total 90.929ms
09-05 07:52:50.804 1560-1571/millennia.sniffbt I/art: Background sticky concurrent mark sweep GC freed 293352(5MB) AllocSpace objects, 17(2MB) LOS objects, 13% free, 36MB/42MB, paused 5.083ms total 93.860ms
09-05 07:52:51.226 1560-1571/millennia.sniffbt I/art: Background partial concurrent mark sweep GC freed 333422(5MB) AllocSpace objects, 19(2MB) LOS objects, 29% free, 37MB/53MB, paused 6.722ms total 178.796ms
09-05 07:52:51.813 1560-1571/millennia.sniffbt I/art: Background sticky concurrent mark sweep GC freed 602192(10MB) AllocSpace objects, 30(3MB) LOS objects, 23% free, 40MB/53MB, paused 6.137ms total 117.126ms
09-05 07:52:52.374 1560-1571/millennia.sniffbt I/art: Background sticky concurrent mark sweep GC freed 506509(8MB) AllocSpace objects, 24(3MB) LOS objects, 19% free, 42MB/53MB, paused 6.292ms total 112.676ms
09-05 07:52:52.605 1560-1567/millennia.sniffbt W/art: Debugger attempted to resume all threads without having suspended them all before.
09-05 07:52:52.615 1560-1567/millennia.sniffbt I/art: Debugger is no longer active

这是我的CustomArrayAdapter

CustomArrayAdapter.java:

public class CustomArrayAdapter extends ArrayAdapter<Row> {
    Row[] rowItems = null;
    Context context;
    SharedPreferences appPrefs;

public CustomArrayAdapter(MyInterface fragmentActivity, Context context, Row[] resource) {
    super(context, R.layout.row_with_cb, resource);
    this.rowItems = resource;
    this.context = context;
    cf = new CommonFunctions();
    appPrefs = getContext().getSharedPreferences(getContext().getString(R.string.app_shared_pref_filename), Context.MODE_PRIVATE);
}

@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    LayoutInflater inflater = ((Activity)this.context).getLayoutInflater();
    convertView = inflater.inflate(R.layout.row_with_cb, parent, false);
    TextView name = (TextView)convertView.findViewById(R.id.row_with_cb_Txt);
    CheckBox cb = (CheckBox)convertView.findViewById(R.id.row_with_cb_ChkBox);

    // Add Checkboxes into ArrayList and store em away
    ArrayList<CheckBox> arrCheckBoxes = new ArrayList<>();
    arrCheckBoxes.add(cb);

    SharedPreferences.Editor prefEditor = appPrefs.edit();
    Gson gson = new Gson();
    String json;
    Type typeOfObject = new TypeToken<ArrayList<CheckBox>>(){}.getType();
    json = gson.toJson(arrCheckBoxes, typeOfObject); // MY COMPILER GOES INTO INFINITE LOOP HERE
    prefEditor.putString("ListOfChkBoxes", json);
    prefEditor.apply();

    // Create a onClickListener when a checkbox is selected
    cb.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            CheckBox cb = (CheckBox) v;
            rowItems[position].setCB(cb.isChecked());
        }
    });

    return convertView;
}

我有两个问题:

  1. 为什么要存储一个&#39;复选框&#39;将编译器发送到无限循环?
  2. 是否有更好的方法来存储和检索复选框?

2 个答案:

答案 0 :(得分:0)

如果Checkbox对象是指Checkobox,View子类 - 不能将它们存储在SharedPreferences中。你甚至不应该在你自己的适配器中保留指向它们的引用。您可以做的是将其状态保留在某个集合中,并将其填入onBindViewHolder()。然后,您可以使用JSON或您选择的任何序列化格式将此基元集合存储在SharedPreferences中。

答案 1 :(得分:0)

解决方案比我预期的要简单得多。感谢@Himani的评论。

我在getView函数中创建的ArrayList是活动的,即使选中了另一个复选框,我也可以操作复选框。

以下是代码:

public View getView(final int position, View convertView, ViewGroup parent) {
    LayoutInflater inflater = ((Activity)this.context).getLayoutInflater();
    convertView = inflater.inflate(R.layout.row_with_cb, parent, false);
    TextView name = (TextView)convertView.findViewById(R.id.row_with_cb_Txt);
    CheckBox cb = (CheckBox)convertView.findViewById(R.id.row_with_cb_ChkBox);

    arrCheckBoxes.add(cb); // THIS ARRAY ALWAYS REMAINS UPDATED INSIDE ONCLICKLISTENER

    // Create a onClickListener when a checkbox is selected
    cb.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            CheckBox cb = (CheckBox) v;
            rowItems[position].setCB(cb.isChecked());

            if(cb.isChecked()) {
                for(int iCnt = 0; iCnt < arrCheckBoxes.size(); iCnt++) {
                    if (rowItems[iCnt].isCBChecked() && !rowItems[iCnt].getDeviceAddress().equals(rowItems[position].getDeviceAddress())) {
                        if (rowItems[iCnt].getDeviceMajorClass() == rowItems[position].getDeviceMajorClass()) {
                            arrCheckBoxes.get(iCnt).setChecked(false); // THIS IS WHERE ANOTHER CHECKBOX GETS UNCHECKED IF THE CONDITION GETS SATISFIED
                            rowItems[iCnt].setCB(false);
                            notifyDataSetChanged();
                        }
                    }
                }
            }
        }
    });

也感谢其他答案。