首页 > 解决方案 > 无法启动活动 ComponentInfo - 由编辑 ArrayList 中的对象引起

问题描述

我正在构建一个与 SQLite 数据库一起使用以跟踪项目列表的应用程序。项目也存储在 ArrayList (productArrayList) 中。我达到了字符数限制,所以将把描述和一些组件放在线程中。

购物清单适配器:

    public class ShoppingListAdapter extends ArrayAdapter<Product> {

    private Cursor adapterCursor;
    private ShoppingList correspondingShoppingList;

    private static final String CHECK_BOX_SHARED_PREFS = "checkBoxPrefs";


    public ShoppingListAdapter(@NonNull Context context, ArrayList<Product> products, Cursor curs, ShoppingList corrShList) {
        super(context, 0, products);
        adapterCursor = curs;
        correspondingShoppingList = corrShList;
    }

    @NonNull
    @Override
    public View getView(final int position, @Nullable View convertView, @NonNull ViewGroup parent) {
        final Product product = getItem(position);
        if(convertView == null){
            convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_shopping_list, parent, false);
        }
        Button btnDeleteProduct = convertView.findViewById(R.id.btn_delete_item);
        TextView viewName = convertView.findViewById(R.id.view_name_item);
        TextView viewInstances = convertView.findViewById(R.id.view_instances_item);
        final CheckBox checkBox = convertView.findViewById(R.id.check_box_item);
        viewName.setText(product.name);

        if (product.instances <= 0) {
            viewInstances.setText("");
        } else {
            viewInstances.setText(" x " + String.valueOf(product.instances));
        }

        btnDeleteProduct.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                remove(product);
                correspondingShoppingList.saveList();
            }
        });

        checkBox.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                saveCheckBoxState(product.productID, position, checkBox.isChecked());    // before was the _ID, now it is position
            }
        });
        loadCheckBoxState(product.productID, checkBox);
        return convertView;
    }

    private void saveCheckBoxState(long id, int position, Boolean checkBoxIsChecked) {      // remove the position parameter if it does not work
        correspondingShoppingList.setCheckBoxStateInList(position, checkBoxIsChecked);      // Used to get around the lack of
        notifyDataSetChanged();                                                             // call by reference

        SharedPreferences shPrefs = getContext().getSharedPreferences (CHECK_BOX_SHARED_PREFS, Context.MODE_PRIVATE);
        SharedPreferences.Editor prefEdit = shPrefs.edit();
        prefEdit.putBoolean(Long.toString(id), checkBoxIsChecked);
        prefEdit.apply();
    }

    private void loadCheckBoxState(long id, CheckBox cb){
        SharedPreferences shPrefs = getContext().getSharedPreferences(CHECK_BOX_SHARED_PREFS, Context.MODE_PRIVATE);
        boolean checked = shPrefs.getBoolean(Long.toString(id), false);
        cb.setChecked(checked);
    }

    public void changeCursor(Cursor replacementCurs){   // replaces adapterCursor with replacementCurs
        if (adapterCursor != null){
            adapterCursor.close();
        }
        adapterCursor = replacementCurs;
        if (replacementCurs!= null){
            notifyDataSetChanged();         // sent notification to the shopping list RecyclerView
        }
    }

    public int getItemCount() {             // returns the amount of items present at the moment of enquiry
        return adapterCursor.getCount();
    }

}

