AndroidオリジナルプロジェクトFragmentにReact Nativeを統合

5492 ワード

AndroidオリジナルプロジェクトFragmentにReact Nativeを統合
AndroidにReactNativeを統合する方法は諸説ありますが、いろいろ試しても実現できるので、迷っています.最後に私は自分の好きな方法を整理しました.アプリケーションでReactApplicationを実装し、getReactNativeHostメソッドを書き換えて、アプリケーションでインスタンス化されたReactNativeHostを返します.ReactNativeHostにはロードパッケージ、開発構成があります.この方式は単一の入口、すなわちindexが1つしかないのに適している.android.bundleは存在します.
以下は私の好きな方法です.
 
Fragmentベースクラス
public abstract class ReactFragment extends Fragment {

    private ReactRootView mReactRootView;
    private ReactInstanceManager mReactInstanceManager;
    private Bundle mBundle;

    // 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);
    }

    public void setmReactInstanceManager(ReactInstanceManager mReactInstanceManager, Bundle bundle) {
        this.mReactInstanceManager = mReactInstanceManager;
        mBundle = bundle;
    }

    @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(),
                mBundle
        );
    }
}
 

FragmentでReactFragmentを継承
 
 
public class ReactUseInFragment extends ReactFragment{

    @Nullable
    @Override
    public String getMainComponentName() {
        //index.js        
        return "MyReactNativeApp";
    }
}

 
Activityで
Activityは、D e f a ultHardwareBackBtnHandlerを実装する必要があります.そうしないと、ジェスチャーやボタンに問題が発生します.
 
public class ReactUseInFragmentTwoActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler {

    private ReactInstanceManager mReactInstanceManager;
    private ReactRootView mReactRootView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_react_use_in_fragment_two);

        mReactInstanceManager = ReactInstanceManager.builder()
                .setApplication(this.getApplication())
                .setBundleAssetName("index.android.bundle")
                .setJSMainModulePath("index")
                .addPackage(new MainReactPackage())
                .setUseDeveloperSupport(BuildConfig.DEBUG)
                .setInitialLifecycleState(LifecycleState.RESUMED)
                .build();

        ReactUseInFragmentTwo fragment = new ReactUseInFragmentTwo();

        fragment.setmReactInstanceManager(mReactInstanceManager, null);

        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.add(R.id.fl_react, fragment).show(fragment);
        fragmentTransaction.commit();
    }

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

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

    @Override
    public void onPause() {
        super.onPause();

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

    @Override
    public void onResume() {
        super.onResume();

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

    @Override
    public void onBackPressed() {
        if (mReactInstanceManager != null) {
            mReactInstanceManager.onBackPressed();
        } else {
            super.onBackPressed();
        }
    }
 

まとめ
こんな簡単な方法で、頭が痛くて、ReactActivityの中のソースコードも頭が痛いです.
mReactInstanceManager = ReactInstanceManager.builder()
                    .setApplication(this.getApplication())
                    .setBundleAssetName("index.android.bundle")
                    .setJSMainModulePath("index")
                    .addPackage(new MainReactPackage())
                    .setUseDeveloperSupport(BuildConfig.DEBUG)
                    .setInitialLifecycleState(LifecycleState.RESUMED)
                    .build();


mReactInstanceManager = new ReactNativeHost(getActivity().getApplication()) {

    @Override
    public boolean getUseDeveloperSupport() {
        return BuildConfig.DEBUG;
    }

    @Override
    protected List getPackages() {
        return Arrays.asList(
                new MainReactPackage()
        );
    }

    @Override
    protected String getJSMainModuleName() {
        return "index";
    }

    @Nullable
    @Override
    protected String getBundleAssetName() {
        return "index.android.bundle";
    }
}.getReactInstanceManager();

この2つの書き方は似ていますが、mReactInstanceManagerは同じです.