Сколько действий против фрагментов?

185

Вступление:

Базовый шаблон "Fragments Tutorial" выглядит примерно так:

  1. На планшете есть список слева, подробности справа.
  2. Оба они Fragmentsнаходятся в одном и том же месте Activity.
  3. На телефоне есть список Fragmentв одном Activity.
  4. Запустите новый Activityс деталями Fragment.

(например, API 3.0 Фрагментов Android 3.0 от Дайан Хэкборн и Руководство по API Фрагментов )

На обоих устройствах функциональность есть в Fragments. (просто)

На планшете всего приложения 1Activity , на телефоне их многоActivities .


Вопросы:

  • Есть ли причина разделять телефонное приложение на множество Activities?

Одна из проблем этого метода заключается в том, что вы дублируете много логики в основном планшете Activityи в отдельном телефоне Activities.

  • Не будет ли проще сохранить модель 1 Activity в обоих случаях, используя одну и ту же логику включения Fragmentsи выключения (просто используя другую схему)?

Таким образом, большая часть логики находится в Fragmentsсамих себе, и существует только одно Activity- меньшее дублирование кода.

Кроме того, я читал о том ActionBarSherlock, что он лучше всего работает Fragmentsвместо Activities(но я еще не работал с ним).

Упрощены ли учебники, или я упустил что-то важное в этом подходе?


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

Некоторые ссылки на связанные вопросы:


Обновления

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

Также найдена интересная статья ребят на площади, которую стоит прочитать:

Ричард Ле Мезурье
источник
38
+1 за отличный и хорошо написанный вопрос.
Сиддхарт Леле
это то, что мне сейчас очень больно, сейчас я работаю над приложением, дизайн которого включает в себя много фрагментов, и оно будет доступно как на телефоне, так и на планшете, я ищу средний путь, но пока не могу найти ...
Nixit Patel
1
Я честно имею в виду не обижаться, но я думаю, что вы просто приняли то, что хотели услышать, а не реальный ответ. Google не рекомендует ответ Scuba, и пост в блоге, который мне нравится объяснять, почему.
pjco
1
@pjco В частности, я не согласен с наличием onItemSelected()метода в Деятельности. В моем "реальном" приложении у меня есть много списков и подсписков. Этот шаблон предполагает, что моя вкладка Activity должна иметь onItemSelected()метод для обработки каждого из списков. Кроме того, в каждой деятельности телефона должна быть одинаковая логика, дублирующаяся внутри каждой из них. ИМХО, гораздо лучше поместить логику «Выбранный элемент» в каждый фрагмент - дублирования нет, и я предпочитаю такой способ структурирования кода. Я надеюсь, что это поможет
Ричард Ле Мезурье
2
Я в настоящее время одержим этой дилеммой на работе. Фрагменты загружаются намного быстрее, чем запуск новых действий, поэтому я начал внедрять единую архитектуру действий. Однако я столкнулся с проблемой, которая заключается в том, что я не могу найти хороший способ поддержки многофрагментных конфигураций без каких-либо хакерских действий. Смотрите этот вопрос .
theblang

Ответы:

41

Я согласен, что учебники очень упрощены. Они просто вводят, Fragmentsно я не согласен с предложенной моделью.

Я также согласен с тем, что не стоит дублировать логику вашего приложения во многих видах деятельности (см. « Принцип СУХО» в Википедии ).


Я предпочитаю шаблон, используемый ActionBarSherlockприложением Fragments Demo ( скачать здесь и исходный код здесь ). Демонстрация, которая наиболее близко соответствует учебнику, упомянутому в вопросе, называется «Макет» в приложении; или FragmentLayoutSupportв исходном коде.

В этой демонстрации логика была перемещена из Activityи в Fragment. TitlesFragmentФактически содержит логику для изменения фрагментов. Таким образом, каждое действие очень просто. Дублировать многие очень простые действия, в которых нет логики внутри действий, сделать это очень просто.

