ReactNative混合開發(fā)-3 Android混編配置

開發(fā)語言:ReactNative 0.59.5 Android
開發(fā)環(huán)境:VSCode Android Studio 3.4

1相叁、項(xiàng)目目錄

參考文章:集成到現(xiàn)有原生應(yīng)用

首先遵绰,我們按照建立一下目錄結(jié)構(gòu)辽幌,其中:
Code目錄放置所有公用的ReactNative腳本,包椿访,以及相關(guān)配置乌企。
Android目錄放置原Android項(xiàng)目。

Code (根目錄)
--Android(一級(jí)目錄)

2成玫、開發(fā)環(huán)境準(zhǔn)備

2.1加酵、package.json配置

在Code目錄下創(chuàng)建package.json文件,編輯文件輸入以下內(nèi)容哭当。

{
  "name": "AppName",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "yarn react-native start"
  }
}

2.2猪腕、React和React Native模塊安裝

在Code目錄下使用控制臺(tái)執(zhí)行以下語句來安裝React Native。

yarn add react-native
  • 注意钦勘,執(zhí)行完以上命令后陋葡,可能會(huì)出現(xiàn)以下提示內(nèi)容,表示我們需要安裝指定版本的React(此例子中需要安裝版本為16.8.3的React)彻采。

warning " > react-native@0.59.5" has unmet peer dependency "react@16.8.3".

在Code目錄下使用控制臺(tái)執(zhí)行以下語句來安裝指定版本的React

yarn add react@16.8.3

3腐缤、配置maven

3.1、在app的build.gradle文件中添加React Native依賴

dependencies {
    ...
    implementation "com.facebook.react:react-native:+" // 新增React Native依賴
}

3.2肛响、在項(xiàng)目的build.gradle文件中添加maven的依賴入口

allprojects {
    repositories {
        ...
        maven { url "$rootDir/../../node_modules/react-native/android"} //注意url路徑應(yīng)該指向根目錄code中的node_modules岭粤,
    }
}

3.3、在AndroidManifest.xml聲明網(wǎng)絡(luò)權(quán)限

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.reactnativedemo" >
    
    
    <uses-permission android:name="android.permission.INTERNET" /> //新增網(wǎng)絡(luò)權(quán)限
     ...
</manifest>

3.4特笋、在AndroidManifest.xml配置調(diào)試Activity

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.reactnativedemo" >

    <uses-permission android:name="android.permission.INTERNET" />

    <application
    
        ...
        //調(diào)試Activiy剃浇,使用搖一搖呼出
        <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
        
 
 
     </application>

</manifest>

4、腳本創(chuàng)建

在Code根目錄下創(chuàng)建Scripts文件夾,用于存放React Native的腳本文件

Code (根目錄)
--Scripts(一級(jí)目錄虎囚,用于存放所有React Native的腳本)

然后我們可以在Scripts目錄下開始寫ReactNative的腳本了臼寄。
首先我們創(chuàng)建一個(gè)FrameText.js,然后寫入如下內(nèi)容:

import React, { Component } from 'react'
import { View, Text } from 'react-native'


export default class FrameText extends Component {

    render() {
        return (
            <View style={{
                width:200,
                height:100,
                backgroundColor: '#CDDAF5'
            }}>
            <Text>{"我來自ReactNative溜宽,我是FrameText"}</Text>
            </View>
        );
    }
}
// 整體js模塊的名稱
export { FrameText } 

在FrameText中吉拳,我們創(chuàng)建了一個(gè)簡(jiǎn)單的組件,供其他腳本使用适揉。

然后我們?cè)賱?chuàng)建一個(gè)index.js留攒,然后寫入如下內(nèi)容

import {AppRegistry} from 'react-native'
import {FrameText} from 'FrameText'


// 整體js模塊的名稱
AppRegistry.registerComponent('Component-1', () => FrameText);

在index中,我們注冊(cè)了FrameText組件嫉嘀,供app使用炼邀,我們可以在index.js注冊(cè)很多不同的組件,app可以通過我們注冊(cè)的名字(本例中為Component-1)來創(chuàng)建這些組件剪侮,下面我們來看看怎么在app內(nèi)使用他們拭宁。

5、Android項(xiàng)目修改

本例中期望在app的一個(gè)controller內(nèi)瓣俯,同時(shí)使用原生語言與ReactNative腳本分別顯示2個(gè)View杰标,現(xiàn)在我們來看看是如果在原生app中加載ReactNative的View。

5.1彩匕、創(chuàng)建 MyReactNativeBridge

