список ArrayList.Удалить не работает при первом вызове

у меня есть ArrayList<String> который я использую для хранения PackageInfo (пример элемента в arraylist - " com.скайп.рейдер.)"

арралист инициализируется следующим образом:

    private List<String> pkgs;

И В Классе Consturctor

    pkgs = new ArrayList<>();

когда я взываю pkgs.remove(String), он не работает, но когда я неоднократно пытаюсь удалить, он в конечном итоге работает.

Heres, как я тестирую, если удаление сработало( я отредактировал код, чтобы он читал больше легко)


private void togglePackage(String selectedPackage,CheckBox chk_app){

    String m_pkg = selectedPackage.toString(); //redundant .toString()
    boolean checked = !chk_app.isChecked(); //checkbox boolean toggle

    if (checked && !pkgs.contains(m_pkg)) { //if not already in arraylist
        pkgs.add(m_pkg); //adding the newly checked package
    } else if (!checked && pkgs.contains(m_pkg)) { //if it needs to be removed
        pkgs.remove(m_pkg); //<-----------------------This works around the 3rd time i press the checkbox
    }
    //Here i check if the string was actually removed from the arrylist
    //This following code will not be in production, i just used it for testing

    if (pkgs.contains(m_pkg)) {
        if (checked) {
            chk_app.setChecked(checked);//Success
        } else {
            chk_app.setChecked(!checked);//Failure
        }
     } else {
         if (!checked) {
            chk_app.setChecked(checked);//Success
         } else {
            chk_app.setChecked(!checked);//Failure
         }
     }
 }

вот неотредактированное событие onclick

RelativeLayout rl_container = (RelativeLayout) child.findViewById(R.id.rl_container);
               rl_container.setTag(pkg);
               rl_container.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        String m_pkg = v.getTag().toString();
                        System.out.println("Pkg = "+m_pkg);
                        boolean checked = !chk_app.isChecked();
                        if (checked && !pkgs.contains(m_pkg)) {
                            pkgs.add(m_pkg);
                            System.out.println("Adding " + m_pkg);
                        } else if (!checked && pkgs.contains(m_pkg)) {
                            pkgs.remove(m_pkg);
                            System.out.println("Removing " + m_pkg);
                        }


                        if (pkgs.contains(m_pkg)) {
                            if (checked) {
                                System.out.println("Success");
                                chk_app.setChecked(checked);
                            } else {
                                System.out.println("Fail");
                                chk_app.setChecked(!checked);
                            }

                        } else {
                            if (!checked) {
                                System.out.println("Success");
                                chk_app.setChecked(checked);
                            } else {
                                System.out.println("Fail");
                                chk_app.setChecked(!checked);
                            }
                        }


                    }
                });

в качестве примера я включил содержимое arraylists, которое я получил, повторяя список. а также вывод журнала моих тестов

список содержание:

com.sbg.mobile.phone

com.google.android.youtube 

com.e8tracks 

com.vlingo.midas 

com.google.android.googlequicksearchbox 

com.truecaller 

Logcat выводится из неотредактированного кода, когда я пытаюсь отменить выбор " com.sbg.мобильный.телефон"

12-18 10:37:25 ViewPostImeInputStage ACTION_DOWN
12-18 10:37:25 Pkg = com.sbg.mobile.phone
12-18 10:37:25 Removing com.sbg.mobile.phone
12-18 10:37:25 Fail
12-18 10:37:28 ViewPostImeInputStage ACTION_DOWN
12-18 10:37:28 Pkg = com.sbg.mobile.phone
12-18 10:37:28 Removing com.sbg.mobile.phone
12-18 10:37:28 Fail
12-18 10:37:30 ViewPostImeInputStage ACTION_DOWN
12-18 10:37:31 Pkg = com.sbg.mobile.phone
12-18 10:37:31 Removing com.sbg.mobile.phone
12-18 10:37:31 Fail
12-18 10:37:32 ViewPostImeInputStage ACTION_DOWN
12-18 10:37:32 Pkg = com.sbg.mobile.phone
12-18 10:37:32 Removing com.sbg.mobile.phone
12-18 10:37:32 Fail
12-18 10:37:33 ViewPostImeInputStage ACTION_DOWN
12-18 10:37:33 Pkg = com.sbg.mobile.phone
12-18 10:37:33 Removing com.sbg.mobile.phone 
12-18 10:37:33 Success

PS. Это мой первый вопрос, так что будь осторожен. Я также был бы признателен за любую совет о том ,как улучшить задаваемые вопросы, я попытался включить всю необходимую информацию, но если вам нужно что-нибудь еще, пожалуйста, дайте мне знать.

3 ответов


Я думаю, что это может быть проблемой, потому что ArrayList дает вам возможность хранить равные объекты несколько раз. Возможно, это хорошая идея использовать HashSet<String> вместо?

 private Set<String> pkgs;

рассмотрим поведение ArrayList по умолчанию:

ArrayList строк имеет 5 элементов. Если вы удалите элемент на 2-й позиции, то arraylist станет набором из 4 элементов и 3-го элемента теперь на 2-й позиции. Теперь, когда вы удаляете 5-й элемент, но его положение изменилось.

поэтому используйте Arraylist hashmap, и когда вы хотите удалить элементы из arraylist, вы должны перебрать все элементы arraylist и удалить из него конкретный элемент.

или если вы хотите только проверенные элементы, когда происходит какое-то событие (например, нажатие кнопки), то получите только те проверенные элементы из адаптера списка.


проблема в вашем состоянии. Условие должно быть как:

    if (checked) {
        if (!pkgs.contains(m_pkg)) {
            pkgs.add(m_pkg);
        }
    } else {
        if (pkgs.contains(m_pkg)) {
            pkgs.remove(m_pkg);
        }
    }

вы можете обратиться к ссылкам:

добавление / удаление строк в ArrayList по флажку

как обрабатывать флажок ischecked и unchecked событие в android