Android ReactNative資料互動

weixin_34342992發表於2018-04-21

1.android跳轉介面,和React native初始化引數的傳遞

實現效果:點選按鈕,跳轉到載入 react native的activityA,讓A傳遞不同的值過去,讓RN.js顯示不同的介面。

1.androind載入reactnative有兩種方式,一種是繼承ReactAcitivity通過重寫getMainComponentName()指定reactnative入口檔案的方式載入。

public class ThreeActivity extends ReactActivity {
 
    @Override
    protected String getMainComponentName() {
        return "androidrn";//這是在package.json的檔案的name要相同
    }
    @Override
    protected ReactActivityDelegate createReactActivityDelegate() {
        return new MyreactDelegate(this, getMainComponentName());
    }
    class MyreactDelegate extends ReactActivityDelegate {

        public MyreactDelegate(Activity activity,    @Nullable String mainComponentName) {
            super(activity, mainComponentName);
        }
        @Nullable
        @Override
        protected Bundle getLaunchOptions() {
            Bundle bundle = new Bundle();
            bundle.putString("fromtag", "C");
            bundle.putString("data3", "android傳遞的初始化引數");
            return bundle;
        }
    }
}
4908477-9906e78534ba836f.png
image.png

這是一種方式傳遞。
2.第二種方式就是將reactnative作為view來使用,新增到佈局檔案。

public abstract class BaseReactActivity extends AppCompatActivity  implements DefaultHardwareBackBtnHandler {
    private ReactRootView mReactRootView;
    private ReactInstanceManager mReactInstanceManager;
    public static int OVERLAY_PERMISSION_REQ_CODE = 300;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (!Settings.canDrawOverlays(this)) {
                Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                        Uri.parse("package:" + getPackageName()));
                startActivityForResult(intent, OVERLAY_PERMISSION_REQ_CODE);
            }
        }
        initData();
        mReactRootView = new ReactRootView(this);
        mReactInstanceManager = ReactInstanceManager.builder()
                .setApplication(getApplication())
                .setBundleAssetName("index.android.bundle")
                .setJSMainModulePath("index.android")
                .addPackage(new MainReactPackage())
                .setUseDeveloperSupport(true)
                .setInitialLifecycleState(LifecycleState.RESUMED)
                .build();
        // “AppRegistry.registerComponent()”的第一個引數
        mReactRootView.startReactApplication(mReactInstanceManager, "dachuan",getBundle());
        setContentView(mReactRootView);


    }

    public abstract Bundle  getBundle() ;

    public abstract void initData();
    @Override
    public void invokeDefaultOnBackPressed() {
        ToastUtils.showShortToast("js預設返回結束呼叫執行Activity銷燬");
        super.onBackPressed();
    }
    @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);
        }
    }
    @Override
    public void onBackPressed() {

        if (mReactInstanceManager != null) {
            mReactInstanceManager.onBackPressed();
            ToastUtils.showShortToast("js返回");
        } else {
            super.onBackPressed();
            ToastUtils.showShortToast("走這裡");
        }

    }
    @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 onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == OVERLAY_PERMISSION_REQ_CODE) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if (!Settings.canDrawOverlays(this)) {
                    // SYSTEM_ALERT_WINDOW permission not granted...
                }
            }
        }
    }
}

這樣寫個抽象類把相同的操作封裝下。

public class NewsActivity extends BaseReactAcitvity {
   Bundle mBundle;
    @Override
    public Bundle getBundle() {
        mBundle=new Bundle();
        mBundle.putString("fromtag","B");
        mBundle.putString("data2","我是新聞介面");
        return mBundle;
    }
    @Override
    public void doLogicBeforeInitView() {

    }
}

繼承下,就能有值了。
3.接受資料並顯示。因為可能跳轉不同頁面,所以傳個fromtag區分下。
在index.android.js中接收