新建一個(gè)Java文件腔剂,創(chuàng)建MyReactNativeBridge類,顧名思義驼仪,此類負(fù)責(zé)橋接原生app與ReactNative掸犬,注意,一個(gè)app中最好只創(chuàng)建一個(gè)橋接實(shí)例绪爸,所以使用單利模式創(chuàng)建湾碎。

package com.example.reactnativedemo;

import com.facebook.react.ReactInstanceManager;
import com.facebook.react.common.LifecycleState;
import com.facebook.react.shell.MainReactPackage;

public class MyReactNativeBridge {

    private static final ReactInstanceManager mReactInstanceManager = ReactInstanceManager.builder()
            .setApplication(MyApplication.getInstance())
            .setBundleAssetName("index.android.bundle")
            .setJSMainModulePath("Scripts/index")
            .addPackage(new MainReactPackage())
            .setUseDeveloperSupport(BuildConfig.DEBUG)
            .setInitialLifecycleState(LifecycleState.RESUMED)
            //注冊(cè)彈出調(diào)試菜單的Activity,發(fā)布版可以無需注冊(cè)
            .setCurrentActivity(MyApplication.getInstance().getCurrentActivity())
            .build();

    private MyReactNativeBridge() {
    
    }

    public static ReactInstanceManager getInstance() {
        return mReactInstanceManager;
    }
}


5.2、創(chuàng)建并使用ReactRootView

ReactRootView為ReactNative腳本描述的View奠货,它繼承FrameLayout介褥,我們可以通過MyReactNativeBridge來創(chuàng)建ReactRootView。

public class MainActivity extends AppCompatActivity {

    private ReactRootView mReactRootView;
    
    LinearLayout reactView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        reactView = findViewById(R.id.reactLayout);
        MyApplication.getInstance().setCurrentActivity(this);
        

        mReactRootView = new ReactRootView(this.getApplicationContext());
        mReactRootView.startReactApplication(MyReactNativeBridge.getInstance(), "Component-1", null);

        
        reactView.addView(mReactRootView);
    }

}

現(xiàn)在我們?cè)谡鏅C(jī)上運(yùn)行模擬器仇味,并且命令開啟ReactNative服務(wù)器(yarn start)呻顽,就可以看到上面例子中的畫面了。

6丹墨、原生與ReactNative通信

6.1廊遍、原生向ReactNative傳遞數(shù)據(jù)

注意我們?cè)趕tartReactApplication時(shí)的語句的第三個(gè)參數(shù)initialProperties,代表由原生向ReactNative傳遞的參數(shù)贩挣。

mReactRootView.startReactApplication(MyReactNativeBridge.getInstance(), "Component-1", null);

現(xiàn)在修改創(chuàng)建語句和腳本

  • Java代碼:通過initialProperties向JS傳遞參數(shù)
public class MainActivity extends AppCompatActivity {

    private Bundle mockData = new Bundle();

    protected void onCreate(Bundle savedInstanceState) {
        
         ...
        mockData.putString("content", "初始化");

        mReactRootView = new ReactRootView(this.getApplicationContext());
        mReactRootView.startReactApplication(MyReactNativeBridge.getInstance(), "Component-1", mockData);

        reactView.addView(mReactRootView);
    }

}
  • JS腳本:通過this.props["content"]使用原生App傳遞的參數(shù)(也可以使用this.props.content)
...

export default class FrameText extends Component {

    render() {
        return (
            <View style={{
                width:200,
                height:100,
                backgroundColor: '#CDDAF5'
            }}>
            <Text>{this.props["content"]}</Text>
            </View>
        );
    }
}

...

重新編譯代碼后喉前,再次運(yùn)行App没酣,可以看到界面變成如下的樣子

ReactRootView還有一個(gè)方法setAppProperties,我們可以通過這個(gè)方法來對(duì)已經(jīng)創(chuàng)建的View傳遞參數(shù)卵迂。

  • Java代碼:通過setAppProperties屬性向已創(chuàng)建的View傳遞參數(shù)
protected void onCreate(Bundle savedInstanceState) {
    ...
    
    mockData.putString("content", "重加載");
    mReactRootView.setAppProperties(mockData);
    
    ...
}
    

重新編譯代碼后裕便,再次運(yùn)行App,可以看到界面變成如下的樣子

6.2见咒、ReactNative向原生傳遞數(shù)據(jù)

我們使用ReactContextBaseJavaModule來定義一個(gè)ReactNative中的NativeModules類型偿衰。在ReactContextBaseJavaModule中,我們可以使用@ReactMethod注解來提供結(jié)構(gòu)供腳本回調(diào)改览。

