在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ HTML/ Native 模塊(Android)
JavaScript 環(huán)境
計(jì)時(shí)器
Native 模塊(iOS)
入門
在設(shè)備上運(yùn)行
ProgressBarAndroid
iOS 應(yīng)用程序狀態(tài)
網(wǎng)絡(luò)
ToolbarAndroid
測(cè)試
輔助功能
網(wǎng)絡(luò)信息
DrawerLayoutAndroid
樣式表
手勢(shì)應(yīng)答系統(tǒng)
與現(xiàn)有的應(yīng)用程序集成
樣式
教程
不透明觸摸
調(diào)試 React Native 應(yīng)用
iOS 活動(dòng)指示器
導(dǎo)航器
無(wú)反饋觸摸
動(dòng)畫布局
Web 視圖
鏈接庫(kù)
像素比率
React Native 官網(wǎng)首頁(yè)介紹
iOS 導(dǎo)航器
交互管理器
全景響應(yīng)器
SwitchAndroid
TabBarIOS.Item
相機(jī)滾動(dòng)
ToastAndroid
iOS 震動(dòng)
BackAndroid
文本輸入
iOS 選擇器
應(yīng)用程序注冊(cè)表
iOS 開關(guān)
滾動(dòng)視圖
iOS 日期選擇器
iOS 警告
iOS 鏈接
視圖
圖片
列表視圖
異步存儲(chǔ)
Native UI 組件(Android)
iOS 滑塊
Map 視圖
高亮觸摸
iOS 推送通知
文本
定位
iOS 狀態(tài)欄
Native UI 組件(iOS)
在設(shè)備上運(yùn)行(Android)
Native 模塊(Android)
Flexbox
已知 Issues
iOS 選項(xiàng)卡
安裝 Android 運(yùn)行環(huán)境

Native 模塊(Android)

有時(shí)候一個(gè)應(yīng)用需要訪問(wèn) React Native 平臺(tái)目前沒(méi)有對(duì)應(yīng)模塊的 API 。也許你需要復(fù)用一些已經(jīng)存在的 Java 代碼而不需要在 JavaScript 里面重新實(shí)現(xiàn),或者寫一些高性能,多線程的代碼,比如圖片處理,數(shù)據(jù)庫(kù),或者任何先進(jìn)的擴(kuò)展。

我們?cè)O(shè)計(jì)了 React Native 以致于你可以寫一些真正的原生代碼并且可以完全擁有系統(tǒng)的權(quán)限的能力。這是一個(gè)更加先進(jìn)的特征,并且我們不希望這是傳統(tǒng)開發(fā)過(guò)程中的一部分,然而它存在是非常重要的。如果 React Native 不支持你需要的原生特征,那么你應(yīng)該可以自己創(chuàng)建它。

Toast 模塊

這個(gè)引導(dǎo)將會(huì)使用這個(gè) Toast 的例子。我們將會(huì)可以通過(guò)使用 JavaScript 創(chuàng)建一個(gè) toast 消息。

我們從創(chuàng)建一個(gè)原生模塊開始。一個(gè)原生模塊是一個(gè)通常繼承 ReactContextBaseJavaModule 類的 Java 類,并且實(shí)現(xiàn)了 JavaScript 需要實(shí)現(xiàn)的方法。我們這里的目標(biāo)是允許通過(guò)使用 JavaScript 書寫 ToastAndroid.show('Awesome', ToastAndroid.SHORT);就可以在屏幕上面顯示一個(gè)短短的 toast 消息。

package com.facebook.react.modules.toast;

import android.widget.Toast;

import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;

import java.util.Map;

public class ToastModule extends ReactContextBaseJavaModule {

  private static final String DURATION_SHORT_KEY = "SHORT";
  private static final String DURATION_LONG_KEY = "LONG";

  public ToastModule(ReactApplicationContext reactContext) {
    super(reactContext);
  }
}

