Использование пользовательских собственных компонентов в React Native – обычное дело, поэтому рано или поздно вам, возможно, придется написать некоторые функции на родном языке и использовать их в своем приложении. Позвольте мне показать вам простой пример, как это сделать.
Сначала подготовьте код в отдельном приложении
Мы начинаем с создания простого собственного приложения. В этом примере наше приложение покажет информацию о пользователе, когда гарнитура подключена или отключена. Это включает в себя несколько нативных взаимодействий:
- взаимодействие с жизненным циклом приложения при регистрации или отмене регистрации слушателей
- отправка и получение данных с помощью намерений
- отображение информации с помощью тостов
- использование контекста приложения
Предполагая, что вы знакомы с созданием собственных приложений для Android, приведенный ниже пример будет очень простым. Наше приложение использует одно действие с простым макетом, которое позже будет неуместным. Начните с личных полей, которые будут использоваться в нашей деятельности:
private Context mContext; private final BroadcastReceiver mHeadsetPlugReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(Intent.ACTION_HEADSET_PLUG)) { boolean plugged = (intent.getIntExtra("state", 0) == 1); String message = plugged ? "Headset plugged in" : "Headset plugged out"; Toast.makeText(mContext, message, Toast.LENGTH_SHORT).show(); } } };
Запоминание ссылки на контекст вашего приложения не всегда необходимо, если мы можем позвонить Метод getApplicationContext
в рамках нашей деятельности. Давайте оставим его сейчас, потому что мы изменим его позже. Широковещательный приемник
является абстрактным классом и описывает поведение при получении информации через Интернет.
Регистрация слушателя выглядит так:
private void registerBroadcastReceiver() { IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_HEADSET_PLUG); registerReceiver(mHeadsetPlugReceiver, filter); }
Метод registerReceiver
является методом действия и может быть вызван для объекта класса контекста.
В методе onCreate
сохраните ссылку на контекст приложения и зарегистрируйте приемник широковещательной передачи:
mContext = this; registerBroadcastReceiver();
В конце концов, следуя принципам чистого кодирования, отмените регистрацию получателя при закрытии приложения с помощью метода действия Отменить регистрацию получателя
:
@Override protected void onDestroy() { unregisterReceiver(mHeadsetPlugReceiver); super.onDestroy(); }
Вот и все, вот над чем мы будем работать. Приложение отображает простое сообщение при подключении гарнитуры:
Давайте используем его в нашем проекте RN!
/реагировать-проект/android
В каталоге вашего проекта React есть папка android
. Его структура похожа на любой проект Android, и вы можете открыть его с помощью Android Studio для удобной навигации. Исходные файлы находятся в /app/src/main/java/{некоторые}/{пакеты}/
и здесь мы добавим наш код. Нам придется упаковать нашу функциональность определенным образом. Проверить Основное приложение.java
сначала файл. Он расширяется Приложение
класс и реализует Реагирующее приложение
интерфейс. Взгляните на getPackages
метод:
@Override protected ListgetPackages() { return Arrays. asList( new MainReactPackage() ); }
Приложение, написанное на React Native, построено так же, как и любое другое приложение для Android, но пакеты React Native добавляются во время выполнения, и это указано здесь. Вы можете написать любой машинный код и связать его здесь, но вы должны добавить его как Пакет React
и инициализировать в методе getPackages
. Понадобится два файла: пакет и модуль .
Сначала создайте файл пакета, который реализует com.facebook.react. Пакет реакции
интерфейс. У него есть два метода, и его базовая реализация выглядит следующим образом:
public class MyHeadsetLibPackager implements ReactPackage { @Override public ListcreateNativeModules(ReactApplicationContext reactContext) { List modules = new ArrayList<>(); modules.add(new MyHeadsetLibModule(reactContext)); return modules; } @Override public List createViewManagers(ReactApplicationContext reactContext) { return Collections.emptyList(); } }
Наиболее важной частью является инициализация модуля в создание собственных модулей
метод:
modules.add(new MyHeadsetLibModule(reactContext));
MyHeadsetLibModule
так мы называем наш второй класс. Он будет содержать все функциональные возможности нашей библиотеки. Необходимо расширить com.facebook.react.bridge. ReactContextBaseJavaModule
класс для этого.
import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; public class MyHeadsetLibModule extends ReactContextBaseJavaModule { public MyHeadsetLibModule(ReactApplicationContext reactContext) { super(reactContext); /* Our starting point. */ } }
Последнее, что необходимо для компиляции проекта, – это добавить зависимость в /приложение/build.gradle
dependencies { ... compile "com.facebook.react:react-native:+" ... }
Уход от деятельности
Теперь мы можем реализовать все так, как делали в своей деятельности. Просто имейте в виду два последствия перехода от Activity
к ReactContextBaseJavaModule
.
Первый: У кого есть контекст? Отныне мы не можем вызывать методы активности, такие как registerReceiver
просто так. Мы также не можем получить доступ к контексту приложения, вызвав Getapplication контекст
. Вот почему в конструкторе модуля мы получаем ReactContext
экземпляр. Из него будут вызываться все методы деятельности.
Во-вторых: Где методы жизненного цикла? Прямо сейчас нигде. Но просто реализуйте Прослушиватель событий жизненного цикла
в вашем классе модулей. Это интерфейс, который предоставляет три основных метода жизненного цикла:
аннулирование в резюме хоста()
аннулирование при паузе хоста()
аннулирование на хосте Уничтожить()
Здесь реализованы все функции жизненного цикла. Затем в конструкторе зарегистрируйте прослушиватель с помощью reactContext.добавьте прослушиватель событий жизненного цикла (это)
и… готово. Теперь наш модуль ведет себя как активность.
Последнее, что нужно сделать, чтобы наш модуль был виден, – это переопределить Метод getName
. Он должен возвращать имя нашего модуля, вот так:
@Override public String getName() { return "MyHeadsetLibModule"; }
Следуя всем этим рекомендациям, окончательная форма нашего модуля, переписанного из activity, выглядит следующим образом:
import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.widget.Toast; import com.facebook.react.bridge.LifecycleEventListener; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; public class MyHeadsetLibModule extends ReactContextBaseJavaModule implements LifecycleEventListener { private ReactApplicationContext mContext; private final BroadcastReceiver mHeadsetPlugReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(Intent.ACTION_HEADSET_PLUG)) { boolean plugged = (intent.getIntExtra("state", 0) == 1); String message = plugged ? "Headset plugged in" : "Headset plugged out"; Toast.makeText(mContext, message, Toast.LENGTH_SHORT).show(); } } }; public MyHeadsetLibModule(ReactApplicationContext reactContext) { super(reactContext); mContext = reactContext; registerBroadcastReceiver(); } private void registerBroadcastReceiver() { IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_HEADSET_PLUG); mContext.registerReceiver(mHeadsetPlugReceiver, filter); } @Override public String getName() { return "MyHeadsetLibModule"; } @Override public void onHostResume() { } @Override public void onHostPause() { } @Override public void onHostDestroy() { mContext.unregisterReceiver(mHeadsetPlugReceiver); } }
Предоставление методов JS
Что, если мы хотели бы зарегистрироваться Широковещательный приемник
не при запуске приложения, а позже, и вызвать его из модуля React Native в TypeScript? Вот идет @Reactmethod
аннотация. Просто добавьте метод с ним в свой класс модуля:
@ReactMethod public void startTrackingAudioJackPlug() { registerBroadcastReceiver(); }
Теперь в любом файле машинописного текста мы можем импортировать его из react-native
:
import { NativeModules } from 'react-native'
и используйте вызов его непосредственно из объекта собственных модулей:
NativeModules.MyHeadsetLibModule.startTrackingAudioJackPlug()
Получение обратного вызова из собственного модуля
Последняя модификация – пусть сообщение о подключении гарнитуры будет отображаться не родным тостом, а каким-то реагирующим родным предупреждением. Для этого мы должны передать информацию о подключении гарнитуры из собственного модуля в модуль JS. В машинном коде добавьте это:
reactContext .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) .emit(eventName, params);
имя события
являетсястрокой
объектом и идентифицирует отправленное сообщениепараметры
являетсязаписываемой картой
объектом и содержит параметры в простой коллекции ключ-значение
Теперь просто зарегистрируйте прослушиватель в модуле JS, чтобы получить отправленное сообщение. Импортируйте DeviceEventEmitter
из 'react-native'
и добавьте этот код в componentDidMount
метод:
DeviceEventEmitter.addListener('CustomNameOfTheEvent', function(e: Event) { /* Here you can display an alert. Get parameters values from event like this: let parameter = e["key"] */ })
Это оно. Мы только что реализовали встроенную функциональность с двунаправленной связью.
Оригинал: “https://dev.to/brightdevs/putting-native-in-react-native-on-android-13g7”