首先我們創(chuàng)建一個(gè)MyReactNativeBridge.swift文件

package com.example.reactnativedemo;

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

public class MyReactNativeCommunication extends ReactContextBaseJavaModule {


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


    //提供Test方法
    @ReactMethod
    public void test(String str) {
        System.out.println(str);
    }

    //提供在NativeModules中該類的名字
    @Override
    public String getName() {
        return "MyReactNativeCommunication";
    }


}


然后我們使用MyReactNativePackage來注冊(cè)這個(gè)類下翎,否則腳本無法使用

package com.example.reactnativedemo;

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 MyReactNativePackage 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 MyReactNativeCommunication(reactContext));

        return modules;
    }

}

然后在MyReactNativeBridge將MyReactNativePackage添加到mReactInstanceManager中

public class MyReactNativeBridge {

    private static final ReactInstanceManager mReactInstanceManager = ReactInstanceManager.builder()
            .setApplication(MyApplication.getInstance())
            .setBundleAssetName("index.android.bundle")
            .setJSMainModulePath("Scripts/index")
            .addPackage(new MainReactPackage())
            .addPackage(new MyReactNativePackage())//新增MyReactNativePackage
            .setUseDeveloperSupport(BuildConfig.DEBUG)
            .setInitialLifecycleState(LifecycleState.RESUMED)
            .setCurrentActivity(MyApplication.getInstance().getCurrentActivity())
            .build();
}

最后修改JS代碼,調(diào)用test方法

import { NativeModules } from 'react-native'


export default class FrameText extends Component {

    render() {
        NativeModules.MyReactNativeCommunication.test("我回來啦");
        ...
    }
}

重新編譯代碼后宝当,再次運(yùn)行App视事,可以看到Android的輸出 “我回來啦”

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市庆揩,隨后出現(xiàn)的幾起案子俐东,更是在濱河造成了極大的恐慌,老刑警劉巖订晌,帶你破解...
    沈念sama閱讀 216,324評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件虏辫,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡腾仅,警方通過查閱死者的電腦和手機(jī)乒裆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門套利,熙熙樓的掌柜王于貴愁眉苦臉地迎上來推励,“玉大人,你說我怎么就攤上這事肉迫⊙榇牵” “怎么了沸久?”我有些...
    開封第一講書人閱讀 162,328評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵堪旧,是天一觀的道長(zhǎng)惭等。 經(jīng)常有香客問我项戴,道長(zhǎng)叙凡,這世上最難降的妖魔是什么韩脑? 我笑而不...
    開封第一講書人閱讀 58,147評(píng)論 1 292
  • 正文 為了忘掉前任直撤,我火速辦了婚禮哎榴,結(jié)果婚禮上寝杖,老公的妹妹穿的比我還像新娘违施。我一直安慰自己,他們只是感情好瑟幕,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評(píng)論 6 388
  • 文/花漫 我一把揭開白布磕蒲。 她就那樣靜靜地躺著留潦,像睡著了一般。 火紅的嫁衣襯著肌膚如雪辣往。 梳的紋絲不亂的頭發(fā)上兔院,一...
    開封第一講書人閱讀 51,115評(píng)論 1 296
  • 那天,我揣著相機(jī)與錄音站削,去河邊找鬼坊萝。 笑死,一個(gè)胖子當(dāng)著我的面吹牛许起,可吹牛的內(nèi)容都是我干的屹堰。 我是一名探鬼主播,決...
    沈念sama閱讀 40,025評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼街氢,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼扯键!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起珊肃,我...
    開封第一講書人閱讀 38,867評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤荣刑,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后伦乔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體厉亏,經(jīng)...
    沈念sama閱讀 45,307評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評(píng)論 2 332
  • 正文 我和宋清朗相戀三年烈和,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了爱只。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,688評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡招刹,死狀恐怖恬试,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情疯暑,我是刑警寧澤训柴,帶...
    沈念sama閱讀 35,409評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站妇拯,受9級(jí)特大地震影響幻馁,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜越锈,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評(píng)論 3 325
  • 文/蒙蒙 一仗嗦、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧甘凭,春花似錦稀拐、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽贡翘。三九已至,卻和暖如春砰逻,著一層夾襖步出監(jiān)牢的瞬間鸣驱,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評(píng)論 1 268
  • 我被黑心中介騙來泰國(guó)打工蝠咆, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留踊东,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,685評(píng)論 2 368
  • 正文 我出身青樓刚操,卻偏偏與公主長(zhǎng)得像闸翅,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子菊霜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容