rn如何测试数据请求时间_React Native代码执行跟踪和调试

在本地开发时, React Native 是加载本地Node服务, 可以通过npm start 启动, package.json 代码如下:"scripts": {"start": "node node_modules/react-native/local-cli/cli.js start"}首次在电脑上面打开该地址,被庞大的源代码吓一跳。一个简单的HelloWorld App 足足有5万多行JS...
摘要由CSDN通过智能技术生成

在本地开发时, React Native 是加载本地Node服务, 可以通过npm start 启动, package.json 代码如下:

"scripts": {

"start": "node node_modules/react-native/local-cli/cli.js start"

}

首次在电脑上面打开该地址,被庞大的源代码吓一跳。一个简单的HelloWorld App 足足有5万多行JS代码(开发模式)。仔细分析和梳理调用流程后,也没有那么的恐怖。代码主要包括React源码, 所有初始化定义的Native组件定义,Bridge层调用相关的MessageQueue,NativeModules,原生JS常用方法polyfill等代码定义实现。

如果是正式发布包,在应用运行时,是不存在本地nodejs服务器这个概念的,所以JS整合文件都是预先打包到asset资源文件里的,减少网络下载JS耗时。当然也可以从网络下载JSBundle,这时就需要考虑首次启动下载JSBundle的网络耗时和下载失败的情况处理。在项目开发时,其实可以在打包时内置一份JSBundle文件,然后启动后异步去下载最新JSBundle,下次启动时就可以加载新的JSBundle。

针对如此庞大的JSBundle文件,首次启动加载和解析的性能如何呢?

一.远程本地调试

通过创建ReactInstanceManager.builder 设置setUseDeveloperSupport(true)支持远程本地调试。

远程调试时,如果是通过Android studio 打包时,可以先通过npm start启动启动本地服务,启动后服务地址:

如果想加载asset下的JSBundle文件,需要先把JSBundle打到本地assets目录下面,可以通过react-native bundle实现。命令自动会分析图片依赖,然后拷贝到res目录下面。

react-native bundle --entry-file ./index.android.js --bundle-output ./app/src/main/assets/index.android.jsbundle --platform android --assets-dest ./app/src/main/res/ --dev false

然后setUseDeveloperSupport(false),之后重新打包即可。

二.远程加载JSBundle文件

在ReactInstanceManager 类里面提供了setJSBundleFile方法,这个就是动态更新的入口.

public Builder setJSBundleFile(String jsBundleFile) {

mJSBundleFile = jsBundleFile;

return this;

}

由于React Native加载的js文件都打包在bundle中,通过这个方法,可以设置app加载的bundle来源。若检测到远端存在更新的bundle文件,下载好后重新加载即可。

在ReactInstanceManager 类里面提供了recreateReactContextInBackground方法, 可以通过调用该方法重新加载JSBundle文件.

private void recreateReactContextInBackground(JavaScriptExecutor jsExecutor, JSBundleLoader jsBundleLoader) {

UiThreadUtil.assertOnUiThread();

ReactContextInitParams initParams = new ReactContextInitParams(jsExecutor, jsBundleLoader);

if (!mIsContextInitAsyncTaskRunning) {

// No background task to create react context is currently running, create and execute one.

ReactContextInitAsyncTask initTask = new ReactContextInitAsyncTask();

initTask.execute(initParams);

mIsContextInitAsyncTaskRunning = true;

} else {

// Background task is currently running, queue up most recent init params to recreate context

// once task completes.

mPendingReactContextInitParams = initParams;

}

}

目前该方法访问权限上private,需要通过反射才能调用, 希望未来 React Native 能够从官方支持. 代码如下:

private void onJSBundleLoadedFromServer() {

try {

Class> RIManagerClazz = mReactInstanceManager.getClass();

Method method = RIManagerClazz.getDeclaredMethod("recreateReactContextInBackground", JavaScriptExecutor.class, JSBundleLoader.class);

method.setAccessible(true);

method.invoke(mReactInstanceManager, new JSCJavaScriptExecutor(),

JSBundleLoader.createFileLoader(getApplicationContext(), JS_BUNDLE_LOCAL_PATH));

} catch (NoSuchMethodException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

} catch (InvocationTargetException e) {

e.printStackTrace();

} catch (IllegalArgumentException e) {

e.printStackTrace();

}

}

