Android開發學習之路--React-Native混合開發初體驗

東月之神發表於2018-07-20

準備

1. Expo嚐鮮

1.1 環境安裝:

  • 1.1.1 npm來安裝create-react-native-app命令列
npm install -g create-react-native-app
  • 1.1.2 建立一個名為“RNExpo”的新的React Native專案
create-react-native-app RNExpo
cd RNExpo
npm start

然後到iOS和android應用商店下載App“Expo”, 掃描二維碼就可以看到效果了。

注:其中ios直接開啟相機掃描識別即可

2. Android混合開發

2.1 gradle配置

  • 2.1.1 修改主工程build.gradle:
allprojects {
    repositories {
        maven{ url "$rootDir/node_modules/react-native/android"}
    }
}

其中url的路徑需要修改為對應的node_modules的的react-native的路徑。

  • 2.1.2 修改app中的build.gradle:
compile "com.facebook.react:react-native:+" // From node_modules.

這裡加上react-native的依賴

2.2 註冊ReactNativeHost

  • 2.2.1 新建MyReactPackage,包含需要暴露的模組
public class MyReactPackage implements ReactPackage {

    public UserInfoModule userInfoModule;

    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
        userInfoModule = new UserInfoModule(reactContext);
        modules.add(userInfoModule);
        return modules;
    }

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
}

這裡主要是為了實現js與原生的互動。可以增加更多的module。

  • 2.2.2 建立一個ReactContextBaseJavaModule

這裡暴露使用者的一些資料定義為UserInfoModule

public class UserInfoModule extends ReactContextBaseJavaModule {

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

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

    @ReactMethod
    public void rnCallNativeFromPromise(String msg, Promise promise) {

        Log.e("---", "adasdasda");
        // 1.處理業務邏輯...
        String result = "處理結果:" + msg;
        // 2.回撥RN,即將處理結果返回給RN
        promise.resolve(result);
    }
}

暴露了rnCallNativeFromPromise方法。需要使用@ReactMethod註解

  • 2.2.3 Application實現ReactApplication
public class MyApplication extends Application implements ReactApplication {

    private static final MyReactPackage myReactPackage = new MyReactPackage();

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

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

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

    /**
     * 獲取 reactPackage
     * @return
     */
    public static MyReactPackage getReactPackage() {
        return myReactPackage;
    }
}

到此基本上前期環境都已經搭建ok了。

2.3 新建ReactActivity

新建MyReactActivity

public class MyReactActivity extends ReactActivity {

    @Nullable
    @Override
    protected String getMainComponentName() {
        return "App";
    }
}

這裡的getMainComponentName就是js中

AppRegistry.registerComponent('App', () => App);

這樣我們就新建了一個Activity,實際載入的js的component就會在這個activity中渲染了。

3. Js開發

基於1中的腳手架create-react-native-app生成的專案,接著開發。

3.1 暴露

npm run eject

不過暴露之後用不了expo了

3.2 支援TypeScript

TypeScript支援更多的語法糖和型別。

  • 3.2.1 安裝typescript
cd RNExpo
npm install -g typescript
npm install typescript
tsc --init

# 未安裝 tsd 則先安裝再進行專案初始化
npm install -g tsd

tsd init && tsd install react-native --save
  • 3.2.2 配置tsconfig.json
{
  "compilerOptions": {
    "target": "es6",
    //    "allowJs": true,
    "jsx": "react",
    //    "outDir": "./dist",
    "sourceMap": false,
    "noImplicitAny": false,
    "skipLibCheck": true
  },
  "include": [
    "typings/**/*.d.ts",
    "*.ts",
    "*.tsx"
  ],
  "exclude": [
    "node_modules"
  ]
}
  • 3.2.3 安裝@types/xxx
    在使用typescript的第三方開源元件時候,需要安裝對應的typescript的元件,如下所示:
npm install @types/react
npm install @types/react-dom
npm install @types/react-native
npm install @types/react-native-swiper
npm install @types/react-navigation
  • 3.2.4 編譯
tsc

編譯成功後會在對應的xxx.tsx下有個xxx.js。因為實際我們還是執行的js程式碼。

3.3 新建App.tsx

新建Component

import * as React from 'react'
import {StyleSheet, Text, View} from 'react-native';

function hello(): string {
    return 'Hello React Native!'
}

export default class App extends React.Component {

    render() {
        return (
            <View style={styles.container}>
                <Text>{hello()}</Text>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: '#fff',
        alignItems: 'center',
        justifyContent: 'center',
    },
});

在index.js中註冊App

import {AppRegistry} from 'react-native';
import HelloRNActivity from "App";

AppRegistry.registerComponent("App", () => App);

3.4 打包

  • 3.4.1 安裝react-native-cli
npm install -g react-native-cli
  • 3.4.2 打包到Android的assets中
    這裡實現了一個指令碼 install.sh,實現如下所示:
#!/bin/sh

ASSETS_PATH="../XXX/RNAndroid/src/main/assets"
RES_PATH="../XXX/RNAndroid/src/main/res/drawable-mdpi"

if [ ! -d "output" ]; then
    mkdir -p output/bundle
    mkdir -p output/res
fi

react-native bundle --platform android --dev false --entry-file index.js --bundle-output output/bundle/index.android.bundle --assets-dest output/res/

if [ ! -d "$ASSETS_PATH" ]; then
    mkdir -p $ASSETS_PATH
fi

if [ ! -d "$RES_PATH" ]; then
    mkdir -p $RES_PATH
fi

cp output/bundle/* $ASSETS_PATH
cp output/res/drawable-mdpi/* $RES_PATH

該指令碼會把需要的bundle檔案和資原始檔拷貝到Android的工程專案中。

相關文章