notifyDataSetHasChanged() выдает ошибку при использовании внутри TextWatcher.onTextChanged() внутри RecyclerView

Я создаю приложение, которое позволяет пользователю выполнять базовое преобразование числа в реальном времени. Пользователи вводят свой номер в редактируемый текст и выбирают базу с помощью кнопок плюс и минус. Проблема, с которой я столкнулся до сих пор, заключается в обеспечении конвертации в реальном времени. Все editText внутри представления переработчика устанавливают свой текст в BigInteger, который может быть преобразован в зависимости от их базы.

Моя идея состояла в том, чтобы обновить BigInteger, когда пользователь вводит новый номер. Поэтому каждый раз, когда пользователи вводят цифру, я должен иметь возможность обновлять BigInteger, уведомлять точку зрения переработчика о том, что данные изменились, и затем представления редактирования текста должны обновляться автоматически. Вот мой ConvertViewHolder

    public ConvertViewHolder(final View itemView) {
        super(itemView);
        mBaseTextView = (TextView) itemView.findViewById(R.id.baseLabel);
        mEditText = (EditText) itemView.findViewById(R.id.numberEditText);
        mMinusButton = (Button) itemView.findViewById(R.id.minusButton);
        mPlusButton = (Button) itemView.findViewById(R.id.plusButton);
        mRemoveButton = (ImageButton)itemView.findViewById(R.id.removeButton);

        mMinusButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (mRoot.get(getPosition()) > MIN_BASE) {
                    mRoot.set(getPosition(), (mRoot.get(getPosition()) - 1));
                    notifyDataSetChanged();
                }
            }
        });

        mPlusButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (mRoot.get(getPosition()) < MAX_BASE){
                    mRoot.set(getPosition(), (mRoot.get( getPosition() ) +1));
                    notifyDataSetChanged();
                }
            }
        });

        mRemoveButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mRoot.remove(getPosition());
                notifyDataSetChanged();
            }
        });

        mEditText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            }

            @Override
            public void afterTextChanged(Editable editable) {
                if(editable.toString().length() > 0) {
                    // change Big Integer
                    mNumber.setDecimalNumber(editable.toString(), mRoot.get( getPosition() ) );
                    // notify change
                    notifyDataSetChanged();
                }
            }
        });


        // TODO: convert numbers at the same time

    }

    public void bindConverter(final int root){
        mBaseTextView.setText(String.format("%02d", root));

        // String containing all the allowed digits depending on base
        String digits = mNumber.getScaleFromBase(root);

        if (root < 11) {
            // filter input
            mEditText.setInputType(InputType.TYPE_CLASS_NUMBER |
                    InputType.TYPE_TEXT_FLAG_MULTI_LINE);
            mEditText.setKeyListener(DigitsKeyListener.getInstance(digits));
            mEditText.setSingleLine(false);
            mEditText.setMaxLines(2);

        } else {
            mEditText.setInputType(InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS |
                    InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
            mEditText.setSingleLine(false);
            mEditText.setMaxLines(2);
            mEditText.setImeOptions(EditorInfo.IME_FLAG_NO_ENTER_ACTION);
            // TODO: filter input for base higher than 10
        }

        // set editText to BigInteger displaying it in the correct base
        // i.e. if the BigInteger is "8" it will be displayed as 8 if the base is 10
        // and as 1000 if the base is 2

        mEditText.setText(mNumber.getDecimalNumber(mRoot.get( getPosition() )));
    }
}

Но, очевидно, мне не разрешено вызывать notifySetDataHasChanged внутри TextWatcher.onTextChanged(), так как компилятор выдает мне эту ошибку:

 java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling

что само собой разумеется, но, к сожалению, я не нашел возможного обходного пути.

1 ответ

view.post(

   new Runnable() {

        public void run() { notifyDatasetChanged(); };
   }


);

само за себя:

вызовите этот метод после того, как RecyclerView вычислит макет или прокрутку (в следующем цикле)

больше объяснений:

  • один поток = синхронный поток кода
  • основной поток = петлитель
  • looper = очередь сообщений = runnable = цикл

другое возможное решение??

вызов после выхода из метода просмотра переработчика

Другие вопросы по тегам