React Native 原生模塊封裝(Android篇)

React Native 原生模塊封裝(IOS篇)

前言

有時候React Native沒有相應(yīng)的模塊, API無法滿足我們的需要時,或者我們需要復(fù)用Object-C, Swift或者Java代碼的時候,而又不是用JavaScript重新實 現(xiàn)一邊,又或者你需要實現(xiàn)某些高性能、多線程的代碼,譬如圖片處理、數(shù)據(jù)庫、或者各種高級擴展等等。

我們把React Native設(shè)計為可以在其基礎(chǔ)上編寫真正的原生代碼,并且可以訪問平臺所有的能力。這是一個相對高級的特性,我們并不認為它應(yīng)當在日常開發(fā)的過程中經(jīng)常出現(xiàn),但具備這樣的能力是很重要的。如果React Native還不支持某個你需要的原生特性,你應(yīng)當可以自己實現(xiàn)該特性的封裝。然后提供出Android或者IOS共用的接口給React Native調(diào)用

用法

第一步:

在React Native中, 一個本地的“原生模塊”其實就是繼承了ReactContextBaseJavaModule的Java類,它可以實現(xiàn)一些JavaScript所需的功能。

package com.my;

import android.widget.Toast;

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

/**
 * Created by scottwang on 2018/1/5.
 */

public class UserNativeModules extends ReactContextBaseJavaModule {
    public UserNativeModules(ReactApplicationContext reactContext) {
        super(reactContext);
    }

    /**
     * ReactContextBaseJavaModule要求派生類實現(xiàn)getName方法。
     * 這個函數(shù)用于返回一個字符串名字,這個名字在JavaScript端標記這個模塊。
     * 這里我們把這個模塊叫做UserNativeModules,
     * 這樣就可以在JavaScript中通過React.NativeModules.UserNativeModules訪問到這個模塊。
     * @return
     */
    @Override
    public String getName() {
        return "UserNativeModules";
    }

    /**
     * 要導(dǎo)出一個方法給JavaScript使用,Java方法需要使用注解@ReactMethod。
     * 方法的返回類型必須為void。React Native的跨語言訪問是異步進行的。
     * @param name
     * @param password
     */
    @ReactMethod
    public void userLogin(String name, String password) {
        Toast.makeText(getReactApplicationContext(), name+" : "+password,Toast.LENGTH_LONG).show();
    }
}

第二步:注冊模塊

在Java這邊要做的最后一件事就是注冊這個模塊。我們需要在應(yīng)用的Package類的createNativeModules方法中添加這個模塊。如果模塊沒有被注冊,它也無法在JavaScript中被訪問到。

package com.my;

import com.facebook.react.ReactPackage;
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 UserReactPackage implements ReactPackage {
    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
    @Override
    public List<NativeModule> createNativeModules(
            ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
        modules.add(new UserNativeModules(reactContext));
        return modules;
    }
}

第三步: 導(dǎo)出包

這個package需要在Application.java文件的getPackages方法中提供。

package com.my;

import android.app.Application;

import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.soloader.SoLoader;

import java.util.Arrays;
import java.util.List;

public class MainApplication extends Application implements ReactApplication {

  private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
    @Override
    public boolean getUseDeveloperSupport() {
      return BuildConfig.DEBUG;
    }

    @Override
    protected List<ReactPackage> getPackages() {
      return Arrays.<ReactPackage>asList(
          new MainReactPackage(),
          new UserReactPackage()
      );
    }

    @Override
    protected String getJSMainModuleName() {
      return "index";
    }
  };

  @Override
  public ReactNativeHost getReactNativeHost() {
    return mReactNativeHost;
  }

  @Override
  public void onCreate() {
    super.onCreate();
    SoLoader.init(this, /* native exopackage */ false);
  }
}

第四步: React Native中調(diào)用

為了讓你的功能從JavaScript端訪問起來更為方便,通常我們都會把原生模塊封裝成一個JavaScript模塊。這不是必須的,但省下了每次都從NativeModules中獲取對應(yīng)模塊的步驟。這個JS文件也可以用于添加一些其他JavaScript端實現(xiàn)的功能。

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import React, { Component } from 'react';
import {
  Platform,
  StyleSheet,
  Text,
  View,
  Button,
  Alert
} from 'react-native';

import { NativeModules } from 'react-native';
var UserNativeModules = NativeModules.UserNativeModules;

const instructions = Platform.select({
  ios: 'Press Cmd+R to reload,\n' +
    'Cmd+D or shake for dev menu',
  android: 'Double tap R on your keyboard to reload,\n' +
    'Shake or press menu button for dev menu',
});

const onButtonPress = () => {
  Alert.alert('Button has been pressed!');
  UserNativeModules.userLogin("User Id","password");
};

export default class App extends Component {
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>
          Welcome to React Native!
        </Text>
        <Text style={styles.instructions}>
          To get started, edit App.js
        </Text>
        <Text style={styles.instructions}>
          {instructions}
        </Text>
        
        <Button
          onPress={onButtonPress}
          title="Learn More"
          color="#841584"
          accessibilityLabel="Learn more about this purple button"
        />

      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容