ag真人从零开始的RxJava2,原生Android项目嵌入Rea

2019-09-18 22:43栏目:专项工作
TAG:

原创版权申明:本文章从本人 csdn 博客转到简书。如有转载,请申明:转载自 IT天宇:

首先需要先安装环境 这里就直接引用官方文档地址了,如果没有配置环境的话,请先配置一下环境。

个人博客搭建完成,欢迎大家来访问哦黎默丶lymoo的博客

由于是转过来的文章,决定把 1-4 篇合并到一篇。此外,还修正了部分过时的内容。

搭建开发环境

ag真人,React是一个用于构建用户界面的JavaScript库,而不是一个MVC框架,但可以使用React作为MVC架构的View层轻易的在已有项目中使用。React起源于Facebook的内部项目,用来架设Instagram的网站,并于2013年5月开源。React拥有较高的性能,代码逻辑非常简单,越来越多的人已开始关注和使用它。

RxJava这些年越来越流行,而上月末(2016.10.29)发布了2.0正式版,但网上大部分关于RxJava的教程都是1.x的。关于2.0的教程基本是介绍1.x2.x的区别,对于RxJava的老用户来说,自然看看和1.x的区别就大致会用了,但是对于新手来说,就不得不先学1.x。这样来说,学习成本就提高了,本身RxJava就不容易上手。

使用Android新建项目 最低版本需要设置为16 因为RN只支持最低版本为16

以前没有ajax技术的时候,web页面从服务端整体渲染出html输出到浏览器端进行渲染,同样的,用户的一个改变页面的操作也会刷新整个页面来完成。直到有了ajax出现,实现页面局部刷新,带来的高效和分离让web开发者们惊叹不已。但随之而来的问题是,复杂的用户交互及展现需要通过大量的DOM操作来完成,这让页面的性能以及开发的效率又出现了新的瓶颈。时至今日,谈到前端性能优化,减少DOM元素、减少reflow和repaint、编码过程中尽量减少DOM的查询等手段是大家耳熟能详的。而页面任何UI的变化都是通过整体刷新来完成的。幸运的是,React通过自己实现的DOM Diff算法,计算出虚拟页面当前版本和新版本之间的差异,最小化重绘,避免不必要的DOM操作,解决了这两个公认的前端性能瓶颈,实现高效DOM渲染。我们知道,频繁的操作DOM所带来的性能消耗是很大的,而React之所以快,是因为它不直接操作DOM,而是引进虚拟DOM的实现来解决这个问题对于页面的更新,React通过自己实现的DOM Diff算法来进行差异对比、差异更新,反映到页面上就是只重绘了更新的部分,从而提高渲染效率。

为了让年轻的司机可以直接从2.0开始学习,我就写了这篇文章。RxJava的老用户可以直接看我这篇文章 RxJava 2.0有什么不同。

打开CMD命令,切换到工程目录下面,执行npm init这时候终端会提示输入一些内容。name:工程名 (不能有大写 随意起就行了)version:(版本号 这里回车默认就好了)description:this is react native projectentry point:index.android.js(这是入口的js文件名)test command:git repository:(输入git地址或者回车)keywords:react nativeauthor:pencilsolicense:

在业务开发中,遇到公共的模板部分,我们不得不将模板和规定的数据格式耦合在一起来实现组件。而在React中,我们可以使用JSX语法来封装组件,将组件的结构、数据逻辑甚至样式都聚合在一起,更加简单、明了、直观的定义组件。有了组件化的实现,我们可以很直观的将一个复杂的页面分割成若干个独立组件,再将这些独立组件组合完成一个复杂的页面。这样既减少了逻辑复杂度,又实现了代码的重用。

ag真人 1

这时候你的项目根目录下应该有了一个package.json的文件,打开它,找到scripts这一栏,在text这个字段后面添加一个字段,"start": "node node_modules/react-native/local-cli/cli.js start" 贴一下完整的配置

首先我们需要获取到React的开发文件,可以从React官网下载相关配置文件,由于React用到的是JSX语法,浏览器是不能够直接进行解析的,还需要配置一个将JSX转换成JavaScript的文件,将链接中的代码复制到自己本地的任意新建的一个文件中保存完成配置,最后配置文件如下图所示:

由于本人文笔拙略,于是仿照着 Grokking RxJava 来写,望 Dan Lew 大大不要介意。

{ "name": "reactnative", "version": "1.0.0", "description": "no description", "main": "index.android.js", "scripts": { "test": "echo "Error: no test specified" && exit 1", "start": "node node_modules/react-native/local-cli/cli.js start" }, "keywords": [ "react", "native" ], "author": "pencilso", "license": "ISC"}

