首页 文章 精选 留言 我的

精选列表

搜索[native],共6251篇文章
优秀的个人博客,低调大师

react native插件 react-navigation使用心得

StackNavigator StackNavigator(screens,configs) const Stack = StackNavigator({ Home: { screen: Home, }, Profile: { screen: Profile } },{ mode: 'card', // 页面切换模式, 左右是card(相当于iOS中的push效果), 上下是modal(相当于iOS中的modal效果) headerMode: 'screen', // 导航栏的显示模式, screen: 有渐变透明效果, float: 无透明效果, none: 隐藏导航栏 onTransitionStart: ()=>{ console.log('导航栏切换开始'); }, // 回调 onTransitionEnd: ()=>{ console.log('导航栏切换结束'); } // 回调 }); screen页面 export default class Home extends React.Component { //本页面的属性配置 static navigationOptions = { title: 'Home', } render() { return ( <View> <Text>Home</Text> </View> ) } }

优秀的个人博客,低调大师

Java代码引起的NATIVE野指针问题(下)

朴英敏,小米MIUI部门。从事嵌入式开发和调试工作8年多,擅长逆向分析方法,主要负责解决安卓系统稳定性问题。 实施hook: 我们有了hook,但目前还不知道是哪个so中释放了functor。 如果无法确定是哪个so,可以多hook几个so就行了。 当然对于特定的例子,也有技巧来确定so,比如我们这个例子: 被析构的对象是Functor类的对象,由于它的vtbl地址我们能够从log中获取到, 而vtbl一般指向定义了该类的so中,所以用vtbl值(0×73648de0)去map表中找,就能确定是哪个so了。 ... 73635000-73646000rw-p0000000000:000 73646000-73648000r-xp00000000b3:181287/system/lib/libwebviewchromium_plat_support.so =>73648000-73649000r--p00001000b3:181287/system/lib/libwebviewchromium_plat_support.so 73649000-7364a000rw-p00002000b3:181287/system/lib/libwebviewchromium_plat_support.so 7364a000-73684000rw-p0000000000:000 73684000-73696000r-xp00000000b3:181034/system/lib/libjavacrypto.so 73696000-73697000r--p00011000b3:181034/system/lib/libjavacrypto.so 73697000-73698000rw-p00012000b3:181034/system/lib/libjavacrypto.so ... 而需要注意的是,C++对象的释放是delete函数, libwebviewchromium_plat_support.so不会直接调用libc的free函数,而是调用libc++.so中的delete函数,再由delete函数调用free函数, 所以我们得hook libc++.so的free函数,但打印调用栈的模块也依赖libc++.so,所以如果在hook函数中打印调用栈,也会遇到死循环问题。 所以我们得hook libwebviewchromium_plat_support.so中的delete函数,这样既减少log量,也能避免死循环。 先确认libwebviewchromium_plat_support.so是否依赖了delete函数: $readelf-slibwebviewchromium_plat_support.so|grepUND 0:000000000NOTYPELOCALDEFAULTUND 1:000000000FUNCGLOBALDEFAULTUND__cxa_finalize 2:000000000FUNCGLOBALDEFAULTUND__cxa_atexit 4:000000000FUNCGLOBALDEFAULTUND__aeabi_unwind_cpp_pr0 5:000000000FUNCGLOBALDEFAULTUND__aeabi_unwind_cpp_pr1 6:000000000FUNCGLOBALDEFAULTUNDgetrlimit 7:000000000FUNCGLOBALDEFAULTUNDsetrlimit 8:000000000FUNCGLOBALDEFAULTUND__errno 9:000000000FUNCGLOBALDEFAULTUNDstrerror 10:000000000FUNCGLOBALDEFAULTUND__android_log_print =>11:000000000FUNCGLOBALDEFAULTUND_Znwj =>12:000000000FUNCGLOBALDEFAULTUND_ZdlPv 14:000000000FUNCGLOBALDEFAULTUND__android_log_assert ... 51:000000000FUNCGLOBALDEFAULTUND__aeabi_llsr 52:000000000OBJECTGLOBALDEFAULTUND__popcount_tab 其中11项_Znwj是new的符号,_ZdlPv是delete的符号。 接下来就用工具hook libwebviewchromium_plat_support.so的delete函数: externvoid_ZdlPv(void*); voidinject__ZdlPv(void*ptr){ LOGD("delete%p",ptr); dumpNativeStack(); dumpJavaStack(); _ZdlPv(ptr); } hook后复现问题,抓到的log如下: 10-2721:19:52.96180278027DObserverLayout:onStop:clz=com.miui.player.display.view.DisplayFragmentLayout{45665838V.E.............0,0-1080,1920#7f080039app:id/content} 10-2721:19:52.96580278027IMusicBaseFragment:onDestroyViewtheviewisstillattached,delaydestroy 10-2721:19:52.96680278027DINJECT:delete0x7a7b8530 10-2721:19:52.98680278027DINJECT:#00pc000015f6/system/lib/libinject.so(inject__ZdlPv+21) 10-2721:19:52.98680278027DINJECT:#01pc00001134/system/lib/libwebviewchromium_plat_supp 10-2721:19:52.98680278027DINJECT:#02pc00001088/system/lib/libwebviewchromium_plat_supp 10-2721:19:52.98780278027DINJECT:#03pc0001d30c/system/lib/libdvm.so(dvmPlatformInvoke+112) 10-2721:19:52.98780278027DINJECT:#04pc0004d8da/system/lib/libdvm.so(dvmCallJNIMethod(unsignedintconst*,JV+397) 10-2721:19:52.98780278027DINJECT:#05pc00026720/system/lib/libdvm.so 10-2721:19:52.98780278027DINJECT:#06pc0002d790/system/lib/libdvm.so(dvmMterpStd(Thread*)+76) 10-2721:19:52.98780278027DINJECT:#07pc0002adf4/system/lib/libdvm.so(dvmInterpret(Thread*,Methodconst*,JVa+184) 10-2721:19:52.98880278027DINJECT:#08pc00060058/system/lib/libdvm.so(dvmInvokeMethod(Object*,Methodconst*,+391) 10-2721:19:52.98880278027DINJECT:#09pc00067ff6/system/lib/libdvm.so 10-2721:19:52.98880278027DINJECT:#10pc00026720/system/lib/libdvm.so 10-2721:19:52.98880278027DINJECT:#11pc0002d790/system/lib/libdvm.so(dvmMterpStd(Thread*)+76) 10-2721:19:52.98880278027DINJECT:#12pc0002adf4/system/lib/libdvm.so(dvmInterpret(Thread*,Methodconst*,JVa+184) 10-2721:19:52.98880278027DINJECT:#13pc0005fd74/system/lib/libdvm.so(dvmCallMethodV(Thread*,Methodconst*,O+335) 10-2721:19:52.98880278027DINJECT:#14pc000494c2/system/lib/libdvm.so 10-2721:19:52.98980278027DINJECT:atcom.android.webview.chromium.DrawGLFunctor.nativeDestroyGLFunctor(NativeMethod) 10-2721:19:52.98980278027DINJECT:atcom.android.webview.chromium.DrawGLFunctor.access$000(DrawGLFunctor.java:31) 10-2721:19:52.98980278027DINJECT:atcom.android.webview.chromium.DrawGLFunctor$DestroyRunnable.run(DrawGLFunctor.java:91) 10-2721:19:52.98980278027DINJECT:atcom.android.org.chromium.content.common.CleanupReference.runCleanupTaskInternal(CleanupReference.java:159) 10-2721:19:52.98980278027DINJECT:atcom.android.org.chromium.content.common.CleanupReference.access$300(CleanupReference.java:32) 10-2721:19:52.98980278027DINJECT:atcom.android.org.chromium.content.common.CleanupReference$LazyHolder$1.handleMessage(CleanupReference.java:93) 10-2721:19:52.99080278027DINJECT:atcom.android.org.chromium.content.common.CleanupReference.handleOnUiThread(CleanupReference.java:147) 10-2721:19:52.99080278027DINJECT:atcom.android.org.chromium.content.common.CleanupReference.cleanupNow(CleanupReference.java:141) 10-2721:19:52.99080278027DINJECT:atcom.android.webview.chromium.DrawGLFunctor.destroy(DrawGLFunctor.java:46) 10-2721:19:52.99080278027DINJECT:atcom.android.webview.chromium.WebViewChromium.destroy(WebViewChromium.java:430) 10-2721:19:52.99080278027DINJECT:atandroid.webkit.WebView.destroy(WebView.java:667) 10-2721:19:52.99080278027DINJECT:atcom.xiaomi.music.hybrid.HybridFragment.destroyHybridView(HybridFragment.java:64) 10-2721:19:52.99080278027DINJECT:atcom.xiaomi.music.hybrid.HybridFragment.onDestroyView(HybridFragment.java:115) 10-2721:19:52.99080278027DINJECT:atcom.miui.player.component.MusicBaseFragment.onDestroyView(MusicBaseFragment.java:216) 10-2721:19:52.99180278027DINJECT:atandroid.app.Fragment.performDestroyView(Fragment.java:1898) 10-2721:19:52.99180278027DINJECT:atandroid.app.FragmentManagerImpl.moveToState(FragmentManager.java:954) 10-2721:19:52.99180278027DINJECT:atandroid.app.FragmentManagerImpl.removeFragment(FragmentManager.java:1167) 10-2721:19:52.99180278027DINJECT:atandroid.app.BackStackRecord.popFromBackStack(BackStackRecord.java:715) 10-2721:19:52.99180278027DINJECT:atandroid.app.FragmentManagerImpl.popBackStackState(FragmentManager.java:1544) 10-2721:19:52.99280278027DINJECT:atandroid.app.FragmentManagerImpl$3.run(FragmentManager.java:502) 10-2721:19:52.99280278027DINJECT:atandroid.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1449) 10-2721:19:52.99280278027DINJECT:atandroid.app.FragmentManagerImpl$1.run(FragmentManager.java:443) 10-2721:19:52.99280278027DINJECT:atandroid.os.Handler.handleCallback(Handler.java:733) 10-2721:19:52.99280278027DINJECT:atandroid.os.Handler.dispatchMessage(Handler.java:95) 10-2721:19:52.99280278027DINJECT:atandroid.os.Looper.loop(Looper.java:136) 10-2721:19:52.99380278027DINJECT:atandroid.app.ActivityThread.main(ActivityThread.java:5016) 10-2721:19:52.99380278027DINJECT:atjava.lang.reflect.Method.invokeNative(NativeMethod) 10-2721:19:52.99380278027DINJECT:atjava.lang.reflect.Method.invoke(Method.java:515) 10-2721:19:52.99380278027DINJECT:atcom.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:792) 10-2721:19:52.99380278027DINJECT:atcom.android.internal.os.ZygoteInit.main(ZygoteInit.java:608) 10-2721:19:52.99380278027DINJECT:atdalvik.system.NativeStart.main(NativeMethod) 10-2721:19:53.02080278027IOpenGLRenderer:functor=0x7a7b8530,vtbl=0x400fc1b8 从log中可以看到,确实是在distroy view的时候释放了Functor,而随后再Renderer中又使用了这个Functor。 打印崩溃时的java调用栈如下: 10-2721:19:53.27480278027Idalvikvm:"main"prio=5tid=1TIMED_WAIT10-2721:19:53.27980278027Idalvikvm:|group="main"sCount=0dsCount=0obj=0x41716ca8self=0x415344f8 10-2721:19:53.27980278027Idalvikvm:|sysTid=6895nice=-6sched=0/0cgrp=appshandle=1074409812 10-2721:19:53.28080278027Idalvikvm:|state=Rschedstat=(000)utm=184stm=61core=3 10-2721:19:53.28080278027Idalvikvm:atandroid.view.GLES20Canvas.nDrawDisplayList(NativeMethod) 10-2721:19:53.28180278027Idalvikvm:atandroid.view.GLES20Canvas.drawDisplayList(GLES20Canvas.java:420) 10-2721:19:53.28180278027Idalvikvm:atandroid.view.HardwareRenderer$GlRenderer.drawDisplayList(HardwareRenderer.java:1709) 10-2721:19:53.28180278027Idalvikvm:atandroid.view.HardwareRenderer$GlRenderer.draw(HardwareRenderer.java:1525) 10-2721:19:53.28280278027Idalvikvm:atandroid.view.ViewRootImpl.draw(ViewRootImpl.java:2475) 10-2721:19:53.28280278027Idalvikvm:atandroid.view.ViewRootImpl.performDraw(ViewRootImpl.java:2347) 10-2721:19:53.28380278027Idalvikvm:atandroid.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1977) 10-2721:19:53.28480278027Idalvikvm:atandroid.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1094) 10-2721:19:53.28580278027Idalvikvm:atandroid.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5703) 10-2721:19:53.28580278027Idalvikvm:atandroid.view.Choreographer$CallbackRecord.run(Choreographer.java:764) 10-2721:19:53.28680278027Idalvikvm:atandroid.view.Choreographer.doCallbacks(Choreographer.java:577) 10-2721:19:53.28780278027Idalvikvm:atandroid.view.Choreographer.doFrame(Choreographer.java:547) 10-2721:19:53.28880278027Idalvikvm:atandroid.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:750) 10-2721:19:53.28980278027Idalvikvm:atandroid.os.Handler.handleCallback(Handler.java:733) 10-2721:19:53.28980278027Idalvikvm:atandroid.os.Handler.dispatchMessage(Handler.java:95) 10-2721:19:53.29080278027Idalvikvm:atandroid.os.Looper.loop(Looper.java:136) 10-2721:19:53.29180278027Idalvikvm:atandroid.app.ActivityThread.main(ActivityThread.java:5016) 10-2721:19:53.29180278027Idalvikvm:atjava.lang.reflect.Method.invokeNative(NativeMethod) 10-2721:19:53.29280278027Idalvikvm:atjava.lang.reflect.Method.invoke(Method.java:515) 10-2721:19:53.29380278027Idalvikvm:atcom.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:792) 10-2721:19:53.29380278027Idalvikvm:atcom.android.internal.os.ZygoteInit.main(ZygoteInit.java:608) 10-2721:19:53.29380278027Idalvikvm:atdalvik.system.NativeStart.main(NativeMethod) 正常情况下,view在被destroy后不应该再被绘制,通过跟孙念沟通,得知这种情况可能是view在destroy前没有remove导致的。 分析代码: 上面delete时的调用栈中有特别的两行: 10-2721:19:52.99080278027DINJECT:atcom.xiaomi.music.hybrid.HybridFragment.destroyHybridView(HybridFragment.java:64) 10-2721:19:52.99080278027DINJECT:atcom.xiaomi.music.hybrid.HybridFragment.onDestroyView(HybridFragment.java:115) 这个是应用的代码,而这个问题只有在这个应用上出现过,所以很可能是应用的代码引起的, 所以查了下opengrok中的代码,发现有两处destroyHybridView()的实现: @v8-kk-pisces-alpha/packages/apps/MiuiMusic/common/music_sdk/hybrid/src/com/xiaomi/music/hybrid/HybridFragment.java privatevoiddestroyHybridView(){ for(HybridViewview:mHybridViews){ if(view!=null){ view.destroy(); } } mHybridViews.clear(); } @v8-kk-pisces-alpha/packages/apps/MiuiSdk/library/src/java/miui/hybrid/HybridFragment.java privatevoiddestroyHybridView(){ for(HybridViewview:mHybridViews){ if(view!=null){ =>if(view.getParent()!=null){ =>((ViewGroup)view.getParent()).removeView(view); =>} view.destroy(); } } mHybridViews.clear(); } 跟应用的同事沟通后得知,音乐应用是用上面的代码,也就是没有removeView的代码。 将上面代码中添加removeView的逻辑后不再复现问题。 虽然问题得到解决,但还不清楚为什么没有removeView会导致野指针。 为了找到根源仔细阅读了相关代码,发现代码中Render中有detachFunctor的代码: classGLES20CanvasextendsHardwareCanvas{ ... publicvoiddetachFunctor(intfunctor){ nDetachFunctor(mRenderer,functor); } 用studio在这个代码中设置断点,得到如下调用栈: java.lang.Thread.State:RUNNABLE atandroid.view.GLES20Canvas.detachFunctor(GLES20Canvas.java:321) atandroid.view.HardwareRenderer$GlRenderer.detachFunctor(HardwareRenderer.java:1791) atandroid.view.ViewRootImpl.detachFunctor(ViewRootImpl.java:744) atcom.android.webview.chromium.DrawGLFunctor$DestroyRunnable.detachNativeFunctor(DrawGLFunctor.java:97) atcom.android.webview.chromium.DrawGLFunctor.detach(DrawGLFunctor.java:53) atcom.android.webview.chromium.WebViewChromium.onDetachedFromWindow(WebViewChromium.java:1718) atandroid.webkit.WebView.onDetachedFromWindow(WebView.java:2108) atandroid.view.View.dispatchDetachedFromWindow(View.java:12631) atandroid.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2587) atandroid.view.ViewGroup.removeViewInternal(ViewGroup.java:3845) atandroid.view.ViewGroup.removeViewInternal(ViewGroup.java:3818) atandroid.view.ViewGroup.removeView(ViewGroup.java:3750) atcom.xiaomi.music.hybrid.HybridFragment.destroyHybridView(HybridFragment.java:66) atcom.xiaomi.music.hybrid.HybridFragment.onDestroyView(HybridFragment.java:119) atcom.miui.player.component.MusicBaseFragment.onDestroyView(MusicBaseFragment.java:216) atandroid.app.Fragment.performDestroyView(Fragment.java:1898) atandroid.app.FragmentManagerImpl.moveToState(FragmentManager.java:954) atandroid.app.FragmentManagerImpl.removeFragment(FragmentManager.java:1167) atandroid.app.BackStackRecord.popFromBackStack(BackStackRecord.java:715) atandroid.app.FragmentManagerImpl.popBackStackState(FragmentManager.java:1544) atandroid.app.FragmentManagerImpl$3.run(FragmentManager.java:502) atandroid.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1449) atandroid.app.FragmentManagerImpl$1.run(FragmentManager.java:443) atandroid.os.Handler.handleCallback(Handler.java:733) atandroid.os.Handler.dispatchMessage(Handler.java:95) atandroid.os.Looper.loop(Looper.java:136) atandroid.app.ActivityThread.main(ActivityThread.java:5016) atjava.lang.reflect.Method.invokeNative(Method.java:-1) atjava.lang.reflect.Method.invoke(Method.java:515) atcom.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:792) atcom.android.internal.os.ZygoteInit.main(ZygoteInit.java:608) atdalvik.system.NativeStart.main(NativeStart.java:-1) 加了removeView后,会从Render中删除Functor,这样Render在绘制时,不再调用这个Functor。 这个问题只会在KK上有,L以后对Render做的很大改动,即使不做removeView,也不会存在野指针问题。 作者:朴英敏 来源:51CTO

优秀的个人博客,低调大师

关于React Native 安卓首屏白屏优化

问题描述 在android中,当点击某个rn模块的入口按钮,弹出rn的activity到rn的页面展现出来的过程中,会有很明显的白屏现象,不同的机型不同(cpu好的白屏时间短),大概1s到2s的时间。 注意,只有在真机上才会有此现象,在模拟器上没有此现象完全是秒开。 优化分析 通过工具分析,问题主要在下面的代码上, ReactRootView mReactRootView = createRootView(); mReactRootView.startReactApplication(mReactInstanceManager, getMainComponentName(), getLaunchOptions()); ReactActivity的onCreate()的完整代码如下: protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getUseDeveloperSupport() && Build.VERSION.SDK_INT >= 23) { // Get permission to show redbox in dev builds. if (!Settings.canDrawOverlays(this)) { Intent serviceIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION); startActivity(serviceIntent); FLog.w(ReactConstants.TAG, REDBOX_PERMISSION_MESSAGE); Toast.makeText(this, REDBOX_PERMISSION_MESSAGE, Toast.LENGTH_LONG).show(); } } mReactInstanceManager = createReactInstanceManager(); ReactRootView mReactRootView = createRootView(); mReactRootView.startReactApplication(mReactInstanceManager, getMainComponentName(), getLaunchOptions()); setContentView(mReactRootView); } 知道了产生问题的原因,我们就知道怎么着手优化了。我们首先想到的:-内存换时间 步骤一: 缓存rootview管理器主要用于初始化和缓存rootview对象。 import android.app.Activity; import android.os.Bundle; import android.view.ViewParent; import com.facebook.react.LifecycleState; import com.facebook.react.ReactInstanceManager; import com.facebook.react.ReactPackage; import com.facebook.react.ReactRootView; import java.lang.reflect.Field; /** * 缓存view管理 */ public class RNCacheViewManager { private static ReactRootView mRootView = null; private static ReactInstanceManager mManager = null; private static AbsRnInfo mRnInfo = null; //初始化 public static void init(Activity act, AbsRnInfo rnInfo) { init(act, rnInfo, null); } public static void init(Activity act, AbsRnInfo rnInfo, Bundle launchOptions) { if (mManager == null) { updateCache(act, rnInfo, launchOptions); } } public static void updateCache(Activity act, AbsRnInfo rnInfo) { updateCache(act, rnInfo, null); } //更新cache,适合于版本升级时候更新cache public static void updateCache(Activity act, AbsRnInfo rnInfo, Bundle launchOptions) { mRnInfo = rnInfo; mManager = createReactInstanceManager(act); mRootView = new ReactRootView(act); mRootView.startReactApplication(mManager, rnInfo.getMainComponentName(), launchOptions); } //设置模块名称,因为是private,只能通过反射赋值 public static void setModuleName(String moduleName) { try { Field field = ReactRootView.class.getDeclaredField("mJSModuleName"); field.setAccessible(true); field.set(getReactRootView(), moduleName); } catch (Throwable e) { throw new RuntimeException(e); } } //设置启动参数,因为是private,只能通过反射赋值 public static void setLaunchOptions(Bundle launchOptions) { try { Field field = ReactRootView.class.getDeclaredField("mLaunchOptions"); field.setAccessible(true); field.set(getReactRootView(), launchOptions); } catch (Throwable e) { throw new RuntimeException(e); } } public static ReactRootView getReactRootView() { if(mRootView==null){ throw new RuntimeException("缓存view管理器尚未初始化!"); } return mRootView; } public static ReactInstanceManager getReactInstanceManager() { if(mManager==null){ throw new RuntimeException("缓存view管理器尚未初始化!"); } return mManager; } public static AbsRnInfo getRnInfo() { if(mRnInfo==null){ throw new RuntimeException("缓存view管理器尚未初始化!"); } return mRnInfo; } public static void onDestroy() { try { ViewParent parent = getReactRootView().getParent(); if (parent != null) ((android.view.ViewGroup) parent).removeView(getReactRootView()); } catch (Throwable e) { e.printStackTrace(); } } public static void clear() { try { if (mManager != null) { mManager.onDestroy(); mManager = null; } if (mRootView != null) { onDestroy(); mRootView = null; } mRnInfo = null; } catch (Throwable e) { e.printStackTrace(); } } private static ReactInstanceManager createReactInstanceManager(Activity act) { ReactInstanceManager.Builder builder = ReactInstanceManager.builder() .setApplication(act.getApplication()) .setJSMainModuleName(getRnInfo().getJSMainModuleName()) .setUseDeveloperSupport(getRnInfo().getUseDeveloperSupport()) .setInitialLifecycleState(LifecycleState.BEFORE_RESUME); for (ReactPackage reactPackage : getRnInfo().getPackages()) { builder.addPackage(reactPackage); } String jsBundleFile = getRnInfo().getJSBundleFile(); if (jsBundleFile != null) { builder.setJSBundleFile(jsBundleFile); } else { builder.setBundleAssetName(getRnInfo().getBundleAssetName()); } return builder.build(); } } 步骤二 重写ReactActivity,可以拷贝出来改,也可以继承写,主要是重写onCreate和onDestroy,其余代码不动。onCreate方法中使用缓存rootview管理器来获得rootview对象,而不是重新创建。 onCreate()代码 protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (RNCacheViewManager.getRnInfo().getUseDeveloperSupport() && Build.VERSION.SDK_INT >= 23) { // Get permission to show redbox in dev builds. if (!Settings.canDrawOverlays(this)) { Intent serviceIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION); startActivity(serviceIntent); FLog.w(ReactConstants.TAG, REDBOX_PERMISSION_MESSAGE); Toast.makeText(this, REDBOX_PERMISSION_MESSAGE, Toast.LENGTH_LONG).show(); } } mReactInstanceManager = RNCacheViewManager.getReactInstanceManager(); ReactRootView mReactRootView = RNCacheViewManager.getReactRootView(); setContentView(mReactRootView); }onDestroy方法中,不能再调用原有的mReactInstanceManager.destroy()方法了,否则rn初始化出来的对象会被销毁,下次就用不了了。同时,要卸载掉rootview的parent对象,否则下次再setContentView时候回报错。 protected void onDestroy() { RNCacheViewManager.onDestroy(); super.onDestroy(); } RNCacheViewManager的onDeatory代码 public static void onDestroy() { try { ViewParent parent = getReactRootView().getParent(); if (parent != null) ((android.view.ViewGroup) parent).removeView(getReactRootView()); } catch (Throwable e) { e.printStackTrace(); } } 步骤三 在app启动时候初始化缓存rootview管理器。 RNCacheViewManager.init((Activity) context, new RnInfo(moduleName, launchOptions));RnInfo实体类代码: public class RnInfo extends AbsRnInfo { private String mModuleName; private Bundle mLaunchOptions; public RnInfo(String moduleName) { this.mModuleName = moduleName; } public RnInfo(String moduleName, Bundle launchOptions) { this.mModuleName = moduleName; this.mLaunchOptions = launchOptions; } @Nullable @Override public Bundle getLaunchOptions() { return mLaunchOptions; } @Override public String getMainComponentName() { return mModuleName; } @Override public String getJSMainModuleName() { return RNKeys.Default.DEf_JS_MAIN_MODULE_NAME; } @Nullable @Override public String getJSBundleFile() { return RNManager.getJsBundlePath(); } @Override public boolean getUseDeveloperSupport() { return true; } @Override public List<ReactPackage> getPackages() { return Arrays.asList( new MainReactPackage(), new BBReactPackage() ); } }

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册