如何在片段内部开始react ?

View view = inflater.inflate(mReactRootView. , container, false);

推荐答案

经过多次try 和错误,我终于弄明白了这一点.我在网上看到过这个问题,我认为这是发布答案的最佳地点.以下是如何使用最新版本的React( compose 本文时为0.29):

我们要做的第一件事是创建一个抽象的ReactFragment类,我们将在整个应用程序中使用它:

public abstract class ReactFragment extends Fragment {
    private ReactRootView mReactRootView;
    private ReactInstanceManager mReactInstanceManager;

    // This method returns the name of our top-level component to show
    public abstract String getMainComponentName();

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        mReactRootView = new ReactRootView(context);
        mReactInstanceManager =
                ((MyApplication) getActivity().getApplication())
                        .getReactNativeHost()
                        .getReactInstanceManager();

    }

    @Override
    public ReactRootView onCreateView(LayoutInflater inflater, ViewGroup group, Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        return mReactRootView;
    }


    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        mReactRootView.startReactApplication(
                mReactInstanceManager,
                getMainComponentName(),
                null
        );
    }
}

我们现在可以创建呈现React本机组件的片段,例如:

public class HelloFragment extends ReactFragment {
    @Override
    public String getMainComponentName() { 
        return "hellocomponent"; // name of our React Native component we've registered 
    }
}

不过,还需要做更多的工作.为了让React Native生命周期正常工作,我们的父Activity需要将一些东西传递给ReactInstanceManager.以下是我的结局:

public class FragmentActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler {
    /*
    * Get the ReactInstanceManager, AKA the bridge between JS and Android
    * We use a singleton here so we can reuse the instance throughout our app
    * instead of constantly re-instantiating and re-downloading the bundle
    */
    private ReactInstanceManager mReactInstanceManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fragment);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });

        /**
         * Get the reference to the ReactInstanceManager
         */
         mReactInstanceManager =
             ((MyApplication) getApplication()).getReactNativeHost().getReactInstanceManager();


        /*
        * We can instantiate a fragment to show for Activity programmatically,
        * or using the layout XML files.
        * This doesn't necessarily have to be a ReactFragment, any Fragment type will do.
        */

        Fragment viewFragment = new HelloFragment();
        getFragmentManager().beginTransaction().add(R.id.container, viewFragment).commit();
    }

    @Override
    public void invokeDefaultOnBackPressed() {
        super.onBackPressed();
    }

    /*
     * Any activity that uses the ReactFragment or ReactActivty
     * Needs to call onHostPause() on the ReactInstanceManager
     */
    @Override
    protected void onPause() {
        super.onPause();

        if (mReactInstanceManager != null) {
            mReactInstanceManager.onHostPause();
        }
    }

    /*
     * Same as onPause - need to call onHostResume
     * on our ReactInstanceManager
     */
    @Override
    protected void onResume() {
        super.onResume();

        if (mReactInstanceManager != null) {
            mReactInstanceManager.onHostResume(this, this);
        }
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) {
            mReactInstanceManager.showDevOptionsDialog();
            return true;
        } 
        return super.onKeyUp(keyCode, event);
    }
}

最后,你会注意到代码中对(MyApplication)的引用;这是一个包含ReactInstanceManager的全局Application对象,也就是Android和React Native之间的桥梁.这是React原生项目在内部使用的模式,所以我只是复制了它.以下是它的实现方式:

public class MyApplication extends Application implements ReactApplication {
    private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
        @Override
        public boolean getUseDeveloperSupport() {
            return true;
        }

        @Override
        public List<ReactPackage> getPackages() {
            return Arrays.<ReactPackage>asList(
                    new MainReactPackage()
            );
        }
    };

    @Override
    public ReactNativeHost getReactNativeHost() {
        return mReactNativeHost;
    }
}

最棘手的一点是找出片段和活动之间的生命周期;ReactRootView需要引用活动上下文才能实例化,因此确保getActivity()不为null非常重要.此外,在父活动中注册onHostPause()onHostResume()起初并不直观,但最终证明,一旦ReactNativeInstanceManager被抽象为一个全局变量,而不是保留在活动或片段中,就更简单了.

希望这能帮助其他人!

React-native相关问答推荐

条件呈现Else语句不会将样式应用于我的组件

react native调用fetch后如何使用Async Storage在本地保存数据?

使用react native 杀死应用程序后蓝牙仍处于活动状态

新的 react-native ios 应用程序没有构建?

在react-native 模块库中找不到 ios 框架头文件

警告:API 'variant.getMergeAssets()' 已过时 / Android Studio 3.3

React Native 用于低互联网带宽的小型 apk APP应用

React Native 中如何使用 Flex 居中组件?

submit提交后如何让 React Native TextInput 保持焦点?

React Native - 如何判断 UI/元素?

React-Native Android - 找不到 com.android.tools:common

React Native Remote Debugger 在 Chrome 中显示缓存的包

React native Redux - 对象不是构造函数(判断'new ctor(props context)')

Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.

查找文本输入框和按钮字段的资源名称以响应本机 android 应用程序

无法在react-native元素中扩展 Zip

Android Log

Gradlew bundleRelease 不会在 react-native 中生成发布 apk

React Navigation 切换背景 colored颜色 和样式 StackNavigator

在 react-native 中使用捏拉zoom 的可滚动图像