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
的简单方法。考虑编写本机模块。
所以我在 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
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
的简单方法。考虑编写本机模块。