Андромеда обеспечивает взаимодействие между модулями как локально, так и удаленно.
Примечание: Различие между локальным сервисом и удалённым сервисом заключается в том, что типы параметров в удалённом сервисе могут быть только примитивными типами или пользовательскими типами, реализующими Parcelable, тогда как типы параметров в локальном сервисе могут быть любыми, включая View и Context.
Документация, лучше на китайском
AIDL интерфейсы и их реализации — это единственное, что разработчики должны делать. bindService() и определение Service не требуются.
Удалённый сервис может быть получен синхронно вместо асинхронного получения.
Управление приоритетами процессов осуществляется вместе с жизненным циклом Fragment/Activity.
Поддержка обратного вызова IPC.
Поддержка шины событий для всех процессов.
Примечание: В данном контексте слово "сервис" относится к интерфейсу и его реализации, а не к компоненту Service.
Сравнение других решений коммуникации с Андромедой:
удобство использования | вторжение в код | совместимость | IPC | шина событий | маршрутизатор страниц | |
---|---|---|---|---|---|---|
Андромеда | хорошее | нет | хорошее | да | да | нет |
DDComponentForAndroid | плохое | некоторое | плохое | нет | нет | да |
ARouter | хорошее | некоторое | плохое | нет | нет | да |
Добавьте classpath в buildscript (замените $version на последнюю версию):
classpath "org.qiyi.video.svg:plugin:$version"
Добавьте зависимость основной библиотеки в Application или модуль библиотеки:
implementation "org.qiyi.video.svg:core:$version"
Примените плагин Gradle в модуле приложения:
apply plugin: 'org.qiyi.svg.plugin'
Dispatcher всегда должен находиться в процессе, который живёт дольше всего, поскольку он управляет информацией обо всех процессах. По умолчанию процесс Dispatcher — это главный процесс, если конфигурация отсутствует. Учитывая, что некоторые процессы могут жить дольше главного процесса (например, музыкальный проигрыватель), разработчики должны указывать имя процесса для Dispatcher в этом случае. Пример конфигурации в build.gradle модуля приложения:
dispatcher{
process ":downloader"
}
В этом случае процесс ":downloader" является процессом, который живёт дольше всего.
Добавьте код инициализации в метод onCreate() класса Application:
Andromeda.init(Context);
Основные различия между локальным сервисом и обычными интерфейсами следующие:
Регистрация локального сервиса возможна двумя способами:
Andromeda.registerLocalService(ICheckApple.class.getCanonicalName(), new CheckApple());
или
Andromeda.registerLocalService(ICheckApple.class, new CheckApple());
ICheckApple — это определение интерфейса. Учитывая ProGuard, регистрация локального сервиса с использованием фиксированной строки не рекомендуется:
Andromeda.registerLocalService("wang.imallen.blog.moduleexportlib.apple.ICheckApple", CheckAppleImpl.getInstance());
Любой модуль, находящийся в одном процессе с серверным модулем, может получить локальный сервис после регистрации. Пример первого способа:
ICheckApple checkApple = (ICheckApple) Andromeda.getLocalService(ICheckApple.class);
или второй:
ICheckApple checkApple = (ICheckApple) Andromeda.getLocalService(ICheckApple.class.getCanonicalName());
Также, учитывая ProGuard, получение локального сервиса с использованием фиксированной строки также не рекомендуется:
ICheckApple checkApple = (ICheckApple) Andromeda.getLocalService("wang.imallen.blog.moduleexportlib.apple.ICheckApple");
LocalServiceDemo показывает детали регистрации и использования локального сервиса.
Обратный вызов локального сервиса аналогичен обычному интерфейсу, поэтому всё зависит от разработчиков. Итак, Андромеда не предоставляет никаких обратных вызовов.
Сначала определяйте AIDL интерфейс и выведите его в общий модуль вместе со своим Stub и Proxy:
package wang.imallen.blog.moduleexportlib.apple;
import org.qiyi.video.svg.IPCCallback;
interface IBuyApple {
int buyAppleInShop(int userId);
void buyAppleOnNet(int userId, IPCCallback callback);
}
Затем предоставьте реализацию:
public class BuyAppleImpl extends IBuyApple.Stub {
private static BuyAppleImpl instance;
public static BuyAppleImpl getInstance() {
if (null == instance) {
synchronized (BuyAppleImpl.class) {
if (null == instance) {
instance = new BuyAppleImpl();
}
}
}
return instance;
}
private BuyAppleImpl() {}
@Override
public int buyAppleInShop(int userId) throws RemoteException {
...
}
@Override
public void buyAppleOnNet(int userId, IPCCallback callback) throws RemoteException {
...
}
}
В отличие от регистрации локального сервиса, IBinder удалённого сервиса необходим для регистрации:
Andromeda.registerRemoteService(IBuyApple.class, BuyAppleImpl.getInstance().asBinder());
Также можно использовать другой способ:
Andromeda.registerRemoteService(IBuyApple.class, BuyAppleImpl.getInstance());
Ещё один способ регистрации:
Andromeda.registerRemoteService(IBuyApple.class.getCanonicalName(), BuyAppleImpl.getInstance().asBinder());
IBinder binder = Andromeda.with(this).getRemoteService(IBuyApple.class);
if (binder == null) {
return;
}
IBuyApple buyApple = IBuyApple.Stub.asInterface(binder);
if (buyApple == null) {
return;
}
try {
buyApple.buyAppleInShop(29);
} catch (RemoteException ex) {
ex.printStackTrace();
}
Использование удаленного сервиса в android.app.Fragment, android.support.v4.app.Fragment и обычном Activity аналогично, примеры демонстрационных приложений: CustomFragment, CustomSupportFragment и FragActivity.
Учитывая, что длительные операции могут выполняться в серверном процессе, обратный вызов удаленного сервиса необходим. Для тех, кто нуждается в обратном вызове, следует добавить параметр IPCCallback в определении AIDL:
interface IBuyApple {
int buyAppleInShop(int userId);
void buyAppleOnNet(int userId, IPCCallback callback);
}
Каноническое имя IPCCallback — это org.qiyi.video.svg.IPCCallback. Его определение такое:
interface IPCCallback {
void onSuccess(in Bundle result);
void onFail(String reason);
}
Клиент может использовать IPCCallback таким образом:
IBinder buyAppleBinder = Andromeda.getRemoteService(IBuyApple.class);
if (null == buyAppleBinder) {
return;
}
IBuyApple buyApple = IBuyApple.Stub.asInterface(buyAppleBinder);
if (null != buyApple) {
try {
buyApple.buyAppleOnNet(10, new IPCCallback.Stub() {
@Override
public void onSuccess(Bundle result) throws RemoteException {
...
}
@Override
public void onFail(String reason) throws RemoteException {
...
}
});
} catch (RemoteException ex) {
ex.printStackTrace();
}
}
Учитывая, что обратный вызов находится в потоке Binder, а большинство разработчиков хотят, чтобы обратный вызов был в потоке UI, Андромеда предлагает базовый класс BaseCallback для разработчиков.
IBinder buyAppleBinder = Andromeda.getRemoteService(IBuyApple.class);
if (null == buyAppleBinder) {
return;
}
IBuyApple buyApple = IBuyApple.Stub.asInterface(buyAppleBinder);
if (null != buyApple) {
try {
buyApple.buyAppleOnNet(10, new BaseCallback() {
@Override
public void onSucceed(Bundle result) {
...
}
@Override
public void onFailed(String reason) {
...
}
});
} catch (RemoteException ex) {
ex.printStackTrace();
}
}
Использование BaseCallback вместо IPCCallback рекомендовано!
BananaActivity показывает подробности использования этого механизма.
Для повышения приоритета процесса сервера, Andromeda выполнит метод bindService()
при вызове Andromeda.with().getRemoteService()
в соответствии с жизненным циклом Fragment/Activity.
Как следствие, требуется выполнение действия отвязки (unbind
) при уничтожении Fragment/Activity.
Существует две ситуации:
Для тех, кто получает удалённый сервис с использованием Fragment/Activity и в главном потоке, Andromeda автоматически выполняет действие отвязки (unbind
).
Для тех, кто получает не с использованием Fragment/Activity или в рабочем потоке, действие отвязки (unbind
) должно быть вызвано разработчиками:
public static void unbind(Class<?> serviceClass);
public static void unbind(Set<Class<?>> serviceClasses);
Определение события в Andromeda выглядит следующим образом:
public class Event implements Parcelable {
private String name;
private Bundle data;
...
}
Конечно, событие состоит из имени и данных, где данные являются типом Bundle, который может загружать параметры примитивного типа или параметры типа Parcelable.
Подписка на событие очень проста с помощью реализации EventListener, такого как MainActivity:
Andromeda.subscribe(EventConstants.APPLE_EVENT,MainActivity.this);
Это означает, что подписывается событие с именем EventConstants.APPLE_EVENT
.
Публикация события также проста:
Bundle bundle = new Bundle();
bundle.putString("Result", "gave u five apples!");
Andromeda.publish(new Event(EventConstants.APPLE_EVENT, bundle));
После публикации все слушатели во всех процессах смогут получить это событие.
MainActivity демонстрирует детали того, как подписываться и публиковать события.
BSD-3-Clause. Дополнительные сведения см. в файле BSD-3-Clause.
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарии ( 0 )