转移菜单:

    public class TransferMenu extends AppCompatActivity {

    private TextView viewProductName;
    private TextView viewProductAmount;
    private TextView viewDate;

    private Button btnMinus;
    private Button btnPlus;
    private Button btnCancel;
    private Button btnSelectDate;
    private Button btnAddItem;

    private DatePickerDialog.OnDateSetListener datePickerDiagListener;
    private ArrayList<Product> receivedShoppingList;


    private String LIST_VIEW_SHARED_PREFS_KEY;
    private int amount = 0;

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

        viewProductName = findViewById(R.id.view_product_name_transfer);
        viewProductAmount = findViewById(R.id.view_amount_transfer);
        viewDate = findViewById(R.id.view_date_transfer);
        btnMinus = findViewById(R.id.btn_minus_transfer);
        btnPlus = findViewById(R.id.btn_plus_transfer);
        btnCancel = findViewById(R.id.btn_cancel_transfer);
        btnSelectDate = findViewById(R.id.btn_select_date_transfer);
        btnAddItem = findViewById(R.id.btn_add_item_transfer);

        receivedShoppingList = (ArrayList<Product>) getIntent().getSerializableExtra("listReference");
        LIST_VIEW_SHARED_PREFS_KEY = getIntent().getStringExtra("sharedPrefsKey");

        System.out.println("TransferMenu:");
        ShoppingList.printList(receivedShoppingList); //works

        processTickedCheckBoxes();

        btnMinus.setOnClickListener(new View.OnClickListener() { // decrement (short push)
            @Override
            public void onClick(View v) {
                decreaseAmountBy(1);
            }
        });
        btnMinus.setOnLongClickListener(new View.OnLongClickListener() { // remove 10 units (long push)
            @Override
            public boolean onLongClick(View v) {
                decreaseAmountBy(10);
                return true;
            }
        });

        btnPlus.setOnClickListener(new View.OnClickListener() { // increment (short push)
            @Override
            public void onClick(View v) {
                increaseAmountBy(1);
            }
        });
        btnPlus.setOnLongClickListener(new View.OnLongClickListener() { // add 10 units (long push)
            @Override
            public boolean onLongClick(View v) {
                increaseAmountBy(10);
                return true;
            }
        });

        /*btnMinus.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                receivedShoppingList.remove(0);         // for testing, will be changed later
                ShoppingList.printList(receivedShoppingList);
            }
        });*/

        btnCancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent shoppingListIntent = new Intent(TransferMenu.this, ShoppingList.class);
                SharedPreferences shPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
                SharedPreferences.Editor prefEdit = shPrefs.edit();
                Gson gson = new Gson();
                String arrInJsonForm = gson.toJson(receivedShoppingList);
                prefEdit.putString(LIST_VIEW_SHARED_PREFS_KEY, arrInJsonForm);
                prefEdit.commit();
                startActivity(shoppingListIntent);
            }
        });

        btnSelectDate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Calendar calendar = Calendar.getInstance();
                int day = calendar.get(Calendar.DAY_OF_MONTH);
                int month = calendar.get(Calendar.MONTH);
                int year = calendar.get(Calendar.YEAR);

                DatePickerDialog dpDiag = new DatePickerDialog(TransferMenu.this,
                        android.R.style.Theme_Holo_Light_Dialog,
                        datePickerDiagListener,
                        year, month, day);
                dpDiag.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
                dpDiag.show();
            }
        });

        datePickerDiagListener = new DatePickerDialog.OnDateSetListener() {
            @Override
            public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
                viewDate.setText(dayOfMonth + "/" + month + "/" + year);
            }
        };
    }

    private void decreaseAmountBy(int value) {
        amount = amount - value;
        if (amount >= 1) {                               // if the user decrements the amount when it is equal to 1, the amount will be displayed
            viewProductAmount.setText("Amount: " + amount);     // as "N/A" and the amount variable will be equal to 0 until it is incremented
        } else {
            viewProductAmount.setText("Amount: N/A");           // if amount is set to 0, it shows up as N/A
            amount = 0;                                  // in case amount is not applicable, set the variable to 0
        }
    }

    private void increaseAmountBy(int value) {
        amount = amount + value;
        viewProductAmount.setText("Amount: " + amount);
    }

    private void processTickedCheckBoxes() {
        for (int i = 0; i < receivedShoppingList.size(); i++){
            Product product = receivedShoppingList.get(i);
            if (product.checkBoxIsChecked){
                amount = product.instances;
                viewProductName.setText(product.name);
                viewProductAmount.setText(amount);
                while (!btnAddItem.isPressed()){}   // used to pause the loop until the item is added to the user inventory or the action is cancelled

                amount = 0;
                viewProductAmount.setText(amount);
                viewDate.setText("Expiry Date");
            }
        }
    }

    private void addProductToInventory(Product product) {
    }
}

