get方法獲取數(shù)據(jù),封裝存儲(chǔ)和移除方法用于操作數(shù)據(jù)緩存列表(需要優(yōu)化,僅參考)
成都創(chuàng)新互聯(lián)是一家成都網(wǎng)站建設(shè)、網(wǎng)站制作,提供網(wǎng)頁設(shè)計(jì),網(wǎng)站設(shè)計(jì),網(wǎng)站制作,建網(wǎng)站,按需設(shè)計(jì),網(wǎng)站開發(fā)公司,從2013年成立是互聯(lián)行業(yè)建設(shè)者,服務(wù)者。以提升客戶品牌價(jià)值為核心業(yè)務(wù),全程參與項(xiàng)目的網(wǎng)站策劃設(shè)計(jì)制作,前端開發(fā),后臺(tái)程序制作以及后期項(xiàng)目運(yùn)營(yíng)并提出專業(yè)建議和思路。
Flutter本地存儲(chǔ)可以用 shared_preferences ,其會(huì)根據(jù)不同操作系統(tǒng)進(jìn)行相對(duì)應(yīng)的存儲(chǔ)。
在pubspec.yaml添加
`shared_preferences: ^2.0.13`
```d
import 'package:shared_preferences/shared_preferences.dart';
class SpUtils {
SharedPreferences?prefs;
SpUtils._() {
init();
}
static SpUtils?_instance;
static preInit() {
_instance ??=SpUtils._();
}
static SpUtilsgetInstance() {
_instance ??=SpUtils._();
return _instance!;
}
void init()async {
prefs ??=await SharedPreferences.getInstance();
}
setString(String key, String value) {
prefs!.setString(key, value);
}
setDouble(String key, double value) {
prefs!.setDouble(key, value);
}
setInt(String key, int value) {
prefs!.setInt(key, value);
}
setBool(String key, bool value) {
prefs!.setBool(key, value);
}
setStringList(String key, List value) {
prefs!.setStringList(key, value);
}
clear(String key){
prefs!.remove(key);
}
clearAll(){
prefs!.clear();
}
Tget(String key) {
return prefs!.get(key)as T;
}
}
```
在項(xiàng)目初始頁調(diào)用
`SpUtils.preInit();`
存
`SpUtils.getInstance().setString('userId', '12345678');`
`SpUtils.getInstance().setDouble('price', 12.88);`
`SpUtils.getInstance().setInt('count', 200);`
`SpUtils.getInstance().setBool('flag', true);`
取
`SpUtils.getInstance().get('userId');`
刪
`SpUtils.getInstance().clearAll();`
`SpUtils.getInstance().clear('userId');`
Flutter的圖片緩存機(jī)制有問題(可能是我使用的版本1.12.13有問題)
網(wǎng)絡(luò)圖片會(huì)默認(rèn)緩存到本地,但是不管圖片是不是完整的或者損壞的,導(dǎo)致頁面在下次進(jìn)入的時(shí)候會(huì)優(yōu)先從緩存里讀取圖片。有些圖片是沒有加載完成的,或者損壞的,導(dǎo)致圖片無法顯示。UI效果就是顯示成白色的。
一種解決方式:加載前或者退出后清理圖片緩存
ImageCache??imageCache?=?PaintingBinding.instance.imageCache;?
imageCache.clear();
缺點(diǎn)就是每次圖片都想要從網(wǎng)絡(luò)上獲取,增加服務(wù)器負(fù)擔(dān)
在默認(rèn)情況下頁面切換走時(shí)會(huì)被銷毀,頁面切換回來時(shí)會(huì)被重新創(chuàng)建,如果頁面中有列表那么整個(gè)列表將會(huì)被重新創(chuàng)建,降低了用戶體驗(yàn),下面是解決這個(gè)問題的幾種處理方式
其中,參數(shù) image 類型為抽象類 ImageProvider ,定義了圖片數(shù)據(jù)獲取和加載的相關(guān)接口。
根據(jù)不同的數(shù)據(jù)來源,派生出不同的 ImageProvider :
抽象類 ImageProvider 提供了一個(gè)用于加載數(shù)據(jù)源的抽象方法 @protected ImageStreamCompleter load(T key, DecoderCallback decode); 接口,不同的數(shù)據(jù)源定義各自的實(shí)現(xiàn)。
子類 NetworkImage 實(shí)現(xiàn)如下:
load 方法返回類型為抽象類 ImageStreamCompleter ,其中定義了一些管理圖片加載過程的接口,比如 addListener 、 removeListener 、 addOnLastListenerRemovedCallback 等, MultiFrameImageStreamCompleter 為其子類。
MultiFrameImageStreamCompleter 第一個(gè)參數(shù) codec 類型為 Futureui.Codec ,用來對(duì)突破進(jìn)行解碼,當(dāng) codec 準(zhǔn)備好的時(shí)候,就會(huì)立即對(duì)圖片第一幀進(jìn)行解碼操作。
codec 為 _loadAsync 方法返回值,
_loadAsync 方法實(shí)現(xiàn):
decode 方法的類型:
其中解碼傳入的回調(diào)方法 image_provider.DecoderCallback decode ,
傳入 Uint8List ,返回 Futureui.Codec 。
而對(duì) decode 回調(diào)方法的具體定義,在 ImageProvider 的 resolveStreamForKey 方法中做了定義, resolveStreamForKey 方法在 ImageProvider 的 resolve 方法中有調(diào)用, resolve 方法則為 ImageProvider 類層級(jí)結(jié)構(gòu)的公共入口點(diǎn)。
resolveStreamForKey 和 resolve 實(shí)現(xiàn)如下:
decode 方法,即 PaintingBinding.instance!.instantiateImageCodec ,即為具體圖片解碼的方法實(shí)現(xiàn)。
ui.instantiateImageCodec 實(shí)現(xiàn):
descriptor.instantiateCodec 方法實(shí)現(xiàn):
_instantiateCodec 方法的實(shí)現(xiàn),最終到了 native 的實(shí)現(xiàn):
其中返回值類型 Codec 里定義了一些屬性:
obtainKey 方法:
ImageProvider 定義了一個(gè)抽象方法 FutureT obtainKey(ImageConfiguration configuration); ,供子類來實(shí)現(xiàn),其中 NetworkImage 的實(shí)現(xiàn)為:
obtainKey 作用:
配合實(shí)現(xiàn)圖片緩存, ImageProvider 從數(shù)據(jù)源加載完數(shù)據(jù)后,會(huì)在 ImageCache 中緩存圖片數(shù)據(jù),圖片數(shù)據(jù)緩存時(shí)一個(gè) Map ,其中 Map 中的 key 便是 obtainKey 。
resolve 作為 ImageProvider 提供給 Image 的主入口方法,參數(shù)為 ImageConfiguration ,
resolve 其中調(diào)用了 _createErrorHandlerAndKey 方法,設(shè)置了成功回調(diào)和失敗回調(diào):
其中 _createErrorHandlerAndKey 方法的實(shí)現(xiàn),便調(diào)用了 obtainKey 來設(shè)置 key 。
在成功回調(diào)里,調(diào)用了方法 resolveStreamForKey ,里面有具體的緩存實(shí)現(xiàn) PaintingBinding.instance!.imageCache!.putIfAbsent :
PaintingBinding.instance!.imageCache 是ImageCache的一個(gè)實(shí)例,是 PaintingBinding 的一個(gè)屬性,是一個(gè)單例,圖片緩存是全局的。
如上述判斷:
ImageCache 定義:
ImageCache 緩存池:
在 NetworkImage 中,對(duì) ImageProvider 的抽象方法 obtainKey 進(jìn)行了實(shí)現(xiàn),將自己創(chuàng)建了一個(gè)同步 Future 進(jìn)行返回:
同時(shí),自身又重寫了 ImageProvider 定義的 == 比較操作符,通過圖片 url 和圖片的縮放比例 scale 進(jìn)行比較:
通過ImageCache提供的方法來設(shè)置: