Почему Android меняет значение EditTexts с тем же идентификатором?

У меня есть фрагмент, содержащий LinearLayout, где различные элементы раздуты в зависимости от некоторой бизнес-логики. В этих элементах содержится EditText. Когда у меня есть несколько элементов с различным содержимым, и я отсоединяю / прикрепляю фрагмент, все EditTexts каким-то образом получают одинаковый текст. Это происходит только до тех пор, пока EditText имеет идентификатор в файле макета.

Почему это происходит? Есть ли другой способ предотвратить это, кроме удаления идентификатора? Я хотел бы использовать findViewById для моих раздутых элементов, чтобы получить доступ к представлениям, а не к ошибкам getChildAt .

Я создал минималистический пример, чтобы продемонстрировать проблему на https://github.com/rodja/EditTextValueProblem

Solutions Collecting From Web of "Почему Android меняет значение EditTexts с тем же идентификатором?"

Его можно просто установить, установив android:saveEnabled="false" в определении Layout EditTexts. Конечно, вам нужно убедиться, что содержимое сохранено / восстановлено самостоятельно. Так что это неинтуитивная работа – но это работает для моего дела. Тем не менее, все это выглядит как ошибка Android:

Хорошей особенностью системы компоновки Android является то, что

Идентификатор не должен быть уникальным во всем дереве […]

Как указано в документации на Android . Это значительно упрощает использование кода и компоновки и в значительной степени используется разработчиками. Я думаю, что реализация состояния экземпляра save / restore для представлений использует идентификатор вида как ключ для хранения его состояния, поэтому он полагается на уникальность во всем дереве . WTF?

Обновить

Я добавил ListView к примеру в GitHub, который демонстрирует, что ListView почти наверняка использует аналогичное обходное решение, чтобы предотвратить использование EditTexts в этой проблеме. Как видно, текст, который вводится в EditText внутри ListView, не восстанавливается автоматически.

Существует другая возможность, просто измените идентификатор текста редактирования, например,

 mEditText.setId((parentView.getId()+editTextPosition+someFinalNumber)); 

Или, если это EditText внутри пользовательского макета:

 mEditText.setId((this.getId()+someFinalNumber)); 

Таким образом, все EditTexts будут иметь другой идентификатор, и текст будет восстановлен правильно.

Я думаю, это связано с тем, что состояние всех EditTexts с идентификатором автоматически сохраняется. Если вы выполните FragmentTransactions или измените ориентацию, активность будет воссоздана, и состояние EditTexts будет восстановлено, так как все они имеют одинаковый идентификатор, все они получат одинаковое значение. Мое первое предложение будет переопределять методы onRestoreInstanceState и onSaveInstanceState вашей деятельности следующим образом:

 @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { // super.onRestoreInstanceState(savedInstanceState); <-- Make sure this is at least commented out or deleted altogether } @Override protected void onSaveInstanceState(Bundle outState) { // super.onSaveInstanceState(outState); <-- Make sure this is at least commented out or deleted altogether } 

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

В любом случае у вас есть проблемы с вашими руками, с которыми не так много приходится иметь дело, использует ListView вместо LinearLayout no option? Потому что я уверен, что использование ListView также решит проблему.