【React Native】在原生项目中集成之坑点总结
??大家座好,要开车了~~~ ??俺是一个非常谨慎的人,对RN这门技术没有十足的信心之前,是不会直接拿来做新项目的(否则填坑,就能让你哭晕在厕所~)。 ??但是还想要体验跨平台+实时发布带来的快感,最好不过的方法就是在现有的项目基础上进行改良,集成ReactNative框架,一个页面or一个View先使用RN搞起来(先挣它一个亿,慢慢来么,急什么),下面就是本人在Integration With Existing Apps (此处有英文显得高大上一些)的过程中踩得坑,又爬出来的过程,希望能对你有所帮助。 集成准备??这方面网络上有好多的文案可以借鉴,(ReactNative向导),内容主要介绍npm和node的一些安装操作,没有这些基础建设,RN搞不转,如果你使用的是MAC,大致的关系如下: 还有就是Android和IOS的开发环境搭建,没什么难度。 ??这里特别(记得是特别)需要提醒的地方就是compileSdkVersion及targetSdkVersion的版本问题(站好,要跳坑了)。 ??先介绍三个基础的概念:
??好的,在RN官网介绍中有这么一段文字
??Android 6.0对应API等级是23,为什么需要Android 6.0,因为ReactNative引用了23的资源文件,另外有个别RN方法有23的等级限制。因此 Error retrieving parent for item: No resource found that matches the given name 'xxx'.
??同理,如果遇到这类问题,也可以检查一下,使用的 ??接下来,通过 Error:错误: 程序包org.apache.http不存在
Error:错误: 程序包org.apache.http.message不存在
??对的,聪明的你肯定猜到了,Android API 23 移除了 android { useLibrary 'org.apache.http.legacy' }
??继续开车,此时我们还没有引入任何RN相关的依赖,好的 Java.lang.SecurityException: xxx was not granted this permission :android.permission.xxx
??机智的我,祭出了Google神器,最终定位到了 defaultConfig { minSdkVersion 16 targetSdkVersion 21 }
??车不能停,关注 <uses-sdk android:minsdkversion="11" android:targetsdkversion="21" tools:overridelibrary="com.facebook.react"></uses-sdk>
??但是切记小心使用,需要做好sdk版本兼容,小于16的版本,需要使用Native代码实现,或者跳转到空页面,否则会出现Crash。 ??ok,集成之前的准备工作,大致的坑点就这么多,如果有其他的坑点,欢迎留言。 增加JS到你的应用??这块非常简单,想遇到坑都很难。建议参考Add JS to your app 官网文档直接搞定。 引入react-native依赖按官方文档搞两件事情,首先添加react-native依赖,其次添加maven的url。 dependencies {
...
compile "com.facebook.react:react-native:+" // From node_modules.
}
allprojects {
repositories {
...
maven {
// All of React Native (JS,Android binaries) is installed from npm
url "$rootDir/../node_modules/react-native/android"
}
}
...
}
&幸运的事情发生了,编译项目错误提示如下: Failed to resolve : com.facebook.react:react-native:xxx
??这个错误很好理解,就是Gradle在编译的时候,不知道引入的是个什么鬼,所以无法下载相应的dependency。 ??尝试:开始以为是当前的react-native版本不在MavenCentral中,所以无法下载,于是打开Project Structure —> Dependencies —> Library Dependency —> 输入‘react-native’,确实给我返回了一个react-native的版本。选择引入后仍然出错(Cry,应该是姿势不对)。 ??仔细的阅读官方文档(要说英文官方文档还是挺牛的,好多国内的翻译文章,很缺少细节),发现正确姿势,react-native都是通过npm来安装的。 ??如果箭头指向的路径错误,将不能正确引入。因为我的应用结构采用的是eclipse的默认结构,所以我的修改方案为: maven {
url "$rootDir/node_modules/react-native/android"
}
成功引入,OY! ?重新编译程序,Word天 ???这是部分间接依赖的错误日志,这些是ReactNative引用的开源库,通过 compile react-native 会将间接依赖编译到程序中。知道少什么就好解决了,推荐的解决办法:
repositories{
jcenter()
mavenCentral()
}
如果你有更好的办法,麻烦给我留言奥~~ ???到这里其实我们已经成功了一大步了,喘口气让我们继续填坑,马上就要看到胜利的曙光了(OY) ??通过上面的编译问题中也能看出,ReactNative自带很多的依赖库,这对我们自己的程序来说,如果我们也引用了其中的部分依赖,就很容易造成包重复的问题,比如: Error:Execution failed for task ':processDebugAndroidTestResources'.
> Error: more than one library with package name 'android.support.v7.recyclerview' You can temporarily disable this error with android.enforceUniquePackageName=false However,this is temporary and will be enforced in 1.0
结构: more than one library with pachage name xxx
??解决的思路很简单,就是使用 dependencies {
compile('com.facebook.react:react-native:+') {
exclude module: 'recyclerview-v7'
exclude module: 'support-v4'
exclude group: 'com.nineoldandroids',module: 'library'
}
}
完美解决我的问题。下面是做过的错误重试及无效写法总结。 1). 因为ReactNative需要将所需的资源文件进行引入到当前项目中,如果所有的间接依赖都不进入,就会出现这个问题。 2). 如下的修改方案,将所有的support包进行屏蔽,同样会引发上面的错误。 compile('com.facebook.react:react-native:+') {
exclude group: 'com.android.support'
}
3). 可以说这是一个无效的写法,按着网上的很多文章的说法是ok的,但是我亲试却并没有起作用。 compile('com.facebook.react:react-native:+') {
exclude group: 'com.android.support',module:'support-v4'
exclude group: 'com.android.support',module:'support-v7-recyclerview'
}
??如果大家重试第三种方案之后是可以的,也可以给我留言,网上说只写group可以,只写module也可以,都写仍然可以。我验证的结果这种结论是不正确的。 为解决包重复的问题,给大家推荐一个gradle的命令,
能查看所有依赖使用的间接依赖及依赖版本。 项目中添加RN相关的Native代码??add-native-code详细讲解向原有项目添加ReactNativeActivity的相关代码,此处无坑,放心使用。 ??我在项目中尝试原生的LinearLayout使用ReactNativeView进行填充,把代码贴出来,仅供参考: private LinearLayout mReactNativeLayout;
private ReactRootView mReactRootView;
private ReactInstanceManager mReactInstanceManager;
private void initReactView(){
mReactNativeLayout = (LinearLayout) findViewById(R.id.react_native_layout);
mReactRootView = new ReactRootView(mContext);
mReactInstanceManager = ReactInstanceManager.builder()
.setApplication(((Activity)mContext).getApplication())
.setBundleAssetName("index.android.bundle")
.setJSMainModuleName("index.android")
.setNativeModuleCallExceptionHandler(new NativeModuleCallExceptionHandler() {
@Override
public void handleException(Exception e) {
}
})
.addPackage(new MainReactPackage())
.setUseDeveloperSupport(false)
.setInitialLifecycleState(LifecycleState.RESUMED)
.build();
mReactRootView.startReactApplication(mReactInstanceManager,"sampleScreenSaver",null);
mReactNativeLayout.addView(mReactRootView);
}
??有没有很腻害,ReactNative可以在原生的Activity、Fragment、View中任意添加,只要你喜欢。 运行程序千呼万唤屎出来,终于可以运行了。O(∩_∩)O哈哈~ ??车开起来,小坑填一下,就能抵达胜利的彼岸了。在这个过程中,我遇到一下几个小问题,我就按我遇到的问题的顺序梳理一下。 问题一: Packager can't listen on port 8081
??解决办法:可能是其他的packager正在运行,关闭其他的Pachager即可。 com.facebook.react.devsupport.JSException: Could not get BatchedBridge,make sure your bundle is packaged correctly
问题原因:没有找到执行的bundle文件。
$ react-native bundle --platform android --dev false --entry-file index.android.js --bundle-output assets/index.android.bundle --sourcemap-output assets/index.android.map --assets-dest res/
要根据自己的项目目录结构进行修改。 问题三 Duplicate module name: react-native-vector-icons
??解决方案:一个Application应用存在多个node_module文件引发的问题,可能在Library中也有node_module可以删除掉其中一个,让另一个去引用已经存在的就OK。 运行程序,成功 !!! 请为自己鼓掌。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |