|
| 1 | +--- |
| 2 | +title: Brownfield integration |
| 3 | +--- |
| 4 | + |
| 5 | +### Supported platforms: |
| 6 | + |
| 7 | +- **iOS** |
| 8 | +- **macOS** |
| 9 | +- **Android** |
| 10 | + |
| 11 | +--- |
| 12 | + |
| 13 | +# iOS |
| 14 | + |
| 15 | +If you're embedding React Native into native application, you can also integrate |
| 16 | +Async Storage module, so that both worlds will use one storage solution. |
| 17 | + |
| 18 | +AsyncStorage can be controlled by the hosting app via the delegate on |
| 19 | +`RNCAsyncStorage`: |
| 20 | + |
| 21 | +```objc |
| 22 | +RNCAsyncStorage *asyncStorage = [bridge moduleForClass:[RNCAsyncStorage class]]; |
| 23 | +asyncStorage.delegate = self; |
| 24 | +``` |
| 25 | +
|
| 26 | +## The protocol |
| 27 | +
|
| 28 | +The delegate must conform to the `RNCAsyncStorageDelegate` protocol: |
| 29 | +
|
| 30 | +### allKeys |
| 31 | +
|
| 32 | +```objc |
| 33 | +- (void)allKeys:(RNCAsyncStorageResultCallback)block; |
| 34 | +``` |
| 35 | + |
| 36 | +Returns all keys currently stored. If none, an empty array is returned. |
| 37 | +Called by `getAllKeys` in JS. |
| 38 | + |
| 39 | +### mergeValues |
| 40 | + |
| 41 | +```objc |
| 42 | +- (void)mergeValues:(NSArray<NSString *> *)values |
| 43 | + forKeys:(NSArray<NSString *> *)keys |
| 44 | + completion:(RNCAsyncStorageResultCallback)block; |
| 45 | +``` |
| 46 | + |
| 47 | +Merges values with the corresponding values stored at specified keys. |
| 48 | +Called by `mergeItem` and `multiMerge` in JS. |
| 49 | + |
| 50 | +### removeAllValues |
| 51 | + |
| 52 | +```objc |
| 53 | +- (void)removeAllValues:(RNCAsyncStorageCompletion)block; |
| 54 | +``` |
| 55 | + |
| 56 | +Removes all values from the store. Called by `clear` in JS. |
| 57 | + |
| 58 | +### removeValuesForKeys |
| 59 | + |
| 60 | +```objc |
| 61 | +- (void)removeValuesForKeys:(NSArray<NSString *> *)keys |
| 62 | + completion:(RNCAsyncStorageResultCallback)block; |
| 63 | +``` |
| 64 | + |
| 65 | +Removes all values associated with specified keys. |
| 66 | +Called by `removeItem` and `multiRemove` in JS. |
| 67 | + |
| 68 | +### setValues |
| 69 | + |
| 70 | +```objc |
| 71 | +- (void)setValues:(NSArray<NSString *> *)values |
| 72 | + forKeys:(NSArray<NSString *> *)keys |
| 73 | + completion:(RNCAsyncStorageResultCallback)block; |
| 74 | +``` |
| 75 | + |
| 76 | +Sets specified key-value pairs. Called by `setItem` and `multiSet` in JS. |
| 77 | + |
| 78 | +### valuesForKeys |
| 79 | + |
| 80 | +```objc |
| 81 | +- (void)valuesForKeys:(NSArray<NSString *> *)keys |
| 82 | + completion:(RNCAsyncStorageResultCallback)block; |
| 83 | +``` |
| 84 | + |
| 85 | +Returns values associated with specified keys. |
| 86 | +Called by `getItem` and `multiGet` in JS. |
| 87 | + |
| 88 | +### passthrough |
| 89 | + |
| 90 | +```objc |
| 91 | +@optional |
| 92 | +@property (nonatomic, readonly, getter=isPassthrough) BOOL passthrough; |
| 93 | +``` |
| 94 | + |
| 95 | +**Optional:** Returns whether the delegate should be treated as a passthrough. |
| 96 | +This is useful for monitoring storage usage among other things. Returns `NO` by |
| 97 | +default. |
| 98 | + |
| 99 | +--- |
| 100 | + |
| 101 | +# Android |
| 102 | + |
| 103 | +The recommended approach here is to use Kotlin language to leverage coroutines when accessing the storage. |
| 104 | +Java is also supported (through Kotlin interop), but the approach is more cumbersome. |
| 105 | + |
| 106 | +## Prerequisites |
| 107 | + |
| 108 | +1. [Next storage feature](Next.md) enabled. |
| 109 | +2. Add dependency on `coroutines-android` in your app's `build.gradle` |
| 110 | + |
| 111 | +```diff |
| 112 | + |
| 113 | +dependencies { |
| 114 | + // other dependencies |
| 115 | + |
| 116 | + |
| 117 | + // will work with coroutines 1.3.0 and up |
| 118 | ++ implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9" |
| 119 | + |
| 120 | +} |
| 121 | +``` |
| 122 | + |
| 123 | +3. Your library of choice for parsing JSON storage values (since there are strings only) |
| 124 | + |
| 125 | +## Access storage |
| 126 | + |
| 127 | +### Kotlin (recommended) |
| 128 | + |
| 129 | +We use Coroutines to handle asynchronous code. Each method on storage is `suspend` method, so you need to |
| 130 | +call it from within a coroutine. |
| 131 | + |
| 132 | +#### Reading value |
| 133 | + |
| 134 | +```kotlin |
| 135 | +suspend fun readValue(ctx: Context, keys: List<String>) { |
| 136 | + // get instance of the Storage by providing context object |
| 137 | + val asyncStorage = StorageModule.getStorageInstance(ctx) |
| 138 | + |
| 139 | + val entries: List<Entry> = asyncStorage.getValues(keys) |
| 140 | + doSomethingWithValues(entries) |
| 141 | +} |
| 142 | +``` |
| 143 | + |
| 144 | +#### Saving value |
| 145 | + |
| 146 | +```kotlin |
| 147 | +suspend fun saveValue(ctx: Context) { |
| 148 | + val asyncStorage = StorageModule.getStorageInstance(ctx) |
| 149 | + |
| 150 | + val entries = listOf( |
| 151 | + Entry("myKey", "myValue") |
| 152 | + ) |
| 153 | + asyncStorage.setValues(entries) |
| 154 | +} |
| 155 | +``` |
| 156 | + |
| 157 | +### Java |
| 158 | + |
| 159 | +You can access AsyncStorage form Java, but you're still required to add Kotlin dependencies. |
| 160 | +There's no one way of accessing the data and there's more than one way to parse it. |
| 161 | + |
| 162 | +#### Reading from storage |
| 163 | + |
| 164 | +```java |
| 165 | +void readStorageValue(Context ctx, String key) { |
| 166 | + AsyncStorageAccess asyncStorage = StorageModule.getStorageInstance(ctx); |
| 167 | + |
| 168 | + BuildersKt.launch(GlobalScope.INSTANCE, |
| 169 | + Dispatchers.getIO(), |
| 170 | + CoroutineStart.DEFAULT, |
| 171 | + (scope, continuation) -> { |
| 172 | + List<String> keys = new ArrayList<>(); |
| 173 | + keys.add(key); |
| 174 | + |
| 175 | + Continuation<? super List<? extends Entry>> cont = new Continuation() { |
| 176 | + @NotNull |
| 177 | + @Override |
| 178 | + public CoroutineContext getContext() { |
| 179 | + return scope.getCoroutineContext(); |
| 180 | + } |
| 181 | + |
| 182 | + @Override |
| 183 | + public void resumeWith(@NotNull Object o) { |
| 184 | + List<Entry> entries = (List<Entry>) o; |
| 185 | + doSomethingWithEntries(entries); |
| 186 | + } |
| 187 | + }; |
| 188 | + |
| 189 | + asyncStorage.getValues(keys, cont); |
| 190 | + return Unit.INSTANCE; |
| 191 | + }); |
| 192 | + |
| 193 | +} |
| 194 | +``` |
| 195 | + |
| 196 | +#### Saving to storage |
| 197 | + |
| 198 | +```java |
| 199 | +void saveStorageValue(Context ctx, String key, String value) { |
| 200 | + AsyncStorageAccess asyncStorage = StorageModule.getStorageInstance(ctx); |
| 201 | + |
| 202 | + BuildersKt.launch(GlobalScope.INSTANCE, |
| 203 | + Dispatchers.getIO(), |
| 204 | + CoroutineStart.DEFAULT, |
| 205 | + (scope, continuation) -> { |
| 206 | + Continuation cont = new Continuation() { |
| 207 | + @NotNull |
| 208 | + @Override |
| 209 | + public CoroutineContext getContext() { |
| 210 | + return scope.getCoroutineContext(); |
| 211 | + } |
| 212 | + |
| 213 | + @Override |
| 214 | + public void resumeWith(@NotNull Object o) {} |
| 215 | + }; |
| 216 | + |
| 217 | + List<Entry> entries = new ArrayList<>(); |
| 218 | + Entry entry = new Entry(key, value); |
| 219 | + entries.add(entry); |
| 220 | + asyncStorage.setValues(entries, cont); |
| 221 | + return Unit.INSTANCE; |
| 222 | + }); |
| 223 | +} |
| 224 | +``` |
0 commit comments