Шаблоны Android: счетчик, в котором каждый элемент запускает другое действие

#android #design-patterns #android-activity #spinner #maintainability

#Android #дизайн-шаблоны #android-активность #счетчик #удобство обслуживания

Вопрос:

Я пытаюсь создать сложную форму, в которой почти все элементы являются необязательными. Он начинается всего с одного поля и кнопки «добавить элемент». Когда вы нажимаете добавить, в форме отображается Spinner один из типов элементов, которые вы можете добавить в форму (местоположение, фотография, подробная заметка, временная метка, отличная от «сейчас», и т.д.). Когда вы выбираете элемент, он запускает Activity , и с каждым элементом по-разному связано Activity .

Кроме того, каждый выбор будет содержать несколько битов данных, которые было бы неплохо каким-то образом сохранить «с помощью» Activity :

  • Значок и отображаемое имя в Spinner
  • Ключ для хранения данных в БД (а также для передачи в веб-сервис)
  • Макет для отображения результата в исходной форме (т. Е. миниатюра для фотографии, широта для местоположения и т.д.)

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

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

Ответ №1:

Несколько советов…

  1. Модульные тесты предотвратят «открепление» 🙂

  2. Когда каждый из них Activity получит необходимую информацию от пользователя, вызовите Activity#SetResult() с Intent , содержащим ваши данные для каждого типа. Intent поддерживает все Bundle методы, поэтому вы можете устанавливать различные типы данных по мере необходимости.

  3. Для поддержки # 2 убедитесь, что вы используете Activity#startActivityForResult(Intent,int) для его запуска, и прослушайте результат в Activity#onActivityResult(int,Intent)

  4. Я бы, вероятно, сохранил список доступных типов «элементов» для использования с SpinnerAdapter (например, ArrayList<Class<? extends AbstractFormElement>> , и вызывал бы статические методы, такие как .getDisplayName() , .getActivityClass() и т.д., В getView() методе адаптера, Чтобы определить, что отображать и какое действие запускать.

    Таким образом, ваш список фактически будет содержать такие вещи, как { MyPhotoElement.class, MyTextElement.class, MyDateElement.class, ...} ).

  5. По мере добавления каждого элемента в форму, добавьте его в ArrayList<AbstractFormElement> , который будет использоваться для резервного копирования другого адаптера для ListView . Этот адаптер отправит раздувание пользовательского макета представления, а также создание ViewHolder в зависимости от типа объекта — это потребует, чтобы у каждого отдельного объекта AbstractFormElement был свой собственный «тип представления», в соответствии с адаптером. Смотрите BaseAdapter#getItemViewType(int) и связанные getViewTypeCount() с ними.

    Стоит отметить, что для них потребуются разные типы представлений только в том случае, если один из них не может быть преобразован в другой… Например, если у вас есть два «элемента», которым нужно отображать только строку текста в списке, они оба могут использовать тип представления «только текст». Аналогично, два элемента, которые отображают только фотографию или могут легко преобразовываться один в другой (например, значок с подписью или миниатюра фотографии без подписи), могут совместно использовать один тип представления «изображение плюс подпись».

Учитывая вышесказанное, вам на самом деле пришлось бы модифицировать разные файлы, чтобы добавить новый тип (ну, я думаю, технически вы могли бы поместить их все в один файл, как внутренние классы, но на самом деле для этого нет веских аргументов), но если вы правильно выполнили свой интерфейс API, следуете хорошим методам OO и внедряете хорошие модульные тесты, вы значительно сократите количество усилий, необходимых для поиска ошибок — просто потому, что большинство вещей, связанных с добавлением нового типа, на самом деле вызовут ошибку компилятора, если вы сделаете это неправильно. Добавьте к этому тот факт, что надлежащий набор модульных тестов сможет программно добавлять все возможные типы и гарантировать, что все отображается правильно, и у вас должен быть довольно упрощенный процесс для легкой расширяемости 🙂

Это звучит как большая работа, и поначалу это может показаться утомительным и подробным… Но конечный результат на самом деле гораздо более удобен в обслуживании, особенно если ваш список типов элементов будет довольно обширным.

Комментарии:

1. Это именно то, что я искал. В частности, пункт 4. Кажется, я никогда не запоминаю общие подстановочные знаки. Спасибо и за другие ваши советы. Очень подробно, жаль, что я не могу принять его дважды.