Предотвращение / отлов ошибки «IllegalArgumentException: параметр должен быть потомком этого представления» - PullRequest
51 голосов
/ 18 августа 2011

У меня есть ListView с некоторыми фокусируемыми компонентами внутри (в основном EditText с). Да, я знаю, что это не совсем рекомендуется, но в целом почти все работает нормально, и фокус направлен на то, что нужно (с некоторыми изменениями, которые мне пришлось кодировать). В любом случае, моя проблема в том, что при прокрутке списка пальцем и странном использовании трекбола при отображении клавиатуры IME возникает странное состояние гонки. Что-то должно выйти за пределы и быть переработано, и в этот момент метод offsetRectBetweenParentAndChild() должен запустить и выбросить IllegalArgumentException.

Проблема в том, что это исключение выдается за пределы любого блока, в который я могу вставить try / catch (насколько я знаю). Таким образом, есть два правильных решения этого вопроса:

  1. Кто-то знает , почему выдается это исключение и как его предотвратить
  2. Кто-то знает, как разместить блок try / catch где-нибудь, чтобы хотя бы выжить моему приложению. Насколько я знаю, проблема в фокусе, так что это определенно не должно убивать мое приложение (что и делает). Я попытался переопределить методы ViewGroup, но эти два offset* метода помечены как окончательные.

Трассировка стека:

08-17 18:23:09.825: ERROR/AndroidRuntime(1608): FATAL EXCEPTION: main
08-17 18:23:09.825: ERROR/AndroidRuntime(1608): java.lang.IllegalArgumentException: parameter must be a descendant of this view
08-17 18:23:09.825: ERROR/AndroidRuntime(1608):     at android.view.ViewGroup.offsetRectBetweenParentAndChild(ViewGroup.java:2633)
08-17 18:23:09.825: ERROR/AndroidRuntime(1608):     at android.view.ViewGroup.offsetDescendantRectToMyCoords(ViewGroup.java:2570)
08-17 18:23:09.825: ERROR/AndroidRuntime(1608):     at android.view.ViewRoot.scrollToRectOrFocus(ViewRoot.java:1624)
08-17 18:23:09.825: ERROR/AndroidRuntime(1608):     at android.view.ViewRoot.draw(ViewRoot.java:1357)
08-17 18:23:09.825: ERROR/AndroidRuntime(1608):     at android.view.ViewRoot.performTraversals(ViewRoot.java:1258)
08-17 18:23:09.825: ERROR/AndroidRuntime(1608):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1859)
08-17 18:23:09.825: ERROR/AndroidRuntime(1608):     at android.os.Handler.dispatchMessage(Handler.java:99)
08-17 18:23:09.825: ERROR/AndroidRuntime(1608):     at android.os.Looper.loop(Looper.java:130)
08-17 18:23:09.825: ERROR/AndroidRuntime(1608):     at android.app.ActivityThread.main(ActivityThread.java:3683)
08-17 18:23:09.825: ERROR/AndroidRuntime(1608):     at java.lang.reflect.Method.invokeNative(Native Method)
08-17 18:23:09.825: ERROR/AndroidRuntime(1608):     at java.lang.reflect.Method.invoke(Method.java:507)
08-17 18:23:09.825: ERROR/AndroidRuntime(1608):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
08-17 18:23:09.825: ERROR/AndroidRuntime(1608):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
08-17 18:23:09.825: ERROR/AndroidRuntime(1608):     at dalvik.system.NativeStart.main(Native Method)

Ответы [ 15 ]

1 голос
/ 11 июля 2016

Если ни одно из предложенных здесь решений не применимо к вам ...

Я столкнулся с подобной ошибкой и заметил, что устройства моих пользователей сообщали о ней (после сбоя) без какого-либо четкого объяснения ее причины (аналогично журналу, показанному в вопросе) - более конкретно, только проблема произошло на устройствах Samsung Galaxy (включая S6) (но не на устройствах Nexus или других, именно поэтому в ходе моего тестирования не было выявлено этой проблемы). Итак, во-первых, стоит проверить, относится ли проблема к конкретному устройству.

Что я обнаружил позже, так это то, что при нажатии кнопки «Назад», когда виртуальная клавиатура Samsung отображалась в текстовом поле, приложение вылетало, вызывая эту ошибку - но не всегда!

Действительно, текстовое поле, вызывающее сбой, также отображалось в просмотре прокрутки с включенным fillViewPort = "true".

Я обнаружил, что удаление параметра fillViewPort из представления прокрутки не будет конфликтовать с отображением / скрытием клавиатуры Samsung. Я подозреваю, что проблема отчасти связана с тем фактом, что клавиатуры Samsung отличаются от виртуальных клавиатур от стандартных клавиатур Nexus, поэтому проблема возникла только у части моих пользователей, и она зависала только на их устройствах.

Как правило, и если ни одно из других решений, предложенных здесь, не применимо к вам, я бы проверил, относится ли проблема к конкретному устройству, а также попытался бы упростить представление, над которым я работаю, до тех пор, пока не найду компонент "виновника" "(компонент и представление, которое, я должен добавить, не было зарегистрировано в журналах сбоев, поэтому я наткнулся только на конкретное представление, вызвавшее проблему случайно!).

Извините, я не могу быть более конкретным, но я надеюсь, что это даст некоторые подсказки для дальнейшего расследования, если кто-то столкнется с подобной, но необъяснимой проблемой.

1 голос
/ 15 мая 2015

В моем случае это было связано с windowSoftInputMode="adjustPan", listView и editText в элементе списка (представление заголовка).

Чтобы исправить это, я вызываю метод скрытой программной клавиатуры до завершения действия.

public void hideKeyboard(Activity activity) {
    InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
    View focusView = activity.getCurrentFocus();
    if (focusView != null) {
        inputMethodManager.hideSoftInputFromWindow(focusView.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
    }
}
0 голосов
/ 18 декабря 2016

Я использую RecyclerView, и ни одно из представленных решений не сработало. Я получил ошибку при удалении предметов.

Что работало, так это переопределение адаптера в onItemDismiss (int position), так что он сначала выполняет notifyDataSetChanged () перед удалением элемента, а затем выполняет notifyItemRemoved (position) после удаления элемента. Как это:

// Adapter code
@Override
public void onItemDismiss(int position) {
    if (position >= 0 && getTheList() != null && getTheList().size() > position) {
        notifyDataSetChanged();  // <--- this fixed it.
        getTheList().remove(position);
        scrollToPosition(position);
        notifyItemRemoved(position);
    }
}

Также выполните переопределение 'removeAt (int position)' в TabFragment, чтобы вызвать новый код очистки, например:

// TabFragment code
@Override
public void removeAt(int position) {
    mAdapter.onItemDismiss(position);
    mAdapter.notifyItemRemoved(position); // <--- I put an extra notify here too
}
0 голосов
/ 22 июня 2016

На основе ответа @Bruce, может исправить ошибку с помощью переработчика:

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        View currentFocus = ((Activity)context).getCurrentFocus();
        if (currentFocus != null) {
            currentFocus.clearFocus();
        }
}
0 голосов
/ 11 июля 2014

Мой ответ связан с большинством ответов здесь, но я просто хотел добавить, что в моем случае этот сбой произошел из-за удаления строки с текстом редактирования, который в данный момент имел фокус.

Итак, все, что я сделал, это переопределил метод удаления адаптера и запросил, содержит ли удаленная строка текущее редактирование фокуса, и, если это так, очистите фокус.

Это решило это для меня.

...