import React, { Component } from 'react';
import {Text, AppRegistry, Image, View,StyleSheet} from 'react-native';
export default class HelloWorldApp extends Component {
    render() {
      var data1=  this.props.data1;
      var data2=  this.props.data2;
      var data3=  this.props.data3;
      var tagfrom=this.props.fromtag;
      if (tagfrom=='A')
      {
          return (
              <Text>{data1}</Text>
          );
      }else if (tagfrom=='B'){
          return (
              <Text>{data2}</Text>
          );
      }
      else if (tagfrom=='C'){
                return (
                    <View>
                    <Text>{data3}</Text>
                    <Image style={styles.img} source={require('./imgs/myicon.jpg')} />
                    </View>
                );
            }
    }
}
var styles = StyleSheet.create({
    img:
        {
          width:300,
          height:300
        },
    container: {
        flex: 1,
        justifyContent: 'center',
    },
    hello: {
        fontSize: 20,
        textAlign: 'center',
        margin: 10,
    },
});
AppRegistry.registerComponent('androidrn', () => HelloWorldApp);

用this.props.data1接收。data1要對應喲

相關介面

跳轉的介面
4908477-3f8654293129fb3b.png
image.png

2.React Native 跳轉android原生介面,並傳值

大致的實現步驟如下:
1.RCTDeviceEventEmitter
優點:可任意時刻傳遞,Native主導控制。
2.Callback
優點:JS呼叫,Native返回。 缺點:CallBack為非同步操作,返回時機不確定
3.Promise
優點:JS呼叫,Native返回。 缺點:每次使用需要JS呼叫一次
(1)定義Module類,繼承ReactContextBaseJavaModule在Module類中,我們定義互動的方法,例如RN呼叫Native的方法,Native呼叫RN的方法等。
(2)定義Package類,繼承ReactPackage實現Package的createNativeModules方法,將Module例項新增到集合。
(3)定義Application,繼承ReactApplication實現getPackages方法,將Package例項新增到getPackages下的集合。
該文沒有描述這3種方式
a.在android中定義MyMapIntentModule ,@ReactMethod建立跳轉方法,並傳值

public class MyMapIntentModule extends ReactContextBaseJavaModule  {
    public static final String REACTCLASSNAME = "MyMapIntentModule";
    private Context mContext;
    public MyMapIntentModule(ReactApplicationContext reactContext) {
        super(reactContext);
        mContext=reactContext;
    }
    @Override
    public String getName() {
        return REACTCLASSNAME;
    }
    @ReactMethod
    public  void startAcByClassName(String name, String  bundle)
    {
        try {
       Activity currentActivity =getCurrentActivity();
       if (null!=currentActivity)
       {
           Class toActivity=Class.forName(name);
           Intent intent=new Intent(currentActivity,toActivity);
           intent.putExtra("nativedata",bundle);
           currentActivity.startActivity(intent);
       }

        }catch (Exception e)
        {
            throw new JSApplicationIllegalArgumentException(
                    "無法開啟activity頁面: "+e.getMessage());
        }
    }
}

b.定義MyreactPackage ,新增到列表中。

public class MyreactPackage implements ReactPackage {
    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        List<NativeModule> modules=new ArrayList<>();
        modules.add(new MyMapIntentModule(reactContext));
        return modules;
    }

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
}

c.在baseapplication中註冊,僅僅在這裡註冊是會報錯的。


4908477-9e5ed9be55a83f95.png
image.png

報錯如下:


4908477-6bf8013a8686bf4a.png
image.png

需要怎麼做呢?
4908477-d8bdb61fcf866274.png
image.png

這樣就可以了。

d .index.android.js中怎麼寫的呢?

1)匯入NativeModules

import {Text, AppRegistry, Image, View,StyleSheet,Button,NativeModules} from 'react-native';
<Button style={styles.container} title="點選跳轉" onPress={() => this.onClick()}></Button>
 onClick() {
        NativeModules.MyMapIntentModule.startAcByClassName("ph.com.test.AndroidNativeActivity","我是index,android.js中的資訊")
    }

4908477-9219e5340c96793e.png
image.png

對應
4908477-4264dc6c2a405e66.png
image.png

到此就完成跳轉傳值了。
感謝文章的作者:連結

相關文章