Привязать услугу к активности или фрагменту?
Я работаю над приложением для музыкального плеера. У меня есть основная деятельность, которая имеет несколько фрагментов, каждый из которых отображает песни на альбоме устройства мудрым, художником мудрым и т.д.
У меня есть музыкальный сервис, который обрабатывает все воспроизведение и другие вещи.
Меня смущает связывание этой службы с различными фрагментами, которые у меня есть.
Прямо сейчас я связываю основную деятельность и каждый фрагмент индивидуально с сервисом, и его работа в значительной степени прекрасна. Но мне было интересно, действительно ли это лучшая практика? Есть ли способ связать основное действие с сервисом, а затем каким-то образом использовать его в своих дочерних фрагментах?
Возможно, мне не хватает элементарной концепции деятельности или фрагментов или служб. Так что, пожалуйста, помогите мне в этом отношении.
Я предполагаю, что это скорее концептуальный вопрос, поэтому никакой код не нужен. Но все же, если потребуется, пожалуйста, дайте мне знать.
РЕДАКТИРОВАТЬ:
Мой вопрос: что было бы лучшим способом связать службу с активностью с несколькими дочерними фрагментами (каждый из которых будет использовать эту службу)?
Ответы
Ответ 1
Привяжите Service
к вашей деятельности, а не к Fragment
. Описание вашего приложения, одно действие с несколькими Fragment
, которые меняются местами и вне, делает это наиболее практичным (и действительно) практическим подходом.
При привязке Service
к Activity
вы привязываете свой жизненный цикл к циклу Activity
. См. Связанные службы. Каждый раз, когда вы добавляете или удаляете Fragment
в своей деятельности, который Fragment
создается и уничтожается. Вы не хотите пытаться связать службу с этим процессом, потому что тогда вам придется создавать и уничтожать службу каждый раз, когда создается или уничтожается новый фрагмент.
Вместо этого привязывайтесь к хосту Activity
. Затем вы можете взаимодействовать с хостом с вашими фрагментами с помощью интерфейса для доступа к связанным службам или с помощью Intent
.
Ответ 2
Я думаю, что более чистая архитектура должна связываться непосредственно с фрагментом. Что касается проблемы, изложенной в ответе Rarw, вы можете связать сервис с вашей деятельностью, а также с вашими фрагментами. Таким образом, вы уверены, что сервис будет там, пока активность не будет уничтожена.
Я вижу два основных преимущества при подключении из фрагмента:
-
Подключение службы асинхронно, поэтому внутри фрагмента вы никогда не уверены, что служба, которую вы получаете от действия, не равна нулю. Это приведет вас, по крайней мере, к некоторым проверкам нулевого указателя и к некоторому механизму для обновления фрагмента как при его создании, так и при подключении службы (так что вы уверены, что будете отображать данные независимо от того, какой из двух событий произойдет первым).
-
Вы не зависите от конкретной деятельности, в которой живут ваши фрагменты. Чтобы получить услугу из упражнения, я думаю, вы выполняете приведение к конкретному классу действия. Вы можете создать интерфейс, такой как BoundActivity
с помощью метода, подобного getBoundService
для получения сервиса от него, но я думаю, что это накладные расходы, учитывая преимущество пункта 1. А что, если у вас есть несколько сервисов?
ОБНОВИТЬ
Вот очень простой проект, показывающий это. https://github.com/ena1106/FragmentBoundServiceExample
Ответ 3
Вы можете получить доступ к своей деятельности из фрагмента getActivity()
Ответ 4
вы можете использовать лоток с использованием шаблона шины событий с этой библиотекой, шаблон публикации публикации/подписки eventbus. https://github.com/greenrobot/EventBus проверить сайт проекта для получения дополнительной информации.
вы можете отправлять события из/в службу в активный или фрагмент.
Ответ 5
ЕСЛИ вам нужно получить некоторые данные из вашей службы в ваш фрагмент в начале жизненного цикла фрагмента, onServiceConnected on activity еще не вызывается, в основном, когда вы вращаете свое устройство, и вы получите NPE.
Я думаю, что это хорошая идея, пусть фрагмент создает свои собственные соединения, поскольку служба запускается с помощью startService(), а не с bindService().
Ответ 6
Я связываю службу в My Host Activity и передаю объект Ibinder через Bundle, который задан в аргументах.
и мой код может выглядеть так:
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//put service in bundle
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
Ответ 7
Единственный метод, который я нашел надежным, - использовать загрузчик в Fragment
:
- создать
Loader
в фрагменте
- используйте
context
для Loader
(установите для activity
в initLoader
, когда вызывается фрагмент onCreate
)
- привязать службу в
onStartLoading
, используя ServiceConnection
, которая вызывает forceLoad()
, как только служба будет связана
- необязательно регистрировать обратные вызовы в
onStartLoading
/onStopLoading
- отвязать услугу в
onStopLoading