代码之家  ›  专栏  ›  技术社区  ›  laptou

React Native应用程序内部的Vulkan SurfaceView使所有内容均为空白

  •  0
  • laptou  · 技术社区  · 4 年前

    我正在创建一个React原生Android应用程序,我想嵌入一个使用Vulkan呈现的控件。我通过创建 SurfaceView 调用 VkSurfaceView 并使用JNI调用在Rust中实现Vulkan代码。

    我打开了显示所有视图边界的调试设置,这样可以清楚地看到视图仍然存在。

    以下是简单Android布局(无React Native)中的Vulkan控件(目前仅呈现三角形):

    enter image description here

    这是我没有Vulkan控件的React原生布局(方形代表我试图放置Vulkan控件的位置):

    enter image description here

    但当我放置Vulkan控件时,其他所有内容都会变暗,即使布局检查器和调试覆盖显示其他视图仍然存在:

    enter image description here

    为什么会发生这种情况?如上所示,Vulkan控件在纯Android布局中工作,因此我认为它一定以某种方式与React Native进行了不利的交互。然而,我发现了这样的例子 this this 能够使用 表面视图 / TextureView / VideoView 在React Native中,不会导致问题。

    编辑: 即使我注释掉了 VkSurfaceView ,黑屏问题仍然存在(但三角形显然消失了),所以我不认为这是因为我的Vulkan代码存在问题。

    编辑2: 如果我从 纹理视图 而不是 表面视图 .但为什么?我怀疑这与所解释的差异有关 here ,但我仍然不明白为什么视图是否使用OpenGL合成很重要。

    这是我的代码:

    反应本机 index.js :

    import React from 'react';
    import {
      AppRegistry,
      StyleSheet,
      Text,
      View
    } from 'react-native';
    import VkSurfaceView from './surface-view';
    
    const HelloWorld = () => {
      return (
        <View style={[styles.container, {
          // Try setting `flexDirection` to `"row"`.
          flexDirection: "column"
        }]}>
          <Text style={styles.hello}>Hello, World</Text>
          <View style={{ width: 100, height: 100, alignSelf: 'center', backgroundColor: 'pink' }}>
            <VkSurfaceView style={{ width: 100, height: 100 }}/>
          </View>
        </View>
      );
    };
    var styles = StyleSheet.create({
      container: {
        flex: 1,
        justifyContent: 'center',
        backgroundColor: '#ffffff'
      },
      hello: {
        fontSize: 20,
        textAlign: 'center',
        margin: 10,
        color: 'green'
      }
    });
    
    AppRegistry.registerComponent(
      'MyReactNativeApp',
      () => HelloWorld
    );
    

    反应本机 surface-view.js :

    import { requireNativeComponent } from 'react-native';
    
    module.exports = requireNativeComponent('SPVkSurfaceView');
    

    JAVA SurfaceReactPackage.java :

    public class SurfaceReactPackage implements ReactPackage {
        @NonNull
        @Override
        public List<NativeModule> createNativeModules(@NonNull ReactApplicationContext reactContext) {
            return Collections.emptyList();
        }
    
        @NonNull
        @Override
        public List<ViewManager> createViewManagers(
                @NonNull ReactApplicationContext reactContext) {
            return Collections.singletonList(
                    new ReactSurfaceManager(reactContext)
            );
        }
    }
    

    JAVA ReactSurfaceManager.java :

    public class ReactSurfaceManager extends SimpleViewManager<VkSurfaceView> {
        public static final String REACT_CLASS = "SPVkSurfaceView";
        ReactApplicationContext mCallerContext;
    
        public ReactSurfaceManager(ReactApplicationContext reactContext) {
            mCallerContext = reactContext;
        }
    
        @NonNull
        @Override
        public VkSurfaceView createViewInstance(ThemedReactContext context) {
            return new VkSurfaceView(context);
        }
    
        @Override
        public String getName() {
            return REACT_CLASS;
        }
    }
    

    JAVA MainActivity.java

    public class MainActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler {
        private ReactRootView mReactRootView;
        private ReactInstanceManager mReactInstanceManager;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            // initialize native code library before using VkSurfaceView
            MyNativeLibary.init();
    
            // initialize React Native
            mReactRootView = new ReactRootView(this);
            List<ReactPackage> packages = new PackageList(getApplication()).getPackages();
            packages.add(new SurfaceReactPackage());
    
            mReactInstanceManager = ReactInstanceManager.builder()
                    .setApplication(getApplication())
                    .setCurrentActivity(this)
                    .setBundleAssetName("index.android.bundle")
                    .setJSMainModulePath("index")
                    .addPackages(packages)
                    .setUseDeveloperSupport(BuildConfig.DEBUG)
                    .setInitialLifecycleState(LifecycleState.RESUMED)
                    .build();
            // The string here (e.g. "MyReactNativeApp") has to match
            // the string in AppRegistry.registerComponent() in index.js
            mReactRootView.startReactApplication(mReactInstanceManager, "MyReactNativeApp", null);
    
            setContentView(mReactRootView);
        }
    
        @Override
        protected void onPause() {
            super.onPause();
    
            if (mReactInstanceManager != null) {
                mReactInstanceManager.onHostPause(this);
            }
        }
    
        @Override
        protected void onResume() {
            super.onResume();
    
            if (mReactInstanceManager != null) {
                mReactInstanceManager.onHostResume(this, this);
            }
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
    
            if (mReactInstanceManager != null) {
                mReactInstanceManager.onHostDestroy(this);
            }
            if (mReactRootView != null) {
                mReactRootView.unmountReactApplication();
            }
        }
    
        @Override
        public void invokeDefaultOnBackPressed() {
            this.onBackPressed();
        }
    
        @Override
        public void onBackPressed() {
            if (mReactInstanceManager != null) {
                mReactInstanceManager.onBackPressed();
            } else {
                super.onBackPressed();
            }
        }
    }
    
    0 回复  |  直到 4 年前
        1
  •  0
  •   laptou    4 年前

    一种解决方案是使用 TextureView 而不是 SurfaceView 但是,这似乎效果不太好,因为每隔几秒钟我就会遇到与帧缓冲相关的超时问题。我最终使用的解决方案是 表面视图 a的内部 FrameLayout