React Native:用 java 写入 AsyncStorage

React Native: write in AsyncStorage with java

所以我在 java 端有这个来自 Intent 的文本,我想将其保存到 AsyncStorage 以便能够通过 React 访问它之后。

我有机会实现这个目标吗?

我有:

package com.myapp;

import android.app.Activity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.content.Intent;


import com.facebook.react.LifecycleState;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactRootView;
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.soloader.SoLoader;

public class MainActivity extends Activity implements DefaultHardwareBackBtnHandler {

    private ReactInstanceManager mReactInstanceManager;
    private ReactRootView mReactRootView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mReactRootView = new ReactRootView(this);

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

        mReactRootView.startReactApplication(mReactInstanceManager, "BrowseItLater", null);

        setContentView(mReactRootView);

        // This code is from http://developer.android.com/training/sharing/receive.html
        Intent intent = getIntent();
        String action = intent.getAction();
        String type = intent.getType();
        if (Intent.ACTION_SEND.equals(action) && type != null) {
            handleSendText(intent);
        }        
    }

    void handleSendText(Intent intent) {
        String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
        if (sharedText != null) {
            // How can I handle this ????
        }
    }
// ...
}

或者有什么其他的办法让MainActivity.java和JS通信?

经过一番折腾我终于找到了解决办法。它不使用 AsyncStorage 正如我在源代码中读到的那样 AsyncStorage 实际上可能位于不同的位置(SQLite 或其他),具体取决于 phone。重复这个逻辑会很脏。

相反,我创建了一个类似 the doc suggests 的模块,并将 inputText 作为参数传递给 MainActivity.java 中的 .addPackage(new EphemeralStoragePackage(inputText)) 调用。

该模块向 JS 世界公开了一个方法 readOnceAsync,我稍后可以调用它:

NativeModules.EphemeralStorage.readOnceAsync((text :string) => {
  if (text.length) {
    this._addValue(text); // this method is in charge of storing in AsyncStorage
  }
})

详情如下:

// android/app/src/main/java/com/appname/modules/ephemeralstorage/EphemeralStorageModule.java

package com.browseitlater.modules.ephemeralstorage;

import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Callback;

import java.util.Map;

public class EphemeralStorageModule extends ReactContextBaseJavaModule {
  private String inputText;

  public EphemeralStorageModule(ReactApplicationContext reactContext, String _inputText) {
    super(reactContext);
    this.inputText = _inputText;
  }

  @Override
  public String getName() {
    return "EphemeralStorage";
  }

  public String getInputText() {
    return inputText;
  }

  @ReactMethod
  public void readOnceAsync(Callback successCallback) {
    successCallback.invoke(getInputText());
    this.inputText = null;
  }

}

// android/app/src/main/java/com/appname/modules/ephemeralstorage/EphemeralStoragePackage.java
package com.browseitlater.modules.ephemeralstorage;

import android.app.Activity;

import java.util.*;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;


public class EphemeralStoragePackage implements ReactPackage {
  private String inputText;

  public EphemeralStoragePackage(String _inputText) {
    super();
    this.inputText = _inputText;
  }

  @Override
  public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
    List<NativeModule> modules = new ArrayList<>();
    modules.add(new EphemeralStorageModule(reactContext, getInputText()));
    return modules;
  }

  @Override
  public List<Class<? extends JavaScriptModule>> createJSModules() {
    return Collections.emptyList();
  }

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

  public String getInputText() {
    return inputText;
  }

}

最后在 MainActivity.java 中,我的 onCreate 方法如下所示:

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mReactRootView = new ReactRootView(this);

    Intent intent = getIntent();
    String action = intent.getAction();
    String type = intent.getType();
    String inputText = intent.getStringExtra(Intent.EXTRA_TEXT);

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

    mReactRootView.startReactApplication(mReactInstanceManager, "BrowseItLater", null);

    setContentView(mReactRootView);

  }

如果不想写原生模块,可以在MainActivity.java

在MainActivity中声明一个全局变量class(别忘了导入com.facebook.react.modules.storage.ReactDatabaseSupplier):

private ReactDatabaseSupplier mReactDatabaseSupplier;

里面onCreate方法初始化全局变量:

mReactDatabaseSupplier = ReactDatabaseSupplier.getInstance(getApplicationContext());

声明一个私有方法以在 AsyncStorage

中保存 key/value 对
private void saveKeyValuePair(String key, String value) {
    String sql = "INSERT OR REPLACE INTO catalystLocalStorage VALUES (?, ?);";
    SQLiteStatement statement = mReactDatabaseSupplier.get().compileStatement(sql);
    try {
        mReactDatabaseSupplier.get().beginTransaction();
        statement.clearBindings();
        statement.bindString(1, key);
        statement.bindString(2, value);
        statement.execute();
        mReactDatabaseSupplier.get().setTransactionSuccessful();
    } catch (Exception e) {
        Log.w("YOUR_TAG", e.getMessage(), e);
    } finally {
        try {
            mReactDatabaseSupplier.get().endTransaction();
        } catch (Exception e) {
            Log.w("YOUR_TAG", e.getMessage(), e);
        }
    }
}

然后你可以像这样保存 key/value 对(例如 onCreate 内):

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mReactDatabaseSupplier = ReactDatabaseSupplier.getInstance(getApplicationContext());
    saveKeyValuePair("myAsyncStorageKey", "myValueInAsyncStorageKey");

}

这是一种保存 React Native 应用程序 AsyncStorage 的简单方法。考虑编写本机模块。