Поместив логику во фрагменты, нет необходимости писать код более одного раза ; он доступен независимо от того, в какую деятельность помещен фрагмент. Это делает его более мощным паттерном, чем тот, который предлагается в базовом уроке.

    /**
    * Helper function to show the details of a selected item, either by
    * displaying a fragment in-place in the current UI, or starting a
    * whole new activity in which it is displayed.
    */
    void showDetails(int index)
    {
        mCurCheckPosition = index;

        if (mDualPane)
        {
            // We can display everything in-place with fragments, so update
            // the list to highlight the selected item and show the data.
            getListView().setItemChecked(index, true);

            // Check what fragment is currently shown, replace if needed.
            DetailsFragment details = (DetailsFragment) getFragmentManager()
                .findFragmentById(R.id.details);
            if (details == null || details.getShownIndex() != index)
            {
                // Make new fragment to show this selection.
                details = DetailsFragment.newInstance(index);

                // Execute a transaction, replacing any existing fragment
                // with this one inside the frame.
                FragmentTransaction ft = getFragmentManager()
                    .beginTransaction();
                ft.replace(R.id.details, details);
                ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
                ft.commit();
            }

        }
        else
        {
            // Otherwise we need to launch a new activity to display
            // the dialog fragment with selected text.
            Intent intent = new Intent();
            intent.setClass(getActivity(), DetailsActivity.class);
            intent.putExtra("index", index);
            startActivity(intent);
        }
    }

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

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

Стивен Ашерсон
источник
Спасибо за исчерпывающий ответ - я посмотрел демоверсии ABS и думаю, что там много хорошего кода. Вместо этого я попытаюсь перенести большую часть своей логики в фрагменты
Ричард Ле Мезурье,
Демонстрационное приложение перенесено сюда: play.google.com/store/apps/…
Филипп Е.
Я думаю, что шаблон, который вы описываете, взят из исходного кода Google: android-developers.blogspot.com/2011/02/… Я думаю, что ActionBarSherlock просто перенес демонстрационный код Google для использования классов ABS.
Дан Дж
17

Я думаю, что вы на правильном пути. (И да, учебники слишком упрощены).

В макете планшета вы можете использовать одну операцию и поменять местами фрагменты (в нескольких «панелях»). Находясь в макете телефона, вы можете использовать новую активность для каждого фрагмента.

Вот так:

введите описание изображения здесь

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

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

Так что, если у пользователя есть планшет, который вы бы использовали, MyMultiPaneFragActivityили что-то подобное. Это действие отвечает за управление обратными вызовами от фрагментов и маршрутизацией намерений к правильному фрагменту (например, поисковое намерение)

Если у пользователя есть телефон, вы можете использовать обычную активность с очень небольшим кодом и расширять его MyBaseSingleFragActivityили что-то подобное. Эти действия могут быть очень простыми, 5-10 строк кода (может быть, даже меньше).

Сложная часть заключается в маршрутизации намерений и еще много чего. * (Редактировать: см. Ниже).

Я думаю, что причина этого рекомендуемого способа состоит в том, чтобы сохранить память и уменьшить сложность и связь. Если вы меняете фрагменты, они FragmentManagerсохраняют ссылку на этот фрагмент для обратного стека. Это также упрощает то, что должно быть «запущено» для пользователя. Эта настройка также разделяет представления, макет и логику в фрагменте из жизненного цикла действия. Таким образом, фрагмент может существовать в одном действии, наряду с другим фрагментом (двухпанельным), или в трехпанельном действии и т. Д.

* Одним из преимуществ регулярной намеренной маршрутизации является то, что вы можете явно запускать Activity из любого места в бэк-стеке. Один пример может быть в случае результатов поиска. (MySearchResults.class).

Прочитайте здесь для получения дополнительной информации:

http://android-developers.blogspot.com/2011/09/preparing-for-handsets.html

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