三.开启ReactNative日志打印

React Native 增加了关键日志自定义listener回调接口MarkerListener,只要在React Activity onCreate设置ReactMarker.setMarkerListener方法,

实现MarkerListener接口logMarker方法,即可实现控制台日志打印。我们可以记录下每个关键路径的当前时间,即可计算出每个关键路径的执行时间。

ReactMarker.setMarkerListener(new ReactMarker.MarkerListener(){

@Override

public void logMarker(String name) {

Log.i("ReactNativeJS", name.toLowerCase() + " cost:" + System.currentTimeMillis());

}

});

09-03 20:33:47.637 I/ReactNativeJS: process_packages_end cost:1472387627637

09-03 20:33:47.637 I/ReactNativeJS: build_native_module_registry_start cost:1472387627637

09-03 20:33:47.639 I/ReactNativeJS: build_native_module_registry_end cost:1472387627639

09-03 20:33:47.646 I/ReactNativeJS: create_catalyst_instance_start cost:1472387627646

09-03 20:33:47.688 I/ReactNativeJS: create_catalyst_instance_end cost:1472387627688

09-03 20:33:47.688 I/ReactNativeJS: run_js_bundle_start cost:1472387627688

09-03 20:33:47.717 I/ReactNativeJS: loadapplicationscript_startstringconvert cost:1472387627717

09-03 20:33:47.833 I/ReactNativeJS: loadapplicationscript_endstringconvert cost:1472387627832

09-03 20:33:48.787 I/ReactNativeJS: create_react_context_end cost:1472387628786

09-03 20:33:48.787 I/ReactNativeJS: run_js_bundle_end c

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
React Native中实现侧滑菜单可以使用第三方组件库,如react-native-drawer、react-native-side-menu等,也可以自己手写实现。以下是手写实现的简单示例: 1. 安装react-native-gesture-handler库 ```bash npm install react-native-gesture-handler ``` 2. 在App.js中引入GestureHandlerRootView,并在render方法中添加侧滑菜单和主页布局 ```javascript import { GestureHandlerRootView } from 'react-native-gesture-handler'; class App extends Component { constructor(props) { super(props); this.state = { isMenuOpen: false, }; } render() { return ( <GestureHandlerRootView style={{ flex: 1 }}> <View style={{ flex: 1 }}> {this.state.isMenuOpen ? <View style={{ flex: 1, backgroundColor: 'white' }}> <Text>侧滑菜单</Text> </View> : <View style={{ flex: 1, backgroundColor: 'white' }}> <Text>主页布局</Text> </View> } </View> </GestureHandlerRootView> ); } } ``` 3. 添加手势识别和动画 ```javascript import { PanGestureHandler, State } from 'react-native-gesture-handler'; class App extends Component { constructor(props) { super(props); this.state = { isMenuOpen: false, gestureState: State.UNDETERMINED, translateX: new Animated.Value(0), }; this.onGestureEvent = Animated.event( [{ nativeEvent: { translationX: this.state.translateX } }], { useNativeDriver: true } ); } onHandlerStateChange = event => { if (event.nativeEvent.oldState === State.ACTIVE) { const { translationX } = event.nativeEvent; if (translationX < -50) { this.setState({ isMenuOpen: true }); Animated.spring(this.state.translateX, { toValue: -200, useNativeDriver: true, }).start(); } else { Animated.spring(this.state.translateX, { toValue: 0, useNativeDriver: true, }).start(); } } }; render() { return ( <GestureHandlerRootView style={{ flex: 1 }}> <View style={{ flex: 1 }}> <PanGestureHandler onGestureEvent={this.onGestureEvent} onHandlerStateChange={this.onHandlerStateChange} > <Animated.View style={{ flex: 1, transform: [{ translateX: this.state.translateX }], }} > {this.state.isMenuOpen ? <View style={{ flex: 1, backgroundColor: 'white' }}> <Text>侧滑菜单</Text> </View> : <View style={{ flex: 1, backgroundColor: 'white' }}> <Text>主页布局</Text> </View> } </Animated.View> </PanGestureHandler> </View> </GestureHandlerRootView> ); } } ``` 这样就可以实现一个简单的侧滑菜单了。需要注意的是,手写实现的侧滑菜单可能会存在一些问题,如滑动冲突、性能问题等,使用第三方组件库可以避免这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值