ag真人 2React所需的环境配置文件

RxJava 2.0 最核心的是PublisherSubscriberPublisher可以发出一系列的事件,而Subscriber负责和处理这些事件。

这时候 JSON文件已经配置好了,接下来该安装React Native了使用终端 切换到工程目录下 执行 npm install --save react react-native然后静静的等待好一会,就可以了,速度跟网络有关,如果没有设置阿里的镜像源的话,是需要科学上网才能安装的。设置阿里镜像源请查看搭建开发环境

新建一个HTML文件进行如下配置,当这个文件配置好之后,以后需要开发React的程序都可以以这个为模板进行开发。

平常用得最多的PublisherFlowable,它支持背压,教程刚开始不适合介绍太多概念,有兴趣的可以看一下 RxJava 2.0中backpressure概念的理解。

可选操作 :curl -o .flowconfig https://raw.githubusercontent.com/facebook/react-native/master/.flowconfig在工程目录下终端执行,下载这个.flowconfig文件,如果你是windows系统,而且没有curl这个命令又想下载的话。很简单,打开你的下载工具,比如说迅雷,粘贴这个地址https://raw.githubusercontent.com/facebook/react-native/master/.flowconfig然后复制到迅雷里面新建任务,开始下载。如果下载下来的文件名不是.flowconfig的话,就需要重命名。然而右键文件重命名是不行的,需要cmd命令 ren 旧文件名 新文件名 比如:ren a.txt .flowconfig然后将该文件,复制到工程目录下即可。
<!DOCTYPE html><html> <head> <meta charset="utf-8"> <title></title> <!--引入react核心库--> <script type="text/javascript" src="build/react.js"></script> <!--引入react的DOM操作--> <script type="text/javascript" src="build/react-dom.js"></script> <!--把JSX语法转换成浏览器能识别的JavaScript--> <script type="text/javascript" src="build/browser.min.js"></script> </head> <body> <!--把通过react生成的DOM放置在#container里面--> <div ></div> </body> <!--写JSX的地方需要设置为text/babel--> <script type="text/babel"> // 在这里写react代码 </script></html>

要使用RxJava 2,你需要先引入相应的jar包。

配置RN的依赖 打开工程下的build.gradle文件 找到allprojects这一栏 加入maven配置 。

上文提到的JSX是什么东西呢?其实JSX是一种语法,不是一门新的语言,它既包括JavaScript和Xhtml语言,XHTML用标签来进行表示,JavaScript用{}展示。这里主要注意的是写JSX的地方需要设置为text/babel,以及内部的书写规范