ReactContextBaseJavaModule 需要一個(gè)叫做 getName 的方法被實(shí)現(xiàn)。這個(gè)方法的目的就是返回在 JavaScript 里面表示這個(gè)類的叫做 NativeModule 的字符串的名字。在這里我們調(diào)用 ToastAndroid 因此我們可以在 JavaScript 里面使用 React.NativeModules.ToastAndroid 來(lái)得到它。

  @Override
  public String getName() {
    return "ToastAndroid";
  }

一個(gè)可選的叫做 getConstants 的方法會(huì)將傳遞給 JavaScript 的常量返回。這個(gè)方法的實(shí)現(xiàn)并不是必須的,但是卻對(duì)在 JavaScript 和 Java 中同步的預(yù)定義的關(guān)鍵字的值非常重要。

  @Override
  public Map<String, Object> getConstants() {
    final Map<String, Object> constants = new HashMap<>();
    constants.put(DURATION_SHORT_KEY, Toast.LENGTH_SHORT);
    constants.put(DURATION_LONG_KEY, Toast.LENGTH_LONG);
    return constants;
  }

給 JavaScript 暴露一個(gè)方法,一個(gè) Java 方法需要使用 @ReactMethod 來(lái)注解。橋接的方法的返回值類型總是 void。React Native 的橋接是異步的,因此將一個(gè)結(jié)果傳遞給 JavaScript 的唯一方式就是使用回調(diào)函數(shù)或者調(diào)用事件(見(jiàn)下面)。

  @ReactMethod
  public void show(String message, int duration) {
    Toast.makeText(getReactApplicationContext(), message, duration).show();
  }

參數(shù)類型

下面的參數(shù)類型是被使用 @ReactMethod 注解的方法支持的,并且它們直接對(duì)應(yīng) JavaScript 中對(duì)應(yīng)的值。

Boolean -> Bool
Integer -> Number
Double -> Number
Float -> Number
String -> String
Callback -> function
ReadableMap -> Object
ReadableArray -> Array

注冊(cè)模塊

在使用 Java 的最后一步就是注冊(cè)這個(gè)模塊,這將在你的應(yīng)用包中的 createNativeModules 發(fā)生。如果一個(gè)模塊沒(méi)有被注冊(cè),那么它在 JavaScript 是不可用的。

class AnExampleReactPackage implements ReactPackage {

  ...

  @Override
  public List<NativeModule> createNativeModules(
                              ReactApplicationContext reactContext) {
    List<NativeModule> modules = new ArrayList<>();

    modules.add(new ToastModule(reactContext));

    return modules;
  }

當(dāng)包被創(chuàng)建的時(shí)候,它需要提供給 ReactInstanceManager 。可以看 UIExplorerActivity.java 這個(gè)例子。當(dāng)你初始化一個(gè)新工程的時(shí)候默認(rèn)的包是MainReactPackage.java。

mReactInstanceManager = ReactInstanceManager.builder()
  .setApplication(getApplication())
  .setBundleAssetName("AnExampleApp.android.bundle")
  .setJSMainModuleName("Examples/AnExampleApp/AnExampleApp.android")
  .addPackage(new AnExampleReactPackage())
  .setUseDeveloperSupport(true)
  .setInitialLifecycleState(LifecycleState.RESUMED)
  .build();

為了能讓你更加方便的從 JavaScript 訪問(wèn)你的新功能的時(shí)候,通常會(huì)將原生模塊包裹在一個(gè) JavaScript 模塊里面。這不是必須的,但是節(jié)省了你的類庫(kù)的使用者每次都要 pull NativeModules 的不便。這個(gè) JavaScript 文件也為你增加任何 JavaScript 端功能提供了方便。

/**
 * @providesModule ToastAndroid
 */

'use strict';

/**
 * This exposes the native ToastAndroid module as a JS module. This has a function 'showText'
 * which takes the following parameters:
 *
 * 1. String message: A string with the text to toast
 * 2. int duration: The duration of the toast. May be ToastAndroid.SHORT or ToastAndroid.LONG
 */
var { NativeModules } = require('react-native');
module.exports = NativeModules.ToastAndroid;

現(xiàn)在,在你的 JavaScript 文件里面你可以像下面這樣調(diào)用方法:

var ToastAndroid = require('ToastAndroid')
ToastAndroid.show('Awesome', ToastAndroid.SHORT);

// Note: We require ToastAndroid without any relative filepath because
// of the @providesModule directive. Using @providesModule is optional.

遠(yuǎn)不止 Toasts

回調(diào)

原生模塊也提供了一種特殊的參數(shù)-一個(gè)回調(diào)。在大多數(shù)情況下這是給 JavaScript 返回結(jié)果使用的。

public class UIManagerModule extends ReactContextBaseJavaModule {

...

