android 架構之整合react native框架js混編APP
本篇文章主要總結一下現在APP當中使用的js、webView混編架構和技術。
什麼是 js 混編?
js混編簡單說就是使用JavaScript開發APP程式。
android應用使用的是java,Kotlin 、c/c++ 為主的語言開發,ios使用的object-c 、 swift、c/c++ 為主語言開發,由於市場是基本都是android和ios手機,所以一般公司開發什麼專案android和ios的APP都必須開發。android和ios都提供一個庫webkit瀏覽器引擎的支援,android提供了一個元件webView用於顯示網頁,相當於一個內建瀏覽器,ios也有類似一個元件UIWebView;webView和UIWebView也都支援js bridge的模式,就是js與java或者object-c進行互動,那麼就產生一種開發模式就是hybrid APP開發模式。
hybrid 應用
hybrid APP開發模式由於可以使用HTML5 、css、js進行大量UI開發得到了飛速的發展,到後面這類開發也出現很多優秀的框架例如:cordova(phoneGap) ionic 等,他們基本架構都是使用瀏覽器元件(webView,UIWebView)渲染UI,使用js呼叫原生程式碼執行手機功能。那麼隨後發展中hybrid應用也暴露很多問題。
hybrid 應用缺點
- UI渲染效能差,例如載入白屏,渲染卡頓
- 記憶體消耗高,主要是沒有優秀的回收複用機制,例如原生recyclerView
- 使用者互動差,使用者觸控反應遲鈍等
- UI渲染失真
那麼為了解決hybrid APP中的雞肋痛點,那麼也產生除了很多記得新js 混編開發框架,例如react native(facebook 公司出品), Xamarin(微軟公司出品,c#陣營,乾的也是跨平臺這檔子事);這種框架已經不再是hybrid模式,應該叫做js native APP 開發模式。
js native 應用(react native ,Xamarin )
js native 應用克服了很hybrid的缺點,他是通過js開發使用自定義封裝UI控制元件進行開發,最終打包成原生應用。
1、優點
- 原生級別的UI渲染
- 沒有通過webView來進行橋接,減少記憶體消耗
- 使用者體驗迅速,觸控流暢
- 提供原生方法呼叫自定義介面,和自定義UI元件的封裝使用,可以無縫對接你現在應用
- android和ios端高度UI一致性
其實缺點也是比較明顯,例如:
1、缺點
- 一定的學習成本,相當於學習新的開發技術
- 專案避免不了封裝自定義方法和UI控制元件,橋接程式碼多
- 專案維護成變高了
常用混編框架對比表
專案 | cordova(phoneGap) | react native | Xamarin | ionic |
---|---|---|---|---|
是否使用webView互動 | 是 | 否 | 否 | 是 |
是否具備自有UI元件 | 否 | 是 | 是 | 是 |
開源 | 是 | 是 | 是 | 是 |
是否打包成原生 | 否 | 是 | 是 | 否 |
具備定製IDE工具 | 否 | 是 | 是 | 否 |
開發語言 | js | js | c# | js |
推薦理由 | 前身phoneGap,歷史悠久 | facebook大廠背景,使用react js開發,提供了良好的呼叫原生api和UI元件機制 | 強烈推薦,超級大廠微軟支援,mono是後臺,匯出平臺不止是android 、iOS, 還有windows桌面程式 | 具備獨立js UI,建立在cordova之上 |
總體而言優點還是跨平臺,如果選擇js混編框架還是推薦使用react native。
react native整合進入android應用 ,加入js開發模式
操作步驟:
配置好React Native依賴和專案結構。
建立js檔案,編寫React Native元件的js程式碼。
在應用中新增一個RCTRootView。這個RCTRootView正是用來承載你的React Native元件的容器。
啟動React Native的Packager服務,執行應用。
驗證這部分元件是否正常工作。
開始前我們必須使用react native腳手架搭建出一個可以執行的hello world 專案,本文介紹主要是整合react native框架進入現有應用重點不是環境搭建,所以你可以自行百度react native官網的初始化專案文章。
假設你現在已經有了環境了和一個可以執行hello world 專案了 那麼我們可以開始接入現有應用了。
hello world 專案專案目錄如圖:
複製node_modules目錄和package.json進入你android專案跟目錄如圖:
建立index.android.js 檔案放入android根目錄,寫入程式碼:
'use strict';
import React from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
TouchableOpacity,
NativeModules,
ToastAndroid,
requireNativeComponent,
DeviceEventEmitte,
Alert
} from 'react-native';
class HelloWorld extends React.Component {
constructor(props) {
super(props);
}
componentWillMount() {
}
render() {
return (
<View style={styles.container}>
<Text style={{alignItems:'flex-start', backgroundColor:'red', height:49, textAlign:'right'}}>
作者jason 李
</Text>
</View>
)
}
}
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
flexDirection: 'column',
},
hello: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
});
AppRegistry.registerComponent('HelloWorlds', () => HelloWorld);
接下是android部分了:
在入口gradle檔案加入程式碼:
allprojects {
repositories {
google()
jcenter()
maven {
url "$rootDir/node_modules/react-native/android" //加入這句
}
}
}
在專案gradle檔案中加入依賴:
compile "com.facebook.react:react-native:0.55.3"
建立Application程式:
public class MyApplication 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()
);
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
}
建立react activity:
public class MyReactActivity extends Activity implements DefaultHardwareBackBtnHandler {
private ReactRootView mReactRootView;
private ReactInstanceManager mReactInstanceManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mReactRootView = new ReactRootView(this);
mReactInstanceManager = ReactInstanceManager.builder()
.setApplication(getApplication())
.setBundleAssetName("index.android.bundle")
.setJSMainModulePath("index")
.addPackage(new MainReactPackage())
.setUseDeveloperSupport(BuildConfig.DEBUG)
.setInitialLifecycleState(LifecycleState.RESUMED)
.build();
// 注意這裡的MyReactNativeApp必須對應“index.js”中的
// “AppRegistry.registerComponent()”的第一個引數
mReactRootView.startReactApplication(mReactInstanceManager, "HelloWorlds", null);
setContentView(mReactRootView);
}
@Override
public void invokeDefaultOnBackPressed() {
super.onBackPressed();
}
}
加入許可權:
<uses-permission android:name="android.permission.INTERNET" />
至此所有的配置結束!!!
執行測試
在目錄開啟cmd:輸入
yarn start
然後用Android studio執行你的專案!!