摘要:當使用開發(fā)應用時,你可能需要使用沒有被封裝的模塊。但你可以使用編寫原生模塊,然后選擇性的暴露公共接口到。編寫一個的原生模塊需要以下步驟創(chuàng)建一個,把很多模塊和包含在一起,然后在中的方法引用。最后,在中通過導入你的模塊。
我們要寫一個什么東西當使用 React Native 開發(fā) Android 應用時,你可能需要使用沒有被 React Native 封裝的模塊。但你可以使用 Java 編寫原生模塊,然后選擇性的暴露公共接口到 React Native。一起來試一下!
在寫這篇文章時,React Native 包含了 ImagePickerIOS 組件,但是在 Android 平臺上卻沒有對應的 ImagePicker 組件。我們接下來就要為 Android 構建一個簡單的、和 ImagePickerIOS 大致相仿的 ImagePicker。
編寫一個 React Native 的 Android 原生模塊需要以下步驟:創(chuàng)建一個 ReactPackage,把很多模塊(Native 和 Javascript)包含在一起,然后在 MainActivity 中的 getPackages 方法引用。
創(chuàng)建一個 Java 類,繼承 ReactContextBaseJavaModule 并實現(xiàn)需要的接口,然后注冊到我們的 ReactPackage。
覆寫上述類的 getName 方法,這個方法會作為 Javascript 的調用方法名。
使用 @ReactMethod 注解把需要的公共方法暴露給 Javascript。
最后,在 Javascript 中通過 NativeModules 導入你的模塊。
讓我們一起實踐一下。
創(chuàng)建一個 ReactPackage啟動 AndroidStudio 并且導航到 MyApp/android/app/src/main/java/com/myapp/MainActivity.java。它應該看起來像這樣:
package com.myapp; import com.facebook.react.ReactActivity; import com.facebook.react.ReactPackage; import com.facebook.react.shell.MainReactPackage; import java.util.Arrays; import java.util.List; public class MainActivity extends ReactActivity { @Override protected String getMainComponentName() { return "MyApp"; } @Override protected boolean getUseDeveloperSupport() { return BuildConfig.DEBUG; } @Override protected ListgetPackages() { return Arrays. asList( new MainReactPackage() ); } }
我們先來引入一個尚未定義的包:
import com.myapp.imagepicker.*; // import the package public class MainActivity extends ReactActivity { @Override protected ListgetPackages() { return Arrays. asList( new MainReactPackage(), new ImagePickerPackage() // include it in getPackages ); } }
現(xiàn)在我們來編寫那個包。我們將會為它創(chuàng)建一個叫 imagepicker 的新目錄并且寫入 ImagePickerPackage:
package com.myapp.imagepicker; import com.facebook.react.ReactPackage; import com.facebook.react.bridge.JavaScriptModule; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.uimanager.ViewManager; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class ImagePickerPackage implements ReactPackage { @Override public ListcreateNativeModules(ReactApplicationContext reactContext) { List modules = new ArrayList<>(); modules.add(new ImagePickerModule(reactContext)); return modules; } @Override public List > createJSModules() { return Collections.emptyList(); } @Override public List createViewManagers(ReactApplicationContext reactContext) { return Collections.emptyList(); } }
現(xiàn)在我們已經創(chuàng)建了一個包并且包含進 MainActivity 中了。
創(chuàng)建一個 ReactContextBaseJavaModule我們將會以創(chuàng)建 ImagePickerModule 開始,繼承 ReactContextBaseJavaModule。
package com.myapp.imagepicker; import com.facebook.react.bridge.ReactContextBaseJavaModule; public class ImagePickerModule extends ReactContextBaseJavaModule { public ImagePickerModule(ReactApplicationContext reactContext) { super(reactContext); } }
這是一個好的開始,為了 React Native 能從 NativeModules 找到我們的模塊,我們需要覆寫 getName 方法。
@Override public String getName() { return "ImagePicker"; }
我們現(xiàn)在有了一個可以被 JavaScript 代碼導入的 native 模塊,讓它做些有趣的事情吧。
暴露方法ImagePickerIOS 定義了 openSelectDialog 方法,可以傳遞配置對象、失敗、成功的回調。讓我們在 ImagePickerModule 中定義一個相似的方法。
import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.ReadableMap; public class ImagePickerModule extends ReactContextBaseJavaModule { @ReactMethod public void openSelectDialog(ReadableMap config, Callback successCallback, Callback cancelCallback) { Activity currentActivity = getCurrentActivity(); if (currentActivity == null) { cancelCallback.invoke("Activity doesn"t exist"); return; } } }
這里我們從 React Native 中導入了 Callback 和 ReadableMap 來對應 JavaScript 中的 function 和 object。我們?yōu)檫@個方法加上 @ReactMethod 注解,從而使它作為 ImagePicker 的一部分被 JavaScript 引用。
在方法體中我們獲取當前的 activity,如果沒有獲取到 activity,就調用 cancel 的回調方法。我們現(xiàn)在有了一個可以運行的方法,但是它還不能做任何有趣的事情。讓我們用它打開相冊。
public class ImagePickerModule extends ReactContextBaseJavaModule { private static final int PICK_IMAGE = 1; private Callback pickerSuccessCallback; private Callback pickerCancelCallback; @ReactMethod public void openSelectDialog(ReadableMap config, Callback successCallback, Callback cancelCallback) { Activity currentActivity = getCurrentActivity(); if (currentActivity == null) { cancelCallback.invoke("Activity doesn"t exist"); return; } pickerSuccessCallback = successCallback; pickerCancelCallback = cancelCallback; try { final Intent galleryIntent = new Intent(); galleryIntent.setType("image/*"); galleryIntent.setAction(Intent.ACTION_GET_CONTENT); final Intent chooserIntent = Intent.createChooser(galleryIntent, "Pick an image"); currentActivity.startActivityForResult(chooserIntent, PICK_IMAGE); } catch (Exception e) { cancelCallback.invoke(e); } } }
首先,我們設置了回調,然后,我們創(chuàng)建了一個 Intent 并把它傳遞給 startActivityForResult。最后,我們把所有的東西都放在 try/catch 塊中來處理可能發(fā)生的異常。
當你調用 openSelectDialog 時,你應該可以看到一個相冊了。然而,當你選擇一張圖片時,相冊并不做任何事情。為了能夠處理圖片數(shù)據(jù),我們需要在模塊中處理 activity 的返回值。
首先,我們需要在 react context 中添加 activity event listener:
public class ImagePickerModule extends ReactContextBaseJavaModule implements ActivityEventListener { public ImagePickerModule(ReactApplicationContext reactContext) { super(reactContext); reactContext.addActivityEventListener(this); } }
現(xiàn)在我們可以獲取到相冊返回的數(shù)據(jù)了。
@Override public void onActivityResult(final int requestCode, final int resultCode, final Intent intent) { if (pickerSuccessCallback != null) { if (resultCode == Activity.RESULT_CANCELED) { pickerCancelCallback.invoke("ImagePicker was cancelled"); } else if (resultCode == Activity.RESULT_OK) { Uri uri = intent.getData(); if (uri == null) { pickerCancelCallback.invoke("No image data found"); } else { try { pickerSuccessCallback.invoke(uri); } catch (Exception e) { pickerCancelCallback.invoke("No image data found"); } } } } }
在這里我們應該可以通過 success callback 獲取到圖片 URI。
NativeModules.ImagePicker.openSelectDialog( {}, // no config yet (uri) => { console.log(uri) }, (error) => { console.log(error) } )
為了和 ImagePickerIOS 的表現(xiàn)大致相仿,我們可以允許用戶選擇圖片、視頻或者直接打開相機。這些功能的寫法和上面基本一致,我們將會把它留給讀者作為練習。
相關閱讀使用 React Native 構建 Facebook Paper 類似的 UI
作者往期佳作ES6 Generators 工作原理
歡迎關注公眾號:MaxLeap_yidongyanfa
原文作者: Ryan Linton
原文鏈接: http://t.cn/Rfadv1R
翻譯自MaxLeap團隊_前端研發(fā)人員:Henry Bai
MaxLeap技術博客首發(fā):https://blog.maxleap.cn/
主題:手把手教你玩轉微信小程序,領先進入藍海市場
時間:11月23日
地點:上海徐匯宜山路888號21樓
報名url:http://t.cn/RfcM3Sa
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://systransis.cn/yun/80991.html
摘要:對象和原生代碼交互對象可以和原生對象之間相互調用,關系如上圖。和本地代碼間的通信其中通信的特點是異步的序列化的批量的,對于大批量的通信事件可以將其分成幾部分,減少時間延遲參考 React Native簡介 React Native是一個建立在JavaScript和React上用于構建本地應用的框架,它具有React和JavaScript相似的代碼風格,編寫一次可以運行在多個平臺之上(>...
閱讀 2344·2023-04-25 14:29
閱讀 1473·2021-11-22 09:34
閱讀 2714·2021-11-22 09:34
閱讀 3398·2021-11-11 10:59
閱讀 1863·2021-09-26 09:46
閱讀 2238·2021-09-22 16:03
閱讀 1928·2019-08-30 12:56
閱讀 484·2019-08-30 11:12