表字符串:

    public class TableStrings {

    private TableStrings(){}       // empty constructor because this class does not need to be instantiated

    public static final class ShoppingListStrings implements BaseColumns {        // one inner class for each table
        public static final String TABLE_NAME_SHOPPING_LIST = "shoppingList";
        public static final String COLUMN_NAME_SHOPPING_LIST = "productNameShoppingList";
        public static final String COLUMN_AMOUNT_SHOPPING_LIST = "amountShoppingList";
        public static final String COLUMN_TIMESTAMP_SHOPPING_LIST = "timeShoppingList";
    }

    public static final class UserInventoryStrings implements  BaseColumns{
        public static final String TABLE_NAME_USER_INVENTORY = "userInventory";
        public static final String COLUMN_NAME_USER_INVENTORY = "productNameUserInventory";
        public static final String COLUMN_AMOUNT_USER_INVENTORY = "amountUserInventory";
        public static final String COLUMN_TIMESTAMP_USER_INVENTORY = "timeUserInventory";

        public static final String COLUMN_EXPIRATION_DATE_USER_INVENTORY = "expirationDateUserInventory";
    }
}

现在,布局:

活动主.xml:

    <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ImageView
        android:id="@+id/view_img_main_menu"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:src="@drawable/grocery_img_1" />

    <Button
        android:id="@+id/btn_inventory"
        android:layout_width="match_parent"
        android:layout_height="65dp"
        android:layout_below="@id/view_img_main_menu"
        android:text="@string/btn_my_groceries_text"
        style="@style/BtnStyle" />

    <Button
        android:id="@+id/btn_shopping_list"
        android:layout_width="match_parent"
        android:layout_height="65dp"
        android:layout_below="@id/btn_inventory"
        android:text="@string/btn_shopping_list_text"
        style="@style/BtnStyle" />

    <Button
        android:id="@+id/btn_how_to_use"
        android:layout_width="match_parent"
        android:layout_height="65dp"
        android:layout_below="@id/btn_shopping_list"
        android:text="@string/btn_how_to_use_text"
        style="@style/BtnStyle" />

    <Button
        android:id="@+id/btn_credits"
        android:layout_width="match_parent"
        android:layout_height="65dp"
        android:layout_below="@id/btn_how_to_use"
        android:text="@string/btn_credits_text"
        style="@style/BtnStyle" />

    </RelativeLayout>