  @ReactMethod
  public void measureLayout(
      int tag,
      int ancestorTag,
      Callback errorCallback,
      Callback successCallback) {
    try {
      measureLayout(tag, ancestorTag, mMeasureBuffer);
      float relativeX = PixelUtil.toDIPFromPixel(mMeasureBuffer[0]);
      float relativeY = PixelUtil.toDIPFromPixel(mMeasureBuffer[1]);
      float width = PixelUtil.toDIPFromPixel(mMeasureBuffer[2]);
      float height = PixelUtil.toDIPFromPixel(mMeasureBuffer[3]);
      successCallback.invoke(relativeX, relativeY, width, height);
    } catch (IllegalViewOperationException e) {
      errorCallback.invoke(e.getMessage());
    }
  }

...

使用以下方法可以來(lái)訪問(wèn)在 JavaScript 里面可以使用:

UIManager.measureLayout(
  100,
  100,
  (msg) => {
    console.log(msg);
  },
  (x, y, width, height) => {
    console.log(x + ':' + y + ':' + width + ':' + height);
  }
);

一個(gè)原生模塊支持只調(diào)用一次它的回調(diào)。它可以保存這個(gè)回調(diào),并且在以后調(diào)用。

有一點(diǎn)需要強(qiáng)調(diào)的就是在原生方法完成之后這個(gè)回調(diào)并不是立即被調(diào)用的-請(qǐng)記住橋接通信是異步的,因此這個(gè)也在運(yùn)行時(shí)循環(huán)里面。

線程

原生模塊不應(yīng)該設(shè)想有它們將在哪些線程里面被調(diào)用,因?yàn)槟壳暗娜蝿?wù)在以后改變是主要的。如果一個(gè)塊調(diào)用是必須的,那么耗時(shí)操作將會(huì)被分配到間歇性的工作線程中,并且任何回調(diào)將會(huì)從這里開始。

給 JavaScript 傳遞事件

原生模塊可以不需要立即被調(diào)用就可以給 JavaScript 發(fā)送事件。最簡(jiǎn)單的方式就是使用從 ReactContext 獲得的 RCTDeviceEventEmitter,就像下面的代碼片段:

...
private void sendEvent(ReactContext reactContext,
                       String eventName,
                       @Nullable WritableMap params) {
  reactContext
      .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
      .emit(eventName, params);
}
...
WritableMap params = Arguments.createMap();
...
sendEvent(reactContext, "keyboardWillShow", params);

JavaScript 模塊在那時(shí)可以通過(guò)使用 SubscribableaddListenerOn 來(lái)注冊(cè)并且接收事件。

var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
...

var ScrollResponderMixin = {
  mixins: [Subscribable.Mixin],

  componentWillMount: function() {
    ...
    this.addListenerOn(RCTDeviceEventEmitter,
                       'keyboardWillShow',
                       this.scrollResponderKeyboardWillShow);
    ...
  },
  scrollResponderKeyboardWillShow:function(e: Event) {
    this.keyboardWillOpenTo = e;
    this.props.onKeyboardWillShow && this.props.onKeyboardWillShow(e);
  },
上一篇:視圖下一篇:交互管理器