Android - мне нужны некоторые пояснения фрагментов против действий и просмотров
В Android API 11+ Google выпустил новый класс под названием Fragment
,
В видео Google предлагает, чтобы, когда это возможно ( ссылка 1, ссылка 2), мы использовали фрагменты вместо действий, но они не объяснили, почему.
Какова цель фрагментов и их возможное использование (кроме некоторых примеров пользовательского интерфейса, которые могут быть легко достигнуты с помощью простых представлений / макетов)?
Мой вопрос о фрагментах:
- Каковы цели использования фрагмента?
- Каковы преимущества и недостатки использования фрагментов по сравнению с использованием действий / представлений / макетов?
Бонусные вопросы:
- Можете ли вы дать некоторые действительно интересные использования для фрагментов? Вещи, которые Google не упомянул в своих видео?
- Как лучше всего общаться между фрагментами и действиями, которые их содержат?
- Что нужно помнить, когда вы используете фрагменты? Какие-нибудь советы и предупреждения из вашего опыта?
16 ответов
#1 и #2 каковы цели использования фрагмента и каковы преимущества и недостатки использования фрагментов по сравнению с использованием действий / представлений / макетов?
Фрагменты - это решение Android для создания пользовательских интерфейсов многократного использования. Вы можете достичь некоторых из тех же результатов, используя действия и макеты (например, используя include). Тем не мение; фрагменты подключены к Android API, от HoneyComb и выше. Позвольте мне уточнить;
ActionBar
, Если вам нужны вкладки для навигации по вашему приложению, вы быстро увидите, чтоActionBar.TabListener
интерфейс дает вамFragmentTransaction
в качестве входного аргумента дляonTabSelected
метод. Вы могли бы, вероятно, игнорировать это, и делать что-то еще и умнее, но вы будете работать против API, а не с этим.FragmentManager
обрабатывает "назад" для вас очень умным способом. Вернуться не означает вернуться к последнему занятию, как к обычным занятиям. Это означает возврат к предыдущему состоянию фрагмента.Вы можете использовать классный
ViewPager
сFragmentPagerAdapter
создавать интерфейсы салфетки.FragmentPagerAdapter
код намного чище, чем обычный адаптер, и он управляет созданием отдельных фрагментов.Ваша жизнь станет намного проще, если вы будете использовать Фрагменты, когда будете пытаться создавать приложения для телефонов и планшетов. Поскольку фрагменты тесно связаны с API-интерфейсами Honeycomb +, вы захотите использовать их и на телефонах для повторного использования кода. Вот где библиотека совместимости пригодится.
Вы даже можете и должны использовать фрагменты для приложений, предназначенных только для телефонов. Если вы думаете о переносимости. я использую
ActionBarSherlock
и библиотеки совместимости для создания "ICS-выглядящих" приложений, которые выглядят одинаково вплоть до версии 1.6. Вы получаете новейшие функции, такие какActionBar
, с вкладками, переполнением, разделенной панелью действий, пейджером и т. д.
Бонус 2
Лучший способ общения между фрагментами - это намерения. Когда вы нажимаете что-то во фрагменте, вы обычно звоните StartActivity()
с данными на нем. Намерение передается всем фрагментам действия, которое вы запускаете.
Фрагмент является частью действия, которое вносит свой собственный интерфейс в это действие. Фрагмент можно рассматривать как подвид деятельности. Где полный экран, с которым взаимодействует пользователь, называется активностью. Деятельность может содержать несколько фрагментов. Фрагменты в основном являются частью деятельности.
Операция может содержать 0 или несколько фрагментов в зависимости от размера экрана. Фрагмент можно повторно использовать в нескольких действиях, поэтому он действует как повторно используемый компонент в действиях.
Фрагмент не может существовать независимо. Это должно быть всегда частью деятельности. Где деятельность может существовать без какого-либо фрагмента.
Не уверен, на какие видео вы ссылаетесь, но я сомневаюсь, что они говорят, что вы должны использовать фрагменты вместо действий, потому что они не являются взаимозаменяемыми. На самом деле в Руководстве для разработчиков есть довольно подробная запись, попробуйте прочитать ее подробнее.
Короче говоря, фрагменты живут внутри действий, и каждое действие может содержать много фрагментов. Как и действия, они имеют определенный жизненный цикл, в отличие от действий, они не являются компонентами приложений верхнего уровня. Преимущества фрагментов включают повторное использование кода и модульность (например, использование одного и того же представления списка во многих действиях), в том числе возможность построения многопанельных интерфейсов (в основном это полезно на планшетах). Основным недостатком является (некоторая) дополнительная сложность. Как правило, вы можете достичь того же с помощью нестандартных и менее надежных представлений.
Фрагмент - это часть пользовательского интерфейса или поведения приложения, которая может быть размещена в Деятельности, которая обеспечивает более модульный дизайн действия. Это не будет неправильно, если мы скажем, что фрагмент является своего рода субактивностью.
Ниже приведены важные моменты о фрагменте:
Фрагмент имеет свою собственную разметку и свое собственное поведение со своими собственными обратными вызовами жизненного цикла.
Вы можете добавлять или удалять фрагменты в действии во время его выполнения.
Вы можете объединить несколько фрагментов в одном действии, чтобы создать многопанельный пользовательский интерфейс.
Фрагмент может быть использован в нескольких видах деятельности.
Жизненный цикл фрагмента тесно связан с жизненным циклом активности хоста.
Когда действие приостановлено, все фрагменты, доступные в активности, также будут остановлены.
Фрагмент может реализовывать поведение, которое не имеет компонента пользовательского интерфейса.
Фрагменты были добавлены в Android API в Android 3 (Honeycomb) с API версии 11.
Для более подробной информации, пожалуйста, посетите официальный сайт, Фрагменты.
Активность - это полноэкранные компоненты в приложении с панелью инструментов, все остальное предпочтительно фрагменты. Одно полноэкранное родительское действие с панелью инструментов может иметь несколько панелей, прокручиваемых страниц, диалогов и т. Д. (Все фрагменты), все из которых могут быть доступны из родительского элемента и взаимодействовать через родительский элемент.
Пример -
Деятельность A, Деятельность B, Деятельность C -
- Все действия должны повторяться в одном и том же коде, например, для показа базовой панели инструментов или наследования от родительского действия (управление становится громоздким).
- Чтобы перейти от одного действия к другому, либо все они должны находиться в памяти (накладные расходы), либо одно должно быть уничтожено, чтобы открылось другое.
- Связь между действиями может быть сделана через Intents.
против
Занятие А, Фрагмент 1, Фрагмент 2, Фрагмент 3 -
- Нет повторения кода, все экраны имеют панели инструментов и т. Д. Из этого одного действия.
- Несколько способов перехода от одного фрагмента к следующему - просмотр пейджера, мультипанель и т. Д.
- Активность содержит большую часть данных, поэтому необходимо минимальное взаимодействие между фрагментами. Если все еще необходимо, может быть сделано через интерфейсы легко.
- Фрагменты не обязательно должны быть полноэкранными, чтобы их можно было загружать гибко.
- Фрагменты не нужно раздувать макет, если представления не нужны.
- Несколько Деятельностей могут использовать один и тот же фрагмент.
Это важная информация, которую я нашел на фрагментах:
Исторически каждый экран в приложении Android был реализован как отдельное действие. Это создает проблему при передаче информации между экранами, потому что механизм Намерения Android не позволяет передавать ссылочный тип (то есть объект) непосредственно между Операциями. Вместо этого объект должен быть сериализован или должна быть доступна глобально доступная ссылка.
Делая каждый экран отдельным фрагментом, эта головная боль при передаче данных полностью исключается. Фрагменты всегда существуют в контексте данного действия и всегда могут получить доступ к этому действию. Сохраняя интересующую информацию в Деятельности, Фрагмент для каждого экрана может просто получить доступ к ссылке на объект через Мероприятие.
Фрагменты особенно полезны в некоторых случаях, например, когда мы хотим сохранить навигационный ящик на всех наших страницах. Вы можете надуть макет кадра любым фрагментом, который вам нужен, и при этом иметь доступ к блоку навигации.
Если бы вы использовали какое-либо действие, вам пришлось бы хранить ящик во всех действиях, что создает избыточный код. Это одно интересное использование фрагмента.
Я новичок в Android и до сих пор думаю, что фрагмент полезен таким образом.
Я знаю, что это уже обсуждалось до смерти, но я хотел бы добавить еще несколько моментов:
Frags можно использовать для заполнения
Menu
с и может справитьсяMenuItem
щелкает самостоятельно. Таким образом, давая дополнительные варианты модуляции для вашей деятельности. Вы можете выполнять работу с ContextualActionBar и т. Д., Не подозревая об этом свою деятельность и, по сути, можете отделить ее от основной вещи, которую обрабатывает ваша деятельность (Навигация / Настройки / О программе).Родительский Frag с дочерними Frags может дать вам дополнительные возможности для модуляции ваших компонентов. Например, вы можете легко менять местами фраги, помещать новые фраги в пейджер или удалять их, переставлять их. Все без вашей Деятельности, ничего не зная об этом, просто сосредотачиваясь на вещах более высокого уровня.
можно рассматривать как некорневые компоненты в составном дереве элементов пользовательского интерфейса, в то время как действия находятся наверху в лесу составных элементов (деревья пользовательского интерфейса).
Эмпирическое правило, когда не использовать, - это когда в детстве фрагмент имеет конфликтующий атрибут, например, он может быть иммерсивным или может использовать другой стиль вместе или иметь некоторые другие архитектурные / логические различия и не подходит существующее дерево однородно .
Практическое правило, когда предпочесть
Activity
надFragment
- это когда задача (или набор согласованных задач) полностью независима и может использоваться повторно и выполняет некоторую тяжелую работу и не должна подвергаться дополнительной нагрузке, чтобы соответствовать другой композиции родительско-дочерний (нарушение SRP, вторая ответственность будет заключаться в согласовании с композицией) . Например,MediaCaptureActivity
который захватывает аудио, видео, фотографии и т. д. и позволяет редактировать, удалять шум, добавлять аннотации к фотографиям и т. д. и т. д. У этого действия / модуля могут быть дочерние фрагменты, которые выполняют более детальную работу и соответствуют общей теме отображения.
Фрагмент живет внутри деятельности.
Пока деятельность живет сама по себе.
Фрагменты живут в Деятельности и имеют:
- свой жизненный цикл
- свой макет
- свои дочерние фрагменты и пр.
Думайте о Фрагментах как о подгруппе основной деятельности, к которой он принадлежит, он не может существовать сам по себе и его можно вызывать / использовать снова и снова. Надеюсь это поможет:)
Если вы когда-либо писали интерфейсную часть раньше, используйте такие компоненты, как (React, Vue или Angular). Подумайте о фрагментах как о повторно используемых компонентах в рамках деятельности.
Фрагмент представляет поведение или часть пользовательского интерфейса в Деятельности. Вы можете объединить несколько фрагментов в одном действии, чтобы создать многопанельный пользовательский интерфейс и повторно использовать фрагмент в нескольких действиях. Вы можете думать о фрагменте как о модульном разделе активности, который имеет собственный жизненный цикл, получает собственные входные события и который можно добавлять или удалять во время выполнения действия.
Вы можете управлять каждым фрагментом независимо, например добавлять или удалять их. Когда вы выполняете такую транзакцию фрагмента, вы также можете добавить ее в задний стек, которым управляет действие - каждая запись в заднем стеке в действии является записью произошедшей транзакции фрагмента. Задний стек позволяет пользователю отменить транзакцию фрагмента (перейти назад), нажав кнопку "Назад".
Когда вы добавляете фрагмент как часть макета своей деятельности, он живет в ViewGroup внутри иерархии представления активности, и фрагмент определяет свой собственный макет представления. Вы можете вставить фрагмент в макет своей деятельности, объявив его в файле макета активности, как элемент, или из кода своего приложения, добавив его в существующую ViewGroup. Однако фрагмент не обязательно должен быть частью макета действия; Вы также можете использовать фрагмент без собственного UI в качестве невидимого работника для действия.
Например: если бы вы использовали NavigationDrawer без фрагментов, то было бы лучше сохранить экземпляр NavigationDrawer в одном действии, а когда вы перемещаетесь по приложению, выбирая из элементов в NavigationDrawer, то каждое из этих запущенных занятий не должно реализовываться. NavigationDrawer, но вместо этого должна быть реализована кнопка "Назад", чтобы перейти обратно к "Основному" / отдельному действию, в котором был реализован NavigationDrawer.
Примечание. Если вы хотите реализовать NavigationDrawer в нескольких действиях, вам нужно будет заново создать новый экземпляр NavigationDrawer в каждом действии, которое вы хотите отобразить.
Я предполагаю, что это будет недостатком по сравнению с использованием фрагментов, тогда как если вы используете фрагмент, вам не понадобится много экземпляров ящика, вам нужен только один.
Ящик с фрагментами вместо действий
Если вы используете NavigationDrawer с фрагментами, ящик должен быть реализован в одном действии, и при выборе каждого элемента ящика его содержимое отображается в каждом из своих собственных фрагментов.
Связь между фрагментом и его Activity: чтобы позволить Fragment взаимодействовать с его Activity, вы можете определить интерфейс в классе Fragment и реализовать его в Activity. Фрагмент захватывает реализацию интерфейса во время его метода жизненного цикла onAttach() и затем может вызовите методы интерфейса для связи с деятельностью.
public class YourFragment extends ListFragment { OnSelectedListener mCallback; // Container Activity must implement this interface public interface OnSelectedListener { public void onItemSelected(int position); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment return inflater.inflate(R.layout.your_view, container, false); } @Override public void onAttach(Activity activity) { super.onAttach(activity); // This makes sure that the container activity has implemented // the callback interface. If not, it throws an exception try { mCallback = (OnSelectedListener) activity; } catch (ClassCastException e) { throw new ClassCastException(activity.toString() + " must implement OnSelectedListener"); } } }...
Теперь фрагмент может доставлять сообщения в активность, вызывая метод onItemSelected() (или другие методы в интерфейсе), используя экземпляр mCallback интерфейса OnSelectedListener.
public static class MainActivity extends Activity
implements YourFragment.OnSelectedListener{
...
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
}
public void onItemSelected(int position) {
// The user selected the headline of an article from the YourFragment
// Do something here to display that article
YourFragment yourFrag = (YourFragment)
getSupportFragmentManager().findFragmentById(R.id.your_fragment);
if (yourFrag != null) {
// If your frag is available, we're in two-pane layout...
// Call a method in the YourFragment to update its content
yourFrag.updateView(position);
} else {
// Otherwise, we're in the one-pane layout and must swap frags...
// Create fragment and give it an argument for the selected item
YourFragment newFragment = new YourFragment();
Bundle args = new Bundle();
args.putInt(YourFragment.ARG_POSITION, position);
newFragment.setArguments(args);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack so the user can navigate back
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
}
}
}
1. Цели использования фрагмента?
- Ans:
- Обработка различий в форм-факторе устройства.
- Передача информации между экранами приложений.
- Организация пользовательского интерфейса.
- Расширенные метафоры пользовательского интерфейса.
Добавляя к приведенным выше ответам, я расскажу на примере приложения, которое я выпустил в playstore.
Это было первое приложение, которое я разработал при изучении Android, поэтому я работал только с действиями. Есть несколько страниц действий, о которых я думаю. 12. Большинство из них содержали контент, который можно было повторно использовать на других страницах, но в итоге я получил отдельную страницу активности почти для каждый щелчок по приложению. Как только я изучил фрагменты, я понял, что все многократно используемые объекты можно просто реализовать, разделить фрагменты и использовать с очень небольшим количеством действий. Мой пользователь может не видеть никакой разницы, но то же самое можно сделать с меньшим количеством кода, кроме того, что фрагменты имеют небольшой вес, не считая возможности повторного использования и модульности, которые они предлагают.
Почему фрагменты?
Фрагменты были созданы для замены большинства вариантов использования активности. И посмотрите эту сессию Android Dev Summit.
Когда использовать фрагменты вместо действий?
Всегда, если вам действительно не нужен API, доступный только в действии.