activity_shopping_list.xml:

    <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    tools:context=".ShoppingList">

    <ImageView
        android:id="@+id/view_img_shopping_list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:src="@drawable/grocery_img_2" />

    <TextView
        android:id="@+id/view_amount"
        style="@style/TextViewStyle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/view_img_shopping_list"
        android:layout_centerInParent="true"
        android:layout_marginStart="10dp"
        android:layout_marginTop="4dp"
        android:gravity="center"
        android:text="@string/amount_default_label"
        android:textSize="25dp" />

    <EditText
        android:id="@+id/edit_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/view_amount"
        android:gravity="center" />


    <LinearLayout
        android:id="@+id/btn_layout_upper"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/edit_text"
        android:layout_marginStart="5dp"
        android:layout_marginTop="1dp"
        android:layout_marginEnd="5dp">

        <Button
            android:id="@+id/btn_minus"
            style="@style/BtnStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/view_title"
            android:layout_weight="1"
            android:text="-"
            android:textSize="20dp" />

        <Button
            android:id="@+id/btn_plus"
            style="@style/BtnStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/view_title"
            android:layout_weight="1"
            android:text="+"
            android:textSize="20dp" />

    </LinearLayout>

    <LinearLayout
        android:id="@+id/btn_layout_lower"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/btn_layout_upper"
        android:layout_marginStart="5dp"

        android:layout_marginEnd="5dp">

        <Button
            android:id="@+id/btn_back"
            style="@style/BtnStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/view_title"
            android:layout_weight="1"
            android:text="@string/btn_inventory_back_label" />

        <Button
            android:id="@+id/btn_add"
            style="@style/BtnStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/view_title"
            android:layout_weight="1"
            android:text="@string/btn_inventory_add_label" />

    </LinearLayout>

    <TextView
        android:id="@+id/view_title"
        style="@style/TextViewStyle"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_below="@id/btn_layout_lower"
        android:layout_centerHorizontal="true"
        android:layout_marginStart="10dp"
        android:layout_marginTop="5dp"
        android:gravity="center"
        android:text="@string/shopping_list_label"
        android:textSize="32dp" />

    <ListView
        android:id="@+id/view_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/view_title"
        android:layout_alignParentStart="true"
        android:layout_alignParentBottom="true"
        android:layout_centerVertical="true"
        android:layout_marginStart="1dp"
        android:layout_marginTop="5dp"
        android:layout_marginBottom="0dp" />

    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentEnd="true"
        android:layout_alignParentBottom="true"
        android:layout_marginStart="312dp"
        android:layout_marginEnd="14dp"
        android:layout_marginBottom="10dp">

        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:id="@+id/btn_float_delete"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="top"
            android:layout_marginStart="16dp"
            android:layout_marginTop="16dp"
            android:layout_marginEnd="16dp"
            android:layout_marginBottom="85dp"
            android:src="@drawable/shopping_list_icon_delete"
            app:layout_anchor="@id/btn_float_save"
            app:fabCustomSize="50dp"
            app:layout_anchorGravity="top" />

        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:id="@+id/btn_float_save"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="left|bottom"
            android:layout_margin="16dp"
            android:src="@drawable/shopping_list_icon_save"
            app:fabCustomSize="50dp" />

    </androidx.coordinatorlayout.widget.CoordinatorLayout>


    </RelativeLayout>

item_shopping_list.xml:

    <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <Button
        android:id="@+id/btn_delete_item"
        style="@style/BtnStyle"
        android:layout_width="35dp"
        android:layout_height="35dp"
        android:textSize="12sp"
        android:text="X" />

    <TextView
        android:id="@+id/view_name_item"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="2dp"
        android:text="empty_item"
        android:layout_toEndOf="@+id/btn_delete_item"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/view_instances_item"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_marginStart="8dp"
        android:layout_marginTop="2dp"
        android:layout_toEndOf="@+id/view_name_item"
        android:text="x amount"
        android:textSize="20sp" />

    <CheckBox
        android:id="@+id/check_box_item"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_alignParentEnd="true"
        android:layout_marginStart="4dp"
        android:layout_marginTop="1dp"
        android:layout_toEndOf="@+id/view_instances_item" />

    </RelativeLayout>

