Android—React Native编程

个人博客:haichenyi.com。感谢关注

新公司,新的开始,新的技术

  新公司的项目,用到的RN编程,之前完全没有碰到过,遇到新技术,之前完全没有碰到过怎么办?google、百度咯。通过不屑的努力,找到了恋猫月亮 的三篇关于RN的文章。我感觉还是很不错的。

从Android到React Native开发(一、入门)

从Android到React Native开发(二、通信与模块实现)

从Android到React Native开发(三、自定义原生控件支持)

  可以先浏览上面的第一篇入门,再过来看我这篇文章,我这篇文章就是讲怎么运行一个RN,我只是针对我的项目,把RN的部分提取了出来,上面大佬讲的比较全面。

React Native环境配置

开发工具:android studio。我不知道为什么要换开发工具。AS不好吗?环境还是跟你之前开发的一样配置,不用变

python安装:python官网,下载安装。记得配置环境变量。不用非要按照他那个上面说的去安装。安装完成之后cmd里面敲python然后回车,看到如下界面:

python.png

node.js安装:node也是一样,百度安装,配置完环境变量。cmd里面敲 npm -v然后回车,看到如下界面

node.png

最后,跑如下命令:

//安装完node后建议设置npm镜像以加速后面的过程(或使用科学上网工具)。
npm config set registry https://registry.npm.taobao.org --global
npm config set disturl https://npm.taobao.org/dist --global
//React Native的命令行工具用于执行创建、初始化、更新项目、运行打包服务(packager)等任务。
npm install -g react-native-cli

  至此,RN的配置就完成了。记得配置NDK环境,然后就是上你们公司的svn,或者git去down项目下来,应该还会有一个错误,那就是找不到react.gradle的路径,找到你添加依赖的那个gradle,在最上面添加如下代码:

apply from: "../../node_modules/react-native/react.gradle"

这个配置应该是添加greenDao那个是一样的,这样就能找到了react.gradle

项目结构如下:

project.png

  我用箭头标记了,你down下来的项目,应该是没有node_modules文件夹的,这个文件夹是怎么产生的呢?你在cmd进入你down的项目,就是图片上面的文件目录,跑如下命令即可

npm install

当命令运行完,就可以跑项目了。

React Native项目搭建

  同鞋,你有freeStyle吗?有没有用过WebView?WebView就是在你的xml里面新增了一个WebView控件,RN也一样,他的这个控件就是ReactRootView。所以,这个控件哪里来?当然是添加依赖了

//版本号你自己找
compile 'com.facebook.react:react-native:0.50.3'

最终的作用代码就是:

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

  这个ReacRootView对象,你可以new出来,也可以写在xml里面findViewById。只要你能获取到这个对象就可以了,然后就是这个方法:

startReactApplication(ReactInstanceManager reactInstanceManager, String moduleName, @Nullable Bundle initialProperties)

三个参数

  1. ReactInstanceManager reactInstanceManager
  2. String moduleName
  3. @Nullable Bundle initialProperties

第一个参数:ReactInstanceManager

就像配置WebView的参数,那些什么配置client允许js弹窗啊,新的页面直接覆盖原来的页面,并不是新建一个页面之类的参数,对应的这里,就是配置ReactInstanceManager

ReactInstanceManagerBuilder builder = ReactInstanceManager.builder();
        builder = builder
                .setApplication(getApplication())
                .setBundleAssetName("index.android.bundle")
                .setJSMainModulePath("index.android");

        mReactInstanceManager = builder
                .addPackage(new MainReactPackage())
                .addPackage(new YzgHDReactPackage())
//                .setUseDeveloperSupport(!Global.ISPRD)
                .setUseDeveloperSupport(true)
              .setInitialLifecycleState(LifecycleState.RESUMED)
                .build();

  前面的builder的初始化是必须要写的,setApplication,如果你没有自己写application,那就直接getApplication,如果,你有自己实现application那就传你的application对象。

  setBundleAssetName和setJSMainModulePath都是写死的,后面的名字也是写死的。

  然后就是添加package,在package里面添加module。这里就是JS和Android相互调用的地方。package里面要实现ReactPackage,在createNativeModules里面去添加moudle

第二个参数:String moduleName

这个moudleName是怎么来的?就是我们前面设置的MoudlePath那个JS里面的。这里的路径应该是index.android.js,是一个js文件,打开之后,最下面有如下代码:

AppRegistry.registerComponent('zzz', () => XXX);

这里的zzz就是我们这里需要传的名字

第三个参数:Bundle initialProperties

这里应该是传一个bundle,传输的数据,传个null就可以了

React Native流程

  前面的整个配置都配置完成之后,Android这边只用新建方法,给RN调用就可以了。新建的方法要用@ReactMethod标记。辣么,这个方法新建在哪呢?————Module,就是对应我们前面package里面添加的module。都说RN每个模块是独立的,怎么独立呢?就是这样独立的。每个模块功能对应一个module,每个都有该功能对应的方法。我就拿我这里的UserModule来举个例子

public class UserModule extends IModule implements NoticeListener{


    public static final String MODULE_NAME = "User_Module";

    private ReactApplicationContext mContext;

    public UserModule(ReactApplicationContext reactContext) {
        super(reactContext);
        this.mContext = reactContext;
    }

    @Override
    public String getName() {
        return MODULE_NAME;
    }

    /**
     * 用户登录接口
     * @param params
     * @param callback
     */
    @ReactMethod
    public void doLogin(String params, final Callback callback){

        HashMap<String,String> map = GsonTool.gson2Map(params);

        if(map == null || map.size() <= 0){
            callback.invoke(new GsonBuilder().create().toJson(new BaseBean(false,"参数异常")));
            return;
        }
        final String userName = map.get("userName");
        final String password = map.get("password");

        if(TextUtils.isEmpty(userName) || TextUtils.isEmpty(password)){
            callback.invoke(new GsonBuilder().create().toJson(new BaseBean(false,"用户名或密码不能为空")));
            return;
        }
        //登录
        new Handler().post(new Runnable() {
            @Override
            public void run() {
                String result = new UserBridge().doLogin(userName,password, Global.DEVICE_ID,Global.APP_VERSION_NAME);
                callback.invoke(result);
            }
        });

    }

  这里我就粘贴出来了部分代码,module要继承IModule,这个是一个抽象类,他继承ReactContextBaseJavaModule,最主要就是继承它,继承之后,我像说的就是这两个方法,getName()和注解的方法doLogin()。

  我们可以看到,这个getName最终返回的是一个User_Module,这个字符串是怎么确定的呢?这个登录的方法名称是怎么确定的呢?

  这些东西都是在js里面定义好的,这里是一个登录方法,我们打开登录的js。

PS: 这里应该是通过js去确定我们这边的方法名,并不是通过这里的名称去确定js的。

  我就不把JS代码,贴出来了,只贴出伪代码,打开js之后,搜索NativeModules。你应该会搜到类似的代码:

const { User_Module, Shop_Module } = NativeModules;

这里有两个Module,没错,就是两个。我们这里现在只关注User_Module,然后,我们搜索 User_Module,你会看到如下代码:

_onLogIn = () => {

        const { username, password } = this.userInfo;
        if (username.length <= 0) return this._modal.Alert('请输入用户名');
        if (password.length <= 0) return this._modal.Alert('请输入密码');
        this._button.setButton(false, '正在登录...');
        const params = { userName: username, password };
        // 登录
        const _dologin = () => {
            return new Promise((resolve, reject) => {
                User_Module.doLogin(JSON.stringify(params), (...values) => {
                    const data = Other.callHandle(values) || {};
                    if (data.status) {
                        resolve('登录成功');
                    } else {
                        reject(data.message);
                    }
                });
            });
        };

其他的一切,我们都不用管,我们在意的是

User_Module.doLogin(JSON.stringify(params), (...values) => {
                    const data = Other.callHandle(values) || {};
                    if (data.status) {
                        resolve('登录成功');
                    } else {
                        reject(data.message);
                    }
                });

  上面这个是我的项目里面的js,你们搜到的肯定跟我的不一样,我这里要说的是,怎么确定name的返回值,和注解方法。我们看到了,name就是这里的User_Module,方法就是这里的doLogin,android里面写用@ReactMethod标记,然后就是参数了,这里两个参数,一个是String,json格式的。用ArrayMap存储好key—value之后,转成字符串即可。第二个参数就是callback。android与JS通信,发送数据,就是一个方法

callback.invoke("data")

他需要什么,你就发送什么。上面是RN主动调用Android方法,辣么,Android怎么主动调用RN方法呢?其实也很简单

//发送给RN
        if (mReactInstanceManager.getCurrentReactContext() != null) {
            mReactInstanceManager.getCurrentReactContext()
                    .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                    .emit(PUSH_DATA_RN, mqttBean.info);
        }

就是获取ReactContext对象,通过调用getJSModule方法,参数传DeviceEventManagerModule.RCTDeviceEventEmitter.class这个类就可以了,然后通过调用emit方法,第一个参数,就是RN规定的方法名称,第二个参数就是需要传给RN的数据。为什么这样写呢?我们再来看看RN那边是怎么写的

DeviceEventEmitter.addListener("push_data_rn",(data)=>{
            alert(data)
        })

他就是通过这DeviceEventEmitter类添加addListener方法,传两个参数,第一个参数就是我们规定的名称,第二个参数就是一个回调,有一个参数,就是用来接收我们的数据,最后做的处理就是简单的弹窗,当然,这是我自己测试用的,最后RN要怎么坐,就是我要担心的问题了。

猜你喜欢

转载自blog.csdn.net/qq_27634797/article/details/80266346