pjco
источник
Преимущество MySearchResults - вы предлагаете по-разному реагировать на это намерение в зависимости от телефона или планшета - почему это лучше, чем одно действие, которое отвечает в обоих случаях? Вы предлагаете, на планшете нет регулярной маршрутизации намерений - так что вы все равно должны решить проблему для планшета. Почему бы не использовать это решение на телефоне тоже?
Ричард Ле Мезурье
Преимущество в том, что код вашего планшета может рассчитывать на несколько панелей. Иногда вам захочется изменить несколько панелей с одной целью. Например, результаты поиска слева с подробностями первого элемента в большей панели справа. Этот код не будет переносимым на один макет.
pjco
Почему нормально переключать фрагменты, когда их много, но если виден только 1 фрагмент, я не должен переключаться на другой фрагмент?
Ричард Ле Мезурье
Не уверен, что я понимаю, что вы имеете в виду, но поясню мой комментарий выше: Иногда вы можете захотеть изменить более 1 фрагмента одновременно в многофрагментном макете. Для этого требуется код для изменения 2 фрагментов, который вы не будете использовать повторно в макете с одним фрагментом
pjco
Добро пожаловать :) пожалуйста, подпишите или примите, если считаете, что ответ полезен
pjco
6

Вот ответ Рето Мейера относительно того же самого, взятый из этого видео курса по основам Android от Udacity .

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

  • Наличие единственной монолитной активности увеличивает сложность вашего кода, затрудняя его чтение, тестирование и обслуживание.
  • Делает создание и управление фильтрами намерений намного сложнее.
  • Увеличивает риск плотного соединения независимых компонентов.
  • Повышает вероятность появления угроз безопасности, если одно действие включает в себя как конфиденциальную информацию, так и информацию, которой можно безопасно делиться.

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

Адитья Найке
источник
интересно, что название видео «Почему мы не используем только фрагменты»
Ричард Ле Мезурье
это хороший подход, я сталкиваюсь с множеством проблем, связанных с несколькими фрагментами действий ... возможно, реальный
опыт
4

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

В шаблоне master-detail есть два действия. Один показывает оба фрагмента на больших экранах и только «главный» фрагмент на меньших экранах. Другой показывает фрагмент «детализации» на экранах меньшего размера.

Ваша логика детализации должна быть связана с фрагментом детализации. Следовательно, нет дублирования кода, связанного с логикой детализации между действиями - операция детализации просто отображает фрагмент детализации, возможно передавая данные из Intentдополнительных.

Также, что я читал о ActionBarSherlock, так это то, что он лучше всего работает с Фрагментами вместо Активов (но я еще не работал с ним).

ActionBarSherlock не имеет ничего общего с фрагментами, чем встроенная панель действий, так как ActionBarSherlock является чисто задним портом встроенной панели действий.

CommonsWare
источник
Что вы думаете об идее единого занятия?
theblang
@mattblang: Пока вы правильно настроили навигацию, с этим проблем нет.
CommonsWare
1
Я попытался выполнить рефакторинг для одной архитектуры действий, потому что замена фрагмента намного быстрее, чем запуск нового действия с тем же фрагментом в нем. Я чувствую, что сталкиваюсь со слишком многими препятствиями, как это . Большинство примеров, которые я нахожу в Интернете, особенно для многофрагментных конфигураций, таких как master-detail, не используют ни одного действия. Таким образом, я нахожусь в некоторой дилемме.
theblang
0

Ссылаясь на 1-й вопрос «Есть ли причина разделить приложение телефона на множество видов деятельности?» - Да. это просто сводится к доступному пространству, планшет предоставляет больше возможностей для разработчиков, что позволяет разработчикам размещать больше на одном экране. Android сообщает нам, что деятельность может предоставить экран . Итак, то, что вы можете сделать с одним большим экраном на планшете, это то, что, возможно, придется распределить по нескольким экранам на телефоне, потому что не хватает места для всех фрагментов.

EFlisio
источник
1-е предложение - «Деятельность - это компонент приложения, который предоставляет экран, с которым пользователи могут взаимодействовать, чтобы что-то делать». Я вижу ошибку в своем первоначальном утверждении, я не хотел ставить «это другой экран»,
EFlisio