ReactNative了解(android)

ReactNative了解(android)

本文旨在对android 端的组件进行定制化,android原生中的实现方式,以及说明原生代码与js的交互过程

组件定制

以下的自定义模块都要加入一个ReactPackage,ReactPackage需要加入一个ReactNativeHost,这个步骤不做具体的说明,在以下的说明中都略过.在js中也需要进行必要的模块导入,相当于java中的包导入,也一起略过

在看组件定制之前先简单的了解下类的依赖关系.才知道组件可以怎么定制.

类图关系

View 定制

//本地的自定View,没有任何特殊的地方,与普通的自定义View是一样的
public class CustomView extends View {

    private String mText = "";

    public CustomView(Context context) {
        super(context);
    }

    public CustomView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint paint = new Paint();
        paint.setTextSize(50);
        paint.setColor(Color.RED);
        canvas.drawText(mText,0,100,paint);
    }


    public void setText(String text){
        mText = text;
        invalidate();
    }

}

//再通过ViewManager包装一下:
public class MyViewManager extends SimpleViewManager<CustomView> {

    @Override
    public String getName() {
        return "Custom";
    }

    @Override
    protected CustomView createViewInstance(ThemedReactContext reactContext) {
        return new CustomView(reactContext);
    }

//     通过@ReactProp(或@ReactPropGroup)注解来导出属性的设置方法
    @ReactProp(name = "text")
    public void setText(CustomView view,  @Nullable String text) {
        view.setText(text);
    }
}

js端进行调用

var requireNativeComponent = require('requireNativeComponent');
var Custom = {
    name:"Custom",
    propTypes:{
        text:PropTypes.string,
        ...View.propTypes
    },
};
var Customview = requireNativeComponent('Custom', Custom);

class HelloWorldApp extends Component {

  render() {
     if (Platform.OS === 'android') {
      TouchableElement = TouchableNativeFeedback;
    }
    let diaplayText = this.state.text;

    return (
    <View style={styles.container}>
         <Customview  text= "test" style={{width: 100, height: 100}} />
   </View>
    );
  }
}

NativeModule定制

public class MyModule extends ReactContextBaseJavaModule {

    public Context mContext;
    public MyModule(ReactApplicationContext reactContext) {
        super(reactContext);
        mContext = reactContext;
    }

    @Override
    public String getName() {
        return "MyModule";
    }

    @ReactMethod
    public void jump() {
        Intent intent = new Intent();
        intent.setClass(mContext, SecondActivity.class);
        mContext.startActivity(intent);
    }

    @ReactMethod
    public void test() {
        Toast.makeText(mContext,"test",Toast.LENGTH_SHORT).show();
    }

}

js端进行调用

export default class AwesomeProject extends Component {
  gotoSecond(){ 
        NativeModules.MyModule.jump();
   }
  render() {
    var TouchableElement = TouchableHighlight;
    if (Platform.OS === 'android') {
      TouchableElement = TouchableNativeFeedback;
    }
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>
          Welcome to React Native!
        </Text>
        <Text style={styles.instructions}>
          To get started, edit index.android.js 
        </Text>
        <Text style={styles.instructions}>
          Double tap R on your keyboard to reload,{'\n'}
          Shake or press menu button for dev menu
        </Text>
        <TouchableElement
          onPress={this.gotoSecond}
        >
          <Text style={styles.instructions}>
               点我点我
          </Text>
        </TouchableElement>
      </View>
    );
  }
}

JsModule定制 (官网上并没有说我该怎么弄)

//java端,需要配置与js端一样的接口
public interface MyJsModule extends JavaScriptModule {

     String getText(String string);

} 

//java端调用
  String text =  mReactInstanceManager.getCurrentReactContext().getJSModule(MyJsModule.class).getText("test");
Toast.makeText(ThreeActivity.this,"来自JS: "+text,Toast.LENGTH_SHORT).show();

js端也是要注册的

//创建一个MyJSModule.js的单独文件
'use strict';
const BatchedBridge = require('BatchedBridge');


const MyJsModule = {

    getText(param) {
        console.log(param);
        return "this is js Module";
    }
};
//要注册啊,大兄弟,这个方法要有的
BatchedBridge.registerCallableModule(
  'MyJsModule',
   MyJsModule
);
module.exports = MyJsModule;

---------------------------------
//在index.android.js中还需要引用啊
require('./MyJSModule.js');

Android中ReactNative处理流程

应用的启动流程

ReactNative本身是相当灵活的.可支持多种嵌套的方式,真正的启动的应用的时候只需要调用ReactRootView.startApplication即可.

不采用其封装的ReactActivity类,自己来启动ReactNative的过程.

       //重新创建,或者 通过ReactHost来处理
        mReactInstanceManager = ReactInstanceManager.builder()
                .setApplication(getApplication())
                .setBundleAssetName("index.android.bundle")
                .setJSMainModuleName("index.android")
                .addPackage(new MainReactPackage())
                .addPackage(new MyPackage())
                .setUseDeveloperSupport(BuildConfig.DEBUG)
                .setInitialLifecycleState(LifecycleState.RESUMED)
                .build();

     //真正的启动,只需要这两步骤,不过由于依赖于ReactInstanceManager,要先实例化它.
        mReactRootView = new ReactRootView(this);
        mReactRootView.startReactApplication(mReactInstanceManager, "AwesomeProject", null);

其启动过程的有一个大致的示意图.

我是图片啊

扫描二维码关注公众号,回复: 2881768 查看本文章

以上的最后模块就的调用到了js端的AppRegister.js(该文件位于:/node_modules/react-native/Libraries/ReactNative目录下面)
这里有一点值得说明的,通常是调用react-native run-android的方式来启动应用,不过其应用默认启动MainActivity的类.可以指定启动的Activity,通过命令加参数–main-activity.(该文件位于/node_modules/react-native/local-cli/runAndroid)

//文件中的参数值
module.exports = {
  name: 'run-android',
  description: 'builds your app and starts it on a connected Android emulator or device',
  func: runAndroid,
  options: [{
    command: '--install-debug',
  }, {
    command: '--root [string]',
    description: 'Override the root directory for the android build (which contains the android directory)',
    default: '',
  }, {
    command: '--flavor [string]',
    description: '--flavor has been deprecated. Use --variant instead',
  }, {
    command: '--variant [string]',
  }, {
    command: '--appFolder [string]',
    description: 'Specify a different application folder name for the android source.',
    default: 'app',
  }, {
    command: '--appIdSuffix [string]',
    description: 'Specify an applicationIdSuffix to launch after build.',
    default: '',
  }, {
    command: '--main-activity [string]',
    description: 'Name of the activity to start',
    default: 'MainActivity',
  }, {
    command: '--deviceId [string]',
    description: 'builds your app and starts it on a specific device/simulator with the ' +
      'given device id (listed by running "adb devices" on the command line).',
  }, {
    command: '--no-packager',
    description: 'Do not launch packager while building',
  }],
};

java与js相互调用

调用示意图
1.NativeModule的注册对于程序员来说是透明,只需要集成类加入Package就好了.
2.js端的模块注册需要手动的完成,通过BatchedBrige来完成注册.

源代码编译

好吧,我还没有弄,等下回再弄吧。

猜你喜欢

转载自blog.csdn.net/xjz729827161/article/details/77413001
今日推荐