React-native初體驗(安卓篇)


本篇文章主要包括兩方面,如何從0開始把RN(react-native)項目整合進入現有Android項目,以及我們做的第一個RN的上線項目遇到的一些坑。

 

初次做RN項目,我們選擇做了一個邏輯相對簡單的轉轉app內部的幫助中心項目。整個項目有4個頁面用的RN,其他頁面走的是native提供的統跳協議,跳轉到對應的native頁面或者是H5頁面。

 

整合RN到android項目中

react-native cli提供的init指令,可以幫助我們創建一個RN的工程,但是很多場景下RN都是移植進入原生android或者iOS中。例如應該如何實現,在Android頁面,點擊一個按鈕進入RN頁面呢?

 

下面是具體的實現過程。

 

 

1、新建一個Android項目

 

注意Minimum SDK選擇API23以上,一路next后finish。

 

2、添加JS

打開studio的Terminal窗口,輸入如下命令:

npm init
會讓你輸入一些初始化package.json 的配置信息,例如:

 

 

按照提示輸入就行了。
這一步完成之后,在項目的根目錄下就會生成package.json這個文件,下一步輸入:

 

npm install react@16.0.0-alpha.6 - -save
npm install react-native@^0.44.0 - -save

注意,一定優先安裝react哦

 

大約一兩分鍾的樣子(如果卡到這里了,看看安裝時是不是忘了配置鏡像),完成之后你的根目錄下會多了一個node_modules的文件夾,里面存放了下載好的React 和React Native。這里有童鞋可能會質疑為什么不把react和react-native的依賴直接寫入package.json中,然后直接npm install,如果這么做的化,npm run start啟動的時候會報如下的錯誤:

 

接下來把如下命令粘貼到package.json 文件下 scripts 標簽中

“start”: “node node_modules/react-native/local-cli/cli.js start”

下一步,在根目錄下創建index.android.js文件並把如下代碼粘貼到其中:

 

 

代碼很簡單,居中顯示一個HelloWorld。

 

3、項目配置(Android)

用android studio打開工程,修改android根目錄下Gradle Scripts的build.gradle(Module:app)文件添加如下內容,注意下面appcompat-v7版本為25.2.0,而且我把dependencies中test相關的依賴移除掉了,避免不必要的bug。

 

 

 

在build.gradle(Project:***)中添加依賴

 

 

繼續下一步,在AndroidManifest.xml中添加網絡訪問權限

 

4、創建Activity

以下幾步不要安裝官網的去做,官網的步驟太麻煩,而且很久沒有更新了。

1.新建一個Activity,讓其繼承ReactActivity,並重寫getMainComponentName(),返回我們在index.android.js中注冊的HelloWorld這個組件。

 

 

別忘了把這個activity加入app/manifests/AndroidManifest.xml文件中

 

2.自定義一個Application,繼承ReactApplication ,編寫以下代碼:

 

 

 

記得在AndroidManifest.xml中引用

android:name=”.App”

 

3.在目錄res/layout中增加activity_main.xml文件,內容如下:

 

 

 

在MainActivity中通過按鈕啟動我們的ReactNativeActivity

 

 

4.app/src/main下新建assets文件夾

運行如下命令

react-native start

 

然后直接在android studio工程中,點擊上方工具欄的“run”按鈕,應該就可以了。
如果卡在了這一步:

沒關系,用資源管理器打開你工程的根目錄,在此目錄下重新運行一個命令行並在其中輸入如下命令

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

 

完成之后assets目錄下會生成以下兩個文件

確認一下react native service處於運行狀態,然后正常運行你的APP,點擊start,如果出現

恭喜你!你已經成功入坑,但是,實際項目中並不是這么簡單!

 

 


 

項目實戰踩坑

 

1.技術棧

es6 + redux + react-redux + redux-thunk + react-navigation

 

2.項目心得

這個項目踩坑最多的地方還是在react-navigation的使用上:

 

1、同一頁面參數不同,多次回退始終進入同一個頁面:
比如詳情頁頁面a/cateId/xy,當傳入不同cateId參數“cd”跳轉到同一詳情頁a/cateId/cd的時候,頁面是正常改變的,但是回退的時候,第一次是回到a/cateId/cd,再次回退還是回到a/cateId/cd。不會觸發頁面render。
stackNavigator導航管理的頁面,在切換的時候,不是按照堆棧的push,pop形式,而是通過移動指針到對應的頁面,同時標記此頁面為激活狀態。

 

解決辦法是通過componentWillReceiveProps,shouldComponentUpdate以及componentDidUpdate,當nextProps中的params.cateId和當前的params.cateId不同的時候,觸發頁面的render。

 

2、實現手勢swipe向右滑動后退功能:
官方文檔介紹,react-navigation在根組件的navigationOptions設置中添加gesturesEnabled: true,就可以實現滑動切換切換頁面的需求,但是在真機上測試不生效。
通過讀源碼了解到,react-navigation內部是通過引入RN的PanResponder手勢識別系統來實現滑動的機制,只有在onMoveShouldSetPanResponder返回true的時候,才能執行接下來的手勢動作。具體執行方法如下:

 

 

因為上述代碼中的 GESTURE_RESPONSE_DISTANCE_HORIZONTAL 過小,導致始終return false,把這個值從20改到60就可以了。

 

3、實現頁面跳轉動畫效果

StackNavigator(RouteConfigs, StackNavigatorConfig);

 

在第二個參數StackNavigatorConfig的配置中,可以傳入mode: ‘card’,這個參數會在native端獲取默認的滑動效果,iOS端默認的是左右切換的效果,但是android端默認的是上下切換效果。為了實現統一的過場效果。
幸好react-navigation提供了一個transitionConfig接口,可以實現定制化滑屏效果。不知道該如何定制么?沒有關系,源碼中已經在iOS端幫我們實現,稍微修改一下代碼就可以了。

 

 

FlatList問題:

1.ListHeaderComponent,ListFooterComponent
當FlatList有並列的組件的時候,會出現,其他並列的組件位置是固定的(類似於css中的position fixed),頁面只有FlatList區域是可以滾動的,為了實現這個頁面整體是可以滾動的,需要把FlatList上面的組件加入FlatList的ListHeaderComponent屬性中,同時把其下面的組件加入到ListFooterComponent中。

2.通過利用getItemLayout,把高度提前設定好,可以較少一次RN計算高度的render。

 

圖片問題:

1.RN中的圖片有兩種來源:native內部圖片,cdn的圖片。
native內部圖片,直接可以通過require圖片名字取到,一定不要加.png等后綴。
例如:

 

 

當然我們可以通過在打包的時候把通過相對路徑引入的內部圖片,

例如:

 

 

通過配置–asset-dest打包進入native原生目錄res中,這時候要注意,打出來的RN的bundle,只有放入android的assets文件夾下才能根據相對路徑取到這些存放在res目錄中的圖片。

cdn的圖片,只有指定圖片的寬高才能夠顯示出來。

與native交互的處理

  1. NativeModules:native暴露出來的模塊,可以通過NativeModules對象取到。

  2. 有些場景需要native直接傳遞某些參數到RN端,iOS可以通過調用initWithBundleURL,在initialProperties參數傳參,android通過getLaunchOptions把參數寫入返回的bundle中。在RN工程的根文件(例如app.js),通過this.props.key(key是屬性名字)直接取到。

 

 如果你喜歡我們的文章,關注我們的公眾號和我們互動吧。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM