react-native-fast-app 詳解與使用之(一) AsyncStorage

react-native-fast-app 是一款爲React Native App快速開發提供基礎服務的純JS庫(支持 IOS & Android),特別是在從0到1的項目搭建初期,至少可以爲開發者減少30%的工作量。

react-native-fast-app 主要做了這些工作:
1. 對AsyncStorage進行封裝,開發者只需幾行代碼即可實現一個持久化數據管理器。
2. 對fetch進行封裝,使得開發者只需關注當前App的前後臺交互邏輯和協議,定義好參數設置及解析邏輯即可。
3. 重新封裝了RN的View、Text、Image、FlatList 使用得這些控件在適當的時候支持事件或支持icon與文本,能有效減少佈局中的嵌套邏輯。
4. 可通過配置,當前庫重定義的組件支持[尺寸屬性] 按設定的參考屏幕尺寸進行等比縮放,去適配在不同屏幕分辨下的樣式。

可能有人覺得,RN的AsyncStorage本身就很簡單,自己封裝也就幾十行代碼的工作量,爲什麼還要使用第三方庫?

一千個人心中,有一千個哈姆雷特,也許我的封裝思路能給你帶來不一樣的啓發也未可知呢?

數據存儲(AsyncStorage)

RN平臺提供的AsyncStorage有一些基礎方法:setItem,getItem,removeItem,getAllKeys,這些是promise模式的並且AsyncStorage只支持對純字符串的存取,因此我們不便於直接在代碼中去直接調用這些方法,我們得對AsyncStorage做一次封裝,怎樣封裝能使我們更方便快捷的訪問本地存取呢?

我們來看下通過 react-native-fast-app 庫的RFStorage,我們可以怎樣訪問AsyncStorage:

1、核心代碼實現
import { RFStorage } from 'react-native-fast-app';

let RNStorage = { // 自定義對象
    hasLogin: undefined,
    customerId: undefined,
    userInfo: undefined
};
RFStorage.initStorage(RNStorage, () => { // 初始化自定義數據管理器
    RNStorage.customerId = '123456';
    RNStorage.hasLogin = true;
    RNStorage.userInfo = {name: 'zhangsan', age: 30};
    console.log(JSON.stringify(RNStorage)) // 打印數據管理器的內容
})

執行完上面的代碼後我們看看控制檯輸出:
console.png

再通過Root Explorer 查看一下當前App的data/data/{package}/database 下數據表的內容:
root_explorer.png

**😲什麼?**上面的代碼中並沒有做任何數據庫的存儲操作啊,爲什麼賦值給RNStorage的數據卻被存到了本地數據庫中呢?我們先看上面的代碼中做了什麼:

  1. 定義了一個自定義對象RNStorage
  2. 將自定義對象傳給RFStorage.initStorage 進行初始化
  3. 在初始化完成後對RNStorage的屬性進行了賦值
  4. 打印RNStorage的內容

由此可見,數據的存儲操作必定是上面的第2、3步引起的。我們進入RFStorage的源碼看看,裏面做了什麼:

  • 初始化核心代碼 1
Object.keys(targetObj).map(key => {
    const keyStr = newKey(Tag, key);
    Object.defineProperty(targetObj, key, {
        get: () => {
            return this[keyStr]
        },
        set: (value) => {
            try {
                this[keyStr] = value;
                const valueStr = (typeof value === 'object') ? JSON.stringify(value) : String(value);
                keyValuesPairs.push([keyStr, valueStr])
            } catch (exception) {
                console.log(exception && exception.message);
            }
        },
    })
});
setInterval(() => {
    if (!isEmpty(keyValuesPairs)) {
        let saveDataArray = [...keyValuesPairs];
        keyValuesPairs = []; //清空原鍵值對數組
        AsyncStorage.multiSet(saveDataArray, () => {
            dataChangedCallback && dataChangedCallback(saveDataArray)
        });
    }
}, 2500)
  • 初始化核心代碼 2
const Keys = Object.keys(storageObj);
const StorageKeys = Keys.map(key => newKey(Tag, key));
// 初始化時,將AsyncStorage中的數據一次性讀取到內存中
AsyncStorage.multiGet(StorageKeys).then(keyValuePairs => {
    keyValuePairs.map(([keyStr, value]) => {
        let [, key] = keyStr.split(splitTag);
        if (persistTag !== key && !isEmpty(value)) {
            storageObj[key] = convertData(value)
        }
    });
    setTimeout(() => initializedCallback(), 100)
}).catch(error => {
    console.log(error)
})

哦,原來 RFStorage 通過getter、setter生成器,將用戶自定義的 RNStorage 的各屬與 AsyncStorage 的數據表各字段的值進行了關聯形成了一個綁定關係,在當用戶對 RNStorage 的各屬性進行賦值、取值操作的時候,實際上會觸發getter、setter生成器,相應的會對 AsyncStorage 中的數據表進行讀寫操作。

效率與性能的平衡

  • <讀> 在初始化RFStorage的時候就將AsyncStorage中的所有字段一次性讀取到 RNStorage 對象中,以後續讀取屬性時,並不需要經過AsyncStorage,而是直接返回 RNStorage的屬性。
  • <寫> 在開發者修改RFStorage的屬性值時,會先將目標數據賦值給RFStorage的屬性,然後再異步通過AsyncStorage將目標數據寫入到數據庫中(考慮到數據寫入的效率與性能問題,目前的處理方式爲:每次數值的變更都會記錄下來,定時程序每隔2.5秒進行一次數據批量寫入操作),但這個絲毫不會影響App對數據的操作,因爲RNStorage中的數據是實時且同步的。

至此就完全清楚了,是不是很簡單?開發者通過 react-native-fast-app 只需定義一個全局可導出的 RNStorage對象(命名隨意,並定義好App所需的各屬性字段),然後在App啓動的時候通過RFStorage初始化一次RNStorage即可,以後直接訪問RNStorage中的屬性值就行了(所有對RNStorage屬性的修改都會被自動同步到AsyncStorage中),完全是一勞永逸啊。。。

想進一步瞭解,請移步至 npm 或github查看 react-native-fast-app,有源碼及使用示例,待大家一探究竟,歡迎朋友們 Star!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章