activity_transfer_menu.xml:

    <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".TransferMenu">

    <ImageView
        android:id="@+id/view_img_shopping_list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:src="@drawable/grocery_img_2" />

    <TextView
        android:id="@+id/view_product_name_transfer"
        style="@style/TextViewStyle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/view_img_shopping_list"
        android:layout_centerInParent="true"
        android:layout_marginStart="10dp"
        android:layout_marginTop="4dp"
        android:gravity="center"
        android:text="@string/item_default_label_transfer"
        android:textSize="25dp" />

    <TextView
        android:id="@+id/view_amount_transfer"
        style="@style/TextViewStyle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/view_product_name_transfer"
        android:layout_centerInParent="true"
        android:layout_marginStart="10dp"
        android:layout_marginTop="4dp"
        android:gravity="center"
        android:text="@string/amount_default_label"
        android:textSize="25dp" />


    <LinearLayout
        android:id="@+id/btn_layout_transfer_upper"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/view_amount_transfer"
        android:layout_marginStart="5dp"
        android:layout_marginTop="1dp"
        android:layout_marginEnd="5dp">

        <Button
            android:id="@+id/btn_minus_transfer"
            style="@style/BtnStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/view_title"
            android:layout_weight="1"
            android:text="-"
            android:textSize="20dp" />

        <Button
            android:id="@+id/btn_plus_transfer"
            style="@style/BtnStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/view_title"
            android:layout_weight="1"
            android:text="+"
            android:textSize="20dp" />
    </LinearLayout>

    <TextView
        android:id="@+id/view_date_transfer"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/btn_layout_transfer_upper"
        android:gravity="center"
        android:text="Expiry Date"
        android:textSize="40sp" />

    <LinearLayout
        android:id="@+id/btn_layout_transfer_lower"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/view_date_transfer"
        android:layout_marginStart="5dp"
        android:layout_marginTop="1dp"
        android:layout_marginEnd="5dp">


        <Button
            android:id="@+id/btn_cancel_transfer"
            style="@style/BtnStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/view_title"
            android:layout_weight="1"
            android:text="Cancel"
            android:textAllCaps="false"
            android:textSize="20dp" />

        <Button
            android:id="@+id/btn_select_date_transfer"
            style="@style/BtnStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/view_title"
            android:layout_weight="1"
            android:text="Select Date"
            android:textAllCaps="false"
            android:textSize="20dp" />

        <Button
            android:id="@+id/btn_add_item_transfer"
            style="@style/BtnStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/view_title"
            android:layout_weight="1"
            android:text="Add item"
            android:textAllCaps="false"
            android:textSize="20dp" />


    </LinearLayout>


    </RelativeLayout>

我怀疑这个问题与数据库有关,因为导致它的布尔值与它没有任何关系,但我包括了这些类以防万一。我尝试了其他人发布的解决方案,例如重建和清理项目,但他们没有解决问题。我将问题追溯到前面提到的 setCheckBoxStateInList() 方法,并在导致它的行中添加了注释。为什么会出现这个错误?

标签: arraylistboolean

解决方案


更多信息在这里,因为我达到了字符限制。

产品对象有一个属性,它跟踪其 CheckBox 的状态(在 setCheckBoxStateInList() 方法中修改此属性会导致崩溃),称为 checkBoxIsChecked。该列表被发送到另一个活动,并且带有勾选复选框的项目应该被添加到另一个数据库。复选框在 ShoppingListAdapter 类中具有侦听器,但在 TransferMenu 活动中,检查是基于 checkBoxIsChecked 属性的值完成的,因此也需要更新。我发现这样做的唯一方法是在 ShoppingList 活动中(在 setCheckBoxStateInList() 方法中)。只要没有将 checkBoxIsChecked 属性设置为 true,当单击保存 FloatingActionButton(带有软盘的按钮)时,TransferMenu 活动就会按预期启动。当其中一个属性设置为 true 时,错误被抛出。我看到的与此错误有关的其他问题与应用程序主题或其他 XML 内容有关,但我没有看到与我遇到的情况类似的情况。如果需要更多代码,请告诉我:

主要活动:

    public class MainActivity extends AppCompatActivity {

    private Button btnInventory;
    private Button btnShopList;

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

        btnInventory = findViewById(R.id.btn_inventory);
        btnShopList = findViewById(R.id.btn_shopping_list);

        btnInventory.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent inventoryIntent = new Intent(MainActivity.this, Inventory.class);
                startActivity(inventoryIntent);
            }
        });

        btnShopList.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent shopListIntent = new Intent(MainActivity.this, ShoppingList.class);
                startActivity(shopListIntent);
            }
        });
    }
`}`

