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);
其启动过程的有一个大致的示意图.
以上的最后模块就的调用到了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来完成注册.
源代码编译
好吧,我还没有弄,等下回再弄吧。