compile 'io.reactivex.rxjava2:rxjava:2.0.0'
allprojects { repositories { jcenter() maven { // All of React Native (JS, Android binaries) is installed from npm url "$rootDir/node_modules/react-native/android" } }}

这里举一个例子展示一个最简单的React程序因为React放置的是虚拟的DOM结构,我们需要将它渲染至页面上,它提供的语法为ReactDOM.render()它里面可以有三个参数,第一个为我们想要渲染至页面上的DOM元素,第二个为我们想在页面的哪个节点元素中进行渲染,第三个为渲染成功以后的回调

创建一个Flowable对象很简单,直接调用Flowable.create即可。

然后打开你的Module中的build.gradle文件

<!DOCTYPE html><html> <head> <meta charset="utf-8"> <title></title> <script type="text/javascript" src="build/react.js"></script> <script type="text/javascript" src="build/react-dom.js"></script> <script type="text/javascript" src="build/browser.min.js"></script> </head> <body> <div ></div> </body> <script type="text/babel"> var name = "zhangsan"; ReactDOM.render( <h1>hello {name}</h1>, document.getElementById("container") ); // 这里有第二种写法 ReactDOM.render( React.createElement("h1", null, "hello " + name), document.getElementById("container") ) </script></html>
// create a flowableFlowable<String> flowable = Flowable.create(new FlowableOnSubscribe<String>() { @Override public void subscribe(FlowableEmitter<String> e) throws Exception { e.onNext("hello RxJava 2"); e.onComplete(); }}, BackpressureStrategy.BUFFER);
在dependencies里面添加RN依赖。compile "com.facebook.react:react-native:+" // From node_modules.然后找到android 这个配置里面 加入:configurations.all { resolutionStrategy.force 'com.google.code.findbugs:jsr305:1.3.9'}找到defaultConfig这个配置 加上ndk支持 注意 一定要加:ndk { abiFilters "armeabi", "armeabi-v7a", "x86", "mips"}然后重新build一下

展示的效果为

上述代码仅仅是发射了一个字符串"hello RxJava 2"。下面我们还需要创建一个Subscriber

ag真人 3

ag真人 4React示例如果想要渲染出多个相同标签的不同内容,React也提供了一种方式,用key来确定标签的不同,以下展示部分script代码

// createSubscriber subscriber = new Subscriber<String>() { @Override public void onSubscribe(Subscription s) { System.out.println("onSubscribe"); s.request(Long.MAX_VALUE); } @Override public void onNext { System.out.println; } @Override public void onError(Throwable t) { } @Override public void onComplete() { System.out.println("onComplete"); }};

在你的工程目录创建一个文件,即配置package.json的时候输入的入口js文件名

index.android.js创建这个文件之后 把下面的代码粘贴进去就好了

var names = ["Alice", "Cindy", "Rose"];ReactDOM.render( <ul> { names.map(function (name, key) { return <li key={key}>{name}</li> }) } </ul>, document.getElementById("container"))

需要注意的是,在onSubscribe中,我们需要调用request去请求资源,参数就是要请求的数量,一般如果不限制请求数量,可以写成Long.MAX_VALUE。如果你不调用requestSubscriberonNextonComplete方法将不会被调用。

'use strict';import React from 'react';import { AppRegistry, StyleSheet, Text, View} from 'react-native';class HelloWorld extends React.Component { render() { return ( Hello, World ) }}var styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', }, hello: { fontSize: 20, textAlign: 'center', margin: 10, },});AppRegistry.registerComponent('HelloWorld', () => HelloWorld);

展示的效果为ag真人 5React示例

onNext方法里面传入的参数就是Flowable中发射出来的。

新建一个Activity,我起名叫ReactNativeActivity,用作React Native的界面。

需要注意一点 如果需要支持5.0以下的设备的话,需要继承AppCompatActivity。

另外这个Activity需要设置一下主题:Theme.AppCompat.Light.NoActionBar

如果你的Application本身就是这个主题的话就不用动了,否则的话,这里在清单文件给Activity单独配置一下吧。

在react中将一些重用的dom结构进行了封装,就称为组件,它便于我们进行代码管理以及代码复用

为了让"发射器"和"接收器"工作起来,我们还需要把他们组装在一起。

 android:name=".ReactNativeActivity" android:theme="@style/Theme.AppCompat.Light.NoActionBar" />

首字母必须大写,使用驼峰命名法

flowable.subscribe(subscriber);

直接贴Activity代码 在你的入口Activity写一个按钮使用Intent跳转到ReactNativeActivity即可

React提供了一个命令为React.createClass()来创建一个组件,它内部包含一个必须要有的方法render,用来返回一个或多个的DOM结构

一旦 flowable.subscribe 被执行,就会分别打印 hello RxJava 2onComplete

public class ReactNativeActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler { private ReactRootView mReactRootView; private ReactInstanceManager mReactInstanceManager; @Override public void invokeDefaultOnBackPressed() { super.onBackPressed(); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mReactRootView = new ReactRootView; mReactInstanceManager = ReactInstanceManager.builder() .setApplication(getApplication .setBundleAssetName("index.android.bundle") .setJSMainModuleName("index.android") .addPackage(new MainReactPackage .setUseDeveloperSupport(BuildConfig.DEBUG) .setInitialLifecycleState(LifecycleState.RESUMED) //.setUseOldBridge // uncomment this line if your app crashes .build(); mReactRootView.startReactApplication(mReactInstanceManager, "HelloWorld", null); setContentView(mReactRootView); } @Override protected void onPause() { super.onPause(); if (mReactInstanceManager != null) { mReactInstanceManager.onHostPause; } } @Override protected void onResume() { super.onResume(); if (mReactInstanceManager != null) { mReactInstanceManager.onHostResume(this, this); } } @Override protected void onDestroy() { super.onDestroy(); if (mReactInstanceManager != null) { mReactInstanceManager.onHostDestroy; } } @Override public void onBackPressed() { if (mReactInstanceManager != null) { mReactInstanceManager.onBackPressed(); } else { super.onBackPressed(); } } @Override public boolean onKeyUp(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) { mReactInstanceManager.showDevOptionsDialog(); return true; } return super.onKeyUp(keyCode, event); }}
var HelloMessage = React.createClass({ render: function () { return <h1>hello message</h1> }});

上面一大串代码仅仅就达到了打印两个字符串的效果,你可能会想:"RxJava只不过是把事情变复杂了"。或许是这样的,但RxJava也提供了很多便利的方法来做这种简单的事情。

有一点需要注意的是 Activity中的代码

mReactRootView.startReactApplication(mReactInstanceManager, "HelloWorld", null);

还有入口js中的代码

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

它们都有一个HelloWorld 这其实就是一个名字,不过Activity和js当中需要对应。

这样就简单的封装了一个名为HelloMessage的组件,如果想要调用这个组件,方法为

Flowable<String> flowable = Flowable.just("hello RxJava 2");
首先配置一下权限 <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW" /> 然后加入RN的设置Activity android:name="com.facebook.react.devsupport.DevSettingsActivity" android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
ReactDOM.render( <HelloMessage/>, document.getElementById("container"))

我们可以直接调用Flowable.just创建一个发射字符串的"发射器"。

基本上配置到这里就结束了,已经搭建完环境了。

Clean Project Rebuild Project 这两个都执行一下

接下来 打开终端 切换到工程目录,执行npm start(如果你只是嵌入而不需要开发RN的话,就不需要npm start启动服务了)

当终端出现以下界面的时候,恭喜你,你可以点击AS上的运行按钮了。

复合组件简单来说即是组件套用组件,我们来尝试封装一个复合组件

而对于 Subscriber 来说,我们目前仅仅关心onNext方法。所以可以简写成下面这样。

ag真人 6

var Component1 = React.createClass({ render: function () { return <h1>测试</h1> }});var Component2 = React.createClass({ render: function () { return <a href="http://www.baidu.com" target="_blank">去百度</a> }});var Component3 = React.createClass({ render: function () { return ( <div> <Component1/> <Component2/> </div> ) }});
Consumer consumer = new Consumer<String>() { @Override public void accept throws Exception { System.out.println; }};

运行跳转到RN的界面的时候,我相信你这时候应该报了一个错误:

Could not get BatchedBridge, make sure your bundle is packaged correctly

如果没出现的话,就跳过这一步吧

React有三种添加样式的方法

当然这只是一个 Consumer,但 subscribe 方法提供了重载,让我们可以只传入一个Consumer

打开终端 切换到项目目录 执行以下代码 注意:as默认创建的Module叫app,如果你的Module名字不叫app的话,需要将下面命令中的app改为你的Module名。成功后会在你的assets下面创建两个文件 (index.android.bundle index.android.bundle.meta)如果失败的话,尝试一下手动创建这两个空文件然后再执行命令。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/
var StyleTest = React.createClass({ render: function () { return <div style={{backgroundColor: "red", border: "10px solid #ccc"}}>Test</div> }});ReactDOM.render( <StyleTest/>, document.getElementById("container"))

所以订阅代码是这样的。

如果你的设备是>=6.0的话,我相信你这时候应该崩溃了。

没有悬浮窗权限 需要在跳转到ReactNative之前进行一下权限判断

直接贴代码

效果展示:ag真人 7React示例

flowable.subscribe;
@Overridepublic void onClick { if (Build.VERSION.SDK_INT >= 23) { if (!Settings.canDrawOverlays { Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION); startActivity; return; } } startActivity(new Intent(this, ReactNativeActivity.class));}

注意这里的styles都是以对象的格式进行书写的,千万不要以前的习惯后面写封号,字段名不加引号等等

如果省去单独定义变量,最终可以写成下面这样。

最后上一下运行效果图

var styles = { color: "blue", backgroundColor: "green"};var StyleTest = React.createClass({ render: function () { return <div style={styles}>Test</div> }});ReactDOM.render( <StyleTest/>, document.getElementById("container"))
Flowable.just("hello RxJava 2") .subscribe(new Consumer<String>() { @Override public void accept throws Exception { System.out.println;

ag真人 8

效果展示:ag真人 9React示例

让我们做一些更有意思的事情把!比如我想在hello RxJava 2后面加上我的签名,你可能会去修改Flowable传入的参数:

RN的坑,到此踩了一部分。好心塞。RN的官方文档都感觉不太全,比如说强制依赖的配置没写,比如RN的生命周期方法名都改变了,然而官方文档还是旧的方法名,最后进入ReactInstanceManager类当中查看源码才发现生命周期的方法名。

这个就和我们原来的CSS书写差不多,但是类名的添加不再是class,注意这里是className

Flowable.just("hello RxJava 2 -ittianyu") .subscribe(s -> System.out.println; 
<style> .styles{ color: yellow; background-color: black; }</style>var StyleTest = React.createClass({ render: function () { return <div className="styles">Test</div> }});ReactDOM.render( <StyleTest/>, document.getElementById("container"))

这当然是可以的,但是这样做,就导致所有的接收者都会受到影响。我只想针对某个订阅者做修改,那么你可能会写出这样的代码:

效果展示:ag真人 10React示例

版权声明:本文由ag真人发布于专项工作,转载请注明出处:ag真人从零开始的RxJava2,原生Android项目嵌入Rea