购物清单:

    public class ShoppingList extends AppCompatActivity {

    private EditText editText;
    private TextView viewAmount;
    private Button btnMinus;
    private Button btnPlus;
    private Button btnBack;
    private Button btnAdd;
    private FloatingActionButton btnFloatDelete;
    private FloatingActionButton getBtnFloatSave;

    private SQLiteDatabase shoppingListDB;
    private ShoppingListAdapter listAdapter;
    private ArrayList<Product> productArrayList;
    private int amount = 1;

    public static final String LIST_VIEW_SHARED_PREFS_KEY = "listViewPrefs";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_shopping_list);
        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); // to make the FloatingActionButtons stay fixed when the keyboard goes up.

        ShoppingListDatabaseHelper listDBHelper = new ShoppingListDatabaseHelper(this);
        shoppingListDB = listDBHelper.getWritableDatabase();        // assign a database to shoppingListDB that can be written to

        loadList();
        final ListView shopListView = findViewById(R.id.view_list);
        listAdapter = new ShoppingListAdapter(this, productArrayList, getFullListCursor(), this);
        shopListView.setAdapter(listAdapter);

        editText = findViewById(R.id.edit_text);
        viewAmount = findViewById(R.id.view_amount);
        btnMinus = findViewById(R.id.btn_minus);
        btnPlus = findViewById(R.id.btn_plus);
        btnBack = findViewById(R.id.btn_back);
        btnAdd = findViewById(R.id.btn_add);
        btnFloatDelete = findViewById(R.id.btn_float_delete);
        getBtnFloatSave = findViewById(R.id.btn_float_save);

        viewAmount.setText("Amount: " + amount);

        btnMinus.setOnClickListener(new View.OnClickListener() { // decrement (short push)
            @Override
            public void onClick(View v) {
                decreaseAmountBy(1);
            }
        });
        btnMinus.setOnLongClickListener(new View.OnLongClickListener() { // remove 10 units (long push)
            @Override
            public boolean onLongClick(View v) {
                decreaseAmountBy(10);
                return true;
            }
        });

        btnPlus.setOnClickListener(new View.OnClickListener() { // increment (short push)
            @Override
            public void onClick(View v) {
                increaseAmountBy(1);
            }
        });
        btnPlus.setOnLongClickListener(new View.OnLongClickListener() { // add 10 units (long push)
            @Override
            public boolean onLongClick(View v) {
                increaseAmountBy(10);
                return true;
            }
        });

        btnBack.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent mainActIntent = new Intent(ShoppingList.this, MainActivity.class);
                startActivity(mainActIntent);
            }
        });

        btnAdd.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                addItem();
            }
        });

        btnFloatDelete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                deleteAllItems();
            }
        });
        getBtnFloatSave.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent transferMenuIntent = new Intent(ShoppingList.this, TransferMenu.class);
                transferMenuIntent.putExtra("listReference", productArrayList);
                transferMenuIntent.putExtra("sharedPrefsKey", LIST_VIEW_SHARED_PREFS_KEY);
                startActivity(transferMenuIntent);
            }
        });
    }

    private Cursor getFullListCursor(){
        Cursor fullListCursor = shoppingListDB.query(ShoppingListStrings.TABLE_NAME_SHOPPING_LIST,
                null,
                null,
                null,
                null,
                null,
                ShoppingListStrings.COLUMN_TIMESTAMP_SHOPPING_LIST + " DESC");
        return fullListCursor;
    }

    private void decreaseAmountBy(int value) {
        amount = amount - value;
        if (amount >= 1) {                               // if the user decrements the amount when it is equal to 1, the amount will be displayed
            viewAmount.setText("Amount: " + amount);     // as "N/A" and the amount variable will be equal to 0 until it is incremented
        } else {
            viewAmount.setText("Amount: N/A");           // if amount is set to 0, it shows up as N/A
            amount = 0;                                  // in case amount is not applicable, set the variable to 0
        }
    }

    private void increaseAmountBy(int value) {
        amount = amount + value;
        viewAmount.setText("Amount: " + amount);
    }

    private void addItem() {
        if (editText.getText().toString().trim().length() == 0) {   // if editText is empty, adding items is impossible; trim() is used to avoid users doing tricks to add empty entries
            return;
        }
        String itemStr = editText.getText().toString();
        ContentValues cVals = new ContentValues();          // used to insert grocery item information into the shopping list database
        cVals.put(ShoppingListStrings.COLUMN_NAME_SHOPPING_LIST, itemStr);
        if (amount > 0){
            cVals.put(ShoppingListStrings.COLUMN_AMOUNT_SHOPPING_LIST, amount);
        } else if (viewAmount.getText().toString() == "Amount: N/A"){
            cVals.put(ShoppingListStrings.COLUMN_AMOUNT_SHOPPING_LIST, amount - 1);
        } else {
            return;
        }
        shoppingListDB.insert(ShoppingListStrings.TABLE_NAME_SHOPPING_LIST, null, cVals);
        listAdapter.changeCursor(getFullListCursor());

        Product product = new Product(itemStr, amount, false);
        listAdapter.add(product);

        editText.setText("");
        amount = 1;
        viewAmount.setText("Amount: " + amount);

        saveList();
        printList(productArrayList);
        //editText.getText().clear();
    }

    private void deleteAllItems(){
        listAdapter.clear();
        shoppingListDB.execSQL("DELETE FROM " + ShoppingListStrings.TABLE_NAME_SHOPPING_LIST);
        Cursor cursCheck = getFullListCursor();
        if (!cursCheck.moveToFirst()){
            System.out.println("Shopping List Database is empty");
        }
        saveList();

        printList(productArrayList);
    }

    // Public methods


    public void saveList(){
        //SharedPreferences shPrefs = ShoppingList.this.getSharedPreferences(LIST_VIEW_SHARED_PREFS_KEY, Context.MODE_PRIVATE);
        SharedPreferences shPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
        SharedPreferences.Editor prefEdit = shPrefs.edit();
        Gson gson = new Gson();
        String arrInJsonForm = gson.toJson(productArrayList);
        prefEdit.putString(LIST_VIEW_SHARED_PREFS_KEY, arrInJsonForm);
        prefEdit.commit();
    }

    public void loadList(){
        //SharedPreferences shPrefs = ShoppingList.this.getSharedPreferences(LIST_VIEW_SHARED_PREFS_KEY, Context.MODE_PRIVATE);
        SharedPreferences shPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
        Gson gson = new Gson();
        String arrInJsonForm = shPrefs.getString(LIST_VIEW_SHARED_PREFS_KEY, null);
        Type type = new TypeToken<ArrayList<Product>>() {}.getType();
        productArrayList = gson.fromJson(arrInJsonForm, type);
        if (productArrayList == null){
            productArrayList = new ArrayList<Product>();
        }
    }

    public void setCheckBoxStateInList(int index, boolean checkBoxState){
        productArrayList.get(index).checkBoxIsChecked = checkBoxState;      // This line throws the error. If checkBoxState is replaced with false, no error is thrown.
                                                                              // If it is replaced with true, the error is thrown as well
        saveList();
    }

    // Testing

    public static void printList(ArrayList<Product> productList){
        System.out.println("List:");
        for (int i = 0; i < productList.size(); i++){
            Product product = productList.get(i);
            System.out.print(" - " + product.name + " " + product.instances + " (ID: " + product.productID + "); box is ");
            if (product.checkBoxIsChecked){
                System.out.println("checked");
            } else {
                System.out.println("not checked");
            }
        }
        System.out.println("End of list\n");
    }

}

这是错误:

    E/atusapplicatio: Invalid ID 0x0000000b.
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.grocerystatusapplication, PID: 20040
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.grocerystatusapplication/com.example.grocerystatusapplication.TransferMenu}: android.content.res.Resources$NotFoundException: String resource ID #0xb
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3344)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3488)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2049)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:216)
        at android.app.ActivityThread.main(ActivityThread.java:7506)
        at java.lang.reflect.Method.invoke(Nati
I/Process: Sending signal. PID: 20040 SIG: 9

推荐阅读