React Native:用java编写AsyncStorage

时间:2015-11-28 07:01:40

标签: java storage react-native

所以我在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沟通吗?

2 个答案:

答案 0 :(得分:4)

经过一番战斗我终于找到了解决方案。我在源代码中读到它并没有使用AsyncStorage AsyncStorage实际上可能位于不同的位置(SQLite或其他东西),具体取决于手机。复制这种逻辑会很脏。

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

该模块向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);

  }

答案 1 :(得分:1)

如果您不想编写本机模块,可以在 # -*- coding: utf-8 -*- """ Created on Mon Nov 27 17:11:21 2017 @author: ZED """ from __future__ import print_function print(__doc__) # Authors: Yann N. Dauphin, Vlad Niculae, Gabriel Synnaeve # License: BSD import numpy as np import matplotlib.pyplot as plt from scipy.ndimage import convolve from keras.models import Sequential from keras.layers.core import Dense,Activation from keras.wrappers.scikit_learn import KerasClassifier from keras.utils import np_utils from sklearn import datasets, metrics from sklearn.model_selection import train_test_split from sklearn.neural_network import BernoulliRBM from sklearn.pipeline import Pipeline #%% # Setting up def nudge_dataset(X, Y): """ This produces a dataset 5 times bigger than the original one, by moving the 8x8 images in X around by 1px to left, right, down, up """ direction_vectors = [ [[0, 1, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [1, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 1], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 1, 0]]] shift = lambda x, w: convolve(x.reshape((8, 8)), mode='constant', weights=w).ravel() X = np.concatenate([X] + [np.apply_along_axis(shift, 1, X, vector) for vector in direction_vectors]) Y = np.concatenate([Y for _ in range(5)], axis=0) return X, Y # Load Data digits = datasets.load_digits() X = np.asarray(digits.data, 'float32') X, Y = nudge_dataset(X, digits.target) X = (X - np.min(X, 0)) / (np.max(X, 0) + 0.0001) # 0-1 scaling X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2, random_state=0) #%% def create_model(): model = Sequential() model.add(Dense(100, input_dim=64)) model.add(Activation('tanh')) """ #other layer model.add(Dense(500)) model.add(Activation('tanh')) """ model.add(Dense(10)) model.add(Activation('softmax')) # Compile model model.compile(loss = 'binary_crossentropy', optimizer = 'adadelta', metrics=['accuracy']) return model rbm = BernoulliRBM(random_state=0, verbose=True) #This is the model you want. it is in sklearn format clf = KerasClassifier(build_fn=create_model, verbose=0) classifier = Pipeline(steps=[('rbm', rbm), ('VNN', clf)]) #%% # Training # Hyper-parameters. These were set by cross-validation, # using a GridSearchCV. Here we are not performing cross-validation to # save time. rbm.learning_rate = 0.06 rbm.n_iter = 20 # More components tend to give better prediction performance, but larger # fitting time rbm.n_components = 64 #adapt targets to hot matrix yTrain = np_utils.to_categorical(Y_train, 10) # Training RBM-Logistic Pipeline classifier.fit(X_train, yTrain) #%% # Evaluation print() print("NN using RBM features:\n%s\n" % ( metrics.classification_report( Y_test, classifier.predict(X_test)))) #%% # Plotting plt.figure(figsize=(4.2, 4)) for i, comp in enumerate(rbm.components_): plt.subplot(10, 10, i + 1) plt.imshow(comp.reshape((8, 8)), cmap=plt.cm.gray_r, interpolation='nearest') plt.xticks(()) plt.yticks(()) plt.suptitle('64 components extracted by RBM', fontsize=16) plt.subplots_adjust(0.08, 0.02, 0.92, 0.85, 0.08, 0.23) plt.show()

中执行此操作

在MainActivity类中声明一个全局变量(不要忘记导入MainActivity.java):

com.facebook.react.modules.storage.ReactDatabaseSupplier

private ReactDatabaseSupplier mReactDatabaseSupplier; 方法内部初始化全局变量:

onCreate

声明一个私有方法来保存mReactDatabaseSupplier = ReactDatabaseSupplier.getInstance(getApplicationContext());

中的键/值对
AsyncStorage

然后你可以像这样保存键/值对(例如在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); } } } 内):

onCreate

}

这是一种在React Native应用程序的@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mReactDatabaseSupplier = ReactDatabaseSupplier.getInstance(getApplicationContext()); saveKeyValuePair("myAsyncStorageKey", "myValueInAsyncStorageKey"); 中保存的简单方法。考虑编写本机模块。