iOS Android flutter 轻量级数据缓存对比

前言

各位同学大家好 有段时间没有给大家更新文章了, 具体多久我也记不清楚了哈 。 今天是大年初四 ,还在休假中。最近在学习iOS 开发 , 了解了iOS中的轻量级数据缓存的(之前做安卓和flutter 开发的 )所以今天趁着有时间就把IOS 端 Android端 flutter 跨端的轻量级数据缓存做一个对比分享给大家 那么废话不多说 我们正式开始

准备工作

  • iOS

安装xcode 这个大家可以自己去appstore 搜索下载安装即可

  • android

安卓这边需要安装AS(android studio)和jdk 然后配置环境变量即可

  • flutter

需要安装flutter的开发环境:大家可以去看看之前的教程:
1 win系统flutter开发环境安装教程: https://www.jianshu.com/p/152447bc8718
2 mac系统flutter开发环境安装教程:https://www.jianshu.com/p/bad2c35b41e3

具体实现:

  • iOS

在iOS 中我们存储轻量级数据的 例如登录的token还有 账号密码等等 轻量级数据的时候我们是用到了ios提供的 NSUserDefault来存储数据
NSUserDefault 的特点
提供了简单的key -value 存储

  • 单例,存取轻量级的数据
  • 一般用于用户偏好设置
  • 升级安装后还可以继续使用
  • 文件存储在/Library/Preferences 下
  • 支持基本数据类型
  • 保存 Interger Float Double Bool
  • 保存NSArray NSData NSString NSDictionary
  • 复杂Model 需要转化成NSData
    系统提供的方法
- (void)setObject:(nullable id)value forKey:(NSString *)defaultName;

- (void)removeObjectForKey:(NSString *)defaultName;


- (nullable NSString *)stringForKey:(NSString *)defaultName;


- (nullable NSArray *)arrayForKey:(NSString *)defaultName;

- (nullable NSDictionary<NSString *, id> *)dictionaryForKey:(NSString *)defaultName;

- (nullable NSData *)dataForKey:(NSString *)defaultName;

- (nullable NSArray<NSString *> *)stringArrayForKey:(NSString *)defaultName;

- (NSInteger)integerForKey:(NSString *)defaultName;

- (float)floatForKey:(NSString *)defaultName;

- (double)doubleForKey:(NSString *)defaultName;

- (BOOL)boolForKey:(NSString *)defaultName;

具体代码调用

  • 存数据
 NSString * str=@"abd";
    //存数据
[[NSUserDefaults  standardUserDefaults] setObject:str forKey:@"test"];
  • 取数据
NSString * test= [[NSUserDefaults standardUserDefaults]stringForKey:@"test"];
NSLog(@"test = %@", test);
  • 效果


    image.png

    其他类型数据大家可以参考api方法自己去多尝试

android

android 中我们主要是用 Sharedpreferences 来实现轻量级数据的存储
Sharedpreferences是Android平台上一个轻量级的存储类,用来保存应用程序的各种配置信息,其本质是一个以“键-值”对的方式保存数据的xml文件,其文件保存在/data/data//shared_prefs目录下。在全局变量上看,其优点是不会产生Application 、 静态变量的OOM(out of memory)和空指针问题,其缺点是效率没有上面的两种方法高。

具体使用

  • 1.获取SharedPreferences

要想使用 SharedPreferences 来存储数据,首先需要获取到 SharedPreferences 对象。Android中主要提供了三种方法用于得到 SharedPreferences 对象。
 1. Context 类中的 getSharedPreferences()方法:
 此方法接收两个参数,第一个参数用于指定 SharedPreferences 文件的名称,如果指定的文件不存在则会创建一个,第二个参数用于指定操作模式,主要有以下几种模式可以选择。MODE_PRIVATE 是默认的操作模式,和直接传入 0 效果是相同的。
 MODE_WORLD_READABLE 和 MODE_WORLD_WRITEABLE 这两种模式已在 Android 4.2 版本中被废弃。

Context.MODE_PRIVATE: 指定该SharedPreferences数据只能被本应用程序读、写;
Context.MODE_WORLD_READABLE:  指定该SharedPreferences数据能被其他应用程序读,但不能写;
Context.MODE_WORLD_WRITEABLE:  指定该SharedPreferences数据能被其他应用程序读;
Context.MODE_APPEND:该模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件;
  1. Activity 类中的 getPreferences()方法:
     这个方法和 Context 中的 getSharedPreferences()方法很相似,不过它只接收一个操作模式参数,因为使用这个方法时会自动将当前活动的类名作为 SharedPreferences 的文件名。
  2. PreferenceManager 类中的 getDefaultSharedPreferences()方法:
     这是一个静态方法,它接收一个 Context 参数,并自动使用当前应用程序的包名作为前缀来命名 SharedPreferences 文件。
  • SharedPreferences的使用

SharedPreferences对象本身只能获取数据而不支持存储和修改,存储修改是通过SharedPreferences.edit()获取的内部接口Editor对象实现。使用Preference来存取数据,用到了SharedPreferences接口和SharedPreferences的一个内部接口SharedPreferences.Editor,这两个接口在android.content包中;

SharedPreferences 存数据

  • 1调用 源码中 ContextWrapper中的 getSharedPreferences 方法给SharedPreferences 创建一个实例
  //步骤1:创建一个SharedPreferences对象
     SharedPreferences sharedPreferences= getSharedPreferences("data",Context.MODE_PRIVATE);
image.png
  • 2 实例化SharedPreferences.Editor对象并调用Editor 对象里面方法存数据
//步骤2: 实例化SharedPreferences.Editor对象
     SharedPreferences.Editor editor = sharedPreferences.edit();
     //步骤3:将获取过来的值放入文件
     editor.putString("name", “xuqing”);
     editor.putInt("age", 28);
     editor.putBoolean("marrid",false);
     //步骤4:提交               
     editor.commit();

SharedPreferences取数据

读取数据:
     SharedPreferences sharedPreferences= getSharedPreferences("data", Context .MODE_PRIVATE);
     String userId=sharedPreferences.getString("name","");

删除数据(删除指定数据)

删除指定数据
     editor.remove("name");
     editor.commit();

清空数据

清空数据
     editor.clear();
     editor.commit();

注意:如果在 Fragment 中使用SharedPreferences 时,需要放在onAttach(Activity activity)里面进行SharedPreferences的初始化,否则会报空指针 即 getActivity()会可能返回null !

editor提供的对外方法

 public interface Editor {

        Editor putString(String key, @Nullable String value);
        

        Editor putStringSet(String key, @Nullable Set<String> values);
        

        Editor putInt(String key, int value);
        
        Editor putLong(String key, long value);
        
        Editor putFloat(String key, float value);

        Editor putBoolean(String key, boolean value);

        Editor remove(String key);

        Editor clear();

        boolean commit();

   
        void apply();
    }

从源码里面 editor 提供的方法来看 我们的SharedPreferences 轻量级缓存 能够存储的数据只支持基本数据类型 (int long float Boolean ) 和string 引用类型 并不能存一个对象 bean这种复杂的数据类型 我们要对SharedPreferences 做些简单的封装就能满足我们的需求 不过我们始终要清楚 SharedPreferences 只适合轻量级数据 如果数据过多不建议使用这种方式
我们对 SharedPreferences 做一些简单封装来满足我们的各种需求

  • 存数据 取数据 删除数据的封装
    private static final String TAG = "SharedPreferencesUtils";
    /**
     * 保存在手机里面的文件名
     */
    private static final String FILE_NAME = "test";
    private static SharedPreferences sp;

    /**
     * 保存数据的方法,我们需要拿到保存数据的具体类型,然后根据类型调用不同的保存方法
     *
     * @param context
     * @param key
     * @param object
     * @param :SharedPreferencesUtils.setParam(this, "key", "value");
     *                                               key -- userid / accountId obj==
     */
    public static void setParam(Context context, String key, Object object) {
        String type = "String";
        if (object != null) {
            type = object.getClass().getSimpleName();
        }
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME, MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();

        if ("String".equals(type)) {
            editor.putString(key, (String) object);
        } else if ("Integer".equals(type) || "int".equals(type)) {
            editor.putInt(key, (Integer) object);
        } else if ("Boolean".equals(type) || "boolean".equals(type)) {
            editor.putBoolean(key, (Boolean) object);
        } else if ("Float".equals(type) || "float".equals(type)) {
            editor.putFloat(key, (Float) object);
        } else if ("Long".equals(type) || "long".equals(type)) {
            editor.putLong(key, (Long) object);
        }
        editor.commit();
    }

    /**
     * 得到保存数据的方法,我们根据默认值得到保存的数据的具体类型,然后调用相对于的方法获取值
     *
     * @param context
     * @param key                                             关键字
     * @param defaultObject                                   若取回空值则返回此默认值
     * @param :SharedPreferencesUtils.getParam(Activity.this, "key", "defaultValue");
     * @return
     */
    public static Object getParam(Context context, String key, Object defaultObject) {
        String type = "String";
        if (defaultObject != null) {
            type = defaultObject.getClass().getSimpleName();
        }
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME, MODE_PRIVATE);

        if ("String".equals(type)) {
            return sp.getString(key, (String) defaultObject);
        } else if ("Integer".equals(type) || "int".equals(type)) {
            return sp.getInt(key, (Integer) defaultObject);
        } else if ("Boolean".equals(type) || "boolean".equals(type)) {
            return sp.getBoolean(key, (Boolean) defaultObject);
        } else if ("Float".equals(type) || "float".equals(type)) {
            return sp.getFloat(key, (Float) defaultObject);
        } else if ("Long".equals(type) || "long".equals(type)) {
            return sp.getLong(key, (Long) defaultObject);
        }
        return null;
    }

    //删除指定的key
    public static void removeParam(Context context, String key, Object defaultObject) {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME, MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        editor.remove(key);
        editor.commit();

    }
  • 存list

  /**
     * 4.存储账本bookBean的list
     */
    public static void putSelectBean(Context context, List<SelectPhone> phoneList, String key) {
        if (sp == null) {
            sp = context.getSharedPreferences("config", MODE_PRIVATE);
        }
        SharedPreferences.Editor editor = sp.edit();
        Gson gson = new Gson();
        String json = gson.toJson(phoneList);
        editor.putString(key, json);
        editor.commit();
    }


    /**
     * 读取账本SelectPhone的list
     */
    public static List<SelectPhone> getSelectBean(Context context, String key) {
        if (sp == null) {
            sp = context.getSharedPreferences("config", MODE_PRIVATE);
        }
        Gson gson = new Gson();
        String json = sp.getString(key, null);

        Log.e(TAG, "getSelectBean: json   >>>   " + json);
        Type type = new TypeToken<List<SelectPhone>>() {
        }.getType();
        List<SelectPhone> arrayList = gson.fromJson(json, type);
        return arrayList;
    }
  • 缓存map集合

   //缓存map集合
    public static void putHashMapData(Context context, String key, Map<String, Object> datas) {
        JSONArray mJsonArray = new JSONArray();
        Iterator<Map.Entry<String, Object>> iterator = datas.entrySet().iterator();

        JSONObject object = new JSONObject();

        while (iterator.hasNext()) {
            Map.Entry<String, Object> entry = iterator.next();
            try {
                object.put(entry.getKey(), entry.getValue());
            } catch (JSONException e) {

            }
        }
        mJsonArray.put(object);

        SharedPreferences sp = context.getSharedPreferences("config",
                Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        editor.putString(key, mJsonArray.toString());
        editor.commit();
    }

    //获取map缓存数据
    public static Map<String, Object> getHashMapData(Context context, String key) {

        Map<String, Object> datas = new HashMap<>();
        SharedPreferences sp = context.getSharedPreferences("config",
                Context.MODE_PRIVATE);
        String result = sp.getString(key, "");
        try {
            JSONArray array = new JSONArray(result);
            for (int i = 0; i < array.length(); i++) {
                JSONObject itemObject = array.getJSONObject(i);
                JSONArray names = itemObject.names();
                if (names != null) {
                    for (int j = 0; j < names.length(); j++) {
                        String name = names.getString(j);
                        String value = itemObject.getString(name);
                        datas.put(name, value);
                    }
                }
            }
        } catch (JSONException e) {

        }

        return datas;
    }
  • 存储到SD卡(这里顺带讲一下 Android 里面 Android 6.0 以后要申请权限再操作SD 存储)

    //存数据到SD卡里面
    public static void storetosd(File file, List<SelectPhone> data) {

        try {
            Gson gson = new Gson();
            String json = gson.toJson(data);
            OutputStream os = new FileOutputStream(file);
            os.write(json.getBytes("utf-8"));
            os.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //读取SD卡里面的数据
    public static List<SelectPhone> readbysd(File file) {
        List<SelectPhone> arrayList = null;
        Gson gson = new Gson();
        try {
            InputStream is = new FileInputStream(file);
            byte[] data = new byte[is.available()];
            is.read(data);
            String content = new String(data, "utf-8");
            Type type = new TypeToken<List<SelectPhone>>() {
            }.getType();
            arrayList = gson.fromJson(content, type);
            is.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return arrayList;
    }

完整代码演示

package com.shiyue.game.utils;

import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.shiyue.game.bean.SelectPhone;
import com.shiyue.game.utils.log.LeLanLog;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import static android.content.Context.MODE_PRIVATE;

/**
 * SharedPreferences的一个工具类
 * 使用方法:
 * 调用setParam就能保存String, Integer, Boolean, Float, Long类型的参数
 * SharedPreferencesUtils.setParam(this, "String", "xiaanming");
 * SharedPreferencesUtils.setParam(this, "int", 10);
 * SharedPreferencesUtils.setParam(this, "boolean", true);
 * SharedPreferencesUtils.setParam(this, "long", 100L);
 * SharedPreferencesUtils.setParam(this, "float", 1.1f);
 * <p>
 * 同样调用getParam就能获取到保存在手机里面的数据
 * SharedPreferencesUtils.getParam(Activity.this, "String", "");
 * SharedPreferencesUtils.getParam(Activity.this, "int", 0);
 * SharedPreferencesUtils.getParam(Activity.this, "boolean", false);
 * SharedPreferencesUtils.getParam(Activity.this, "long", 0L);
 * SharedPreferencesUtils.getParam(Activity.this, "float", 0.0f);
 *
 * @author xuqing
 */
public class SharedPreferencesUtils {
    private static final String TAG = "SharedPreferencesUtils";
    /**
     * 保存在手机里面的文件名
     */
    private static final String FILE_NAME = "test";
    private static SharedPreferences sp;

    /**
     * 保存数据的方法,我们需要拿到保存数据的具体类型,然后根据类型调用不同的保存方法
     *
     * @param context
     * @param key
     * @param object
     * @param :SharedPreferencesUtils.setParam(this, "key", "value");
     *                                               key -- userid / accountId obj==
     */
    public static void setParam(Context context, String key, Object object) {
        String type = "String";
        if (object != null) {
            type = object.getClass().getSimpleName();
        }
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME, MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();

        if ("String".equals(type)) {
            editor.putString(key, (String) object);
        } else if ("Integer".equals(type) || "int".equals(type)) {
            editor.putInt(key, (Integer) object);
        } else if ("Boolean".equals(type) || "boolean".equals(type)) {
            editor.putBoolean(key, (Boolean) object);
        } else if ("Float".equals(type) || "float".equals(type)) {
            editor.putFloat(key, (Float) object);
        } else if ("Long".equals(type) || "long".equals(type)) {
            editor.putLong(key, (Long) object);
        }
        editor.commit();
    }

    /**
     * 得到保存数据的方法,我们根据默认值得到保存的数据的具体类型,然后调用相对于的方法获取值
     *
     * @param context
     * @param key                                             关键字
     * @param defaultObject                                   若取回空值则返回此默认值
     * @param :SharedPreferencesUtils.getParam(Activity.this, "key", "defaultValue");
     * @return
     */
    public static Object getParam(Context context, String key, Object defaultObject) {
        String type = "String";
        if (defaultObject != null) {
            type = defaultObject.getClass().getSimpleName();
        }
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME, MODE_PRIVATE);

        if ("String".equals(type)) {
            return sp.getString(key, (String) defaultObject);
        } else if ("Integer".equals(type) || "int".equals(type)) {
            return sp.getInt(key, (Integer) defaultObject);
        } else if ("Boolean".equals(type) || "boolean".equals(type)) {
            return sp.getBoolean(key, (Boolean) defaultObject);
        } else if ("Float".equals(type) || "float".equals(type)) {
            return sp.getFloat(key, (Float) defaultObject);
        } else if ("Long".equals(type) || "long".equals(type)) {
            return sp.getLong(key, (Long) defaultObject);
        }
        return null;
    }

    //删除指定的key
    public static void removeParam(Context context, String key, Object defaultObject) {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME, MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        editor.remove(key);
        editor.commit();


    }

    /**
     * 4.存储账本bookBean的list
     */
    public static void putSelectBean(Context context, List<SelectPhone> phoneList, String key) {
        if (sp == null) {
            sp = context.getSharedPreferences("config", MODE_PRIVATE);
        }
        SharedPreferences.Editor editor = sp.edit();
        Gson gson = new Gson();
        String json = gson.toJson(phoneList);
        editor.putString(key, json);
        editor.commit();
    }


    /**
     * 读取账本SelectPhone的list
     */
    public static List<SelectPhone> getSelectBean(Context context, String key) {
        if (sp == null) {
            sp = context.getSharedPreferences("config", MODE_PRIVATE);
        }
        Gson gson = new Gson();
        String json = sp.getString(key, null);

        Log.e(TAG, "getSelectBean: json   >>>   " + json);
        Type type = new TypeToken<List<SelectPhone>>() {
        }.getType();
        List<SelectPhone> arrayList = gson.fromJson(json, type);
        return arrayList;
    }

    //缓存map集合
    public static void putHashMapData(Context context, String key, Map<String, Object> datas) {
        JSONArray mJsonArray = new JSONArray();
        Iterator<Map.Entry<String, Object>> iterator = datas.entrySet().iterator();

        JSONObject object = new JSONObject();

        while (iterator.hasNext()) {
            Map.Entry<String, Object> entry = iterator.next();
            try {
                object.put(entry.getKey(), entry.getValue());
            } catch (JSONException e) {

            }
        }
        mJsonArray.put(object);

        SharedPreferences sp = context.getSharedPreferences("config",
                Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        editor.putString(key, mJsonArray.toString());
        editor.commit();
    }

    //获取map缓存数据
    public static Map<String, Object> getHashMapData(Context context, String key) {

        Map<String, Object> datas = new HashMap<>();
        SharedPreferences sp = context.getSharedPreferences("config",
                Context.MODE_PRIVATE);
        String result = sp.getString(key, "");
        try {
            JSONArray array = new JSONArray(result);
            for (int i = 0; i < array.length(); i++) {
                JSONObject itemObject = array.getJSONObject(i);
                JSONArray names = itemObject.names();
                if (names != null) {
                    for (int j = 0; j < names.length(); j++) {
                        String name = names.getString(j);
                        String value = itemObject.getString(name);
                        datas.put(name, value);
                    }
                }
            }
        } catch (JSONException e) {

        }

        return datas;
    }

    //存数据到SD卡里面
    public static void storetosd(File file, List<SelectPhone> data) {

        try {
            Gson gson = new Gson();
            String json = gson.toJson(data);
            OutputStream os = new FileOutputStream(file);
            os.write(json.getBytes("utf-8"));
            os.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //读取SD卡里面的数据
    public static List<SelectPhone> readbysd(File file) {
        List<SelectPhone> arrayList = null;
        Gson gson = new Gson();
        try {
            InputStream is = new FileInputStream(file);
            byte[] data = new byte[is.available()];
            is.read(data);
            String content = new String(data, "utf-8");
            Type type = new TypeToken<List<SelectPhone>>() {
            }.getType();
            arrayList = gson.fromJson(content, type);
            is.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return arrayList;
    }

    /**
     * 获得账号数组形式的列表(字符串转数组)
     * 通过参数确认是否需要翻转排序输出
     *
     * @param context
     * @param isReverse
     * @return
     */
    public static ArrayList getSYAccountList(Context context, boolean isReverse) {
        if (!getSYAccountArray(context).equals("")) {
            String temp = getSYAccountArray(context);
            LeLanLog.d("getSYAccountList 已缓存 账号列表 accountList=" + temp);
            String[] arrString = temp.split("#");
            ArrayList b = new ArrayList();
            for (int i = 0; i <= arrString.length - 1; i++) {
                b.add(arrString[i]);
            }
            if (isReverse) {
                ArrayList c = b;
                Collections.reverse(c);
                return c;
            } else {
                return b;
            }
        } else {
            return null;
        }
    }

    /**
     * 获取账号列表
     *
     * @param context
     * @return
     */
    public static String getSYAccountArray(Context context) {
        String temp = "";
        SharedPreferences data = context.getSharedPreferences("account_file_name", 0);
        temp = data.getString("array", "");
        LeLanLog.d("getSYAccountArray 从账号文件中读取账号数组 array=" + temp);
        String arraylist = BaseUtil.decode(temp);
        return arraylist;
    }

    /**
     * 通过账号列表获取到详细用户信息
     *
     * @param context
     * @param account
     * @return
     */
    public static HashMap getUserInfo(Context context, String account) {
        String key = BaseUtil.encode(account.getBytes());
        SharedPreferences userData = context.getSharedPreferences(key, 0);
        String muid = userData.getString("account", "");
        String mpwd = userData.getString("pwd", "");
        String mphoneNum = userData.getString("phoneNum", "");
        String mlonginTicket = userData.getString("longinToken", "");
        String muserName = userData.getString("userName", "");
        String mloginType = userData.getString("loginType", "");
        String mnickName = userData.getString("nickName", "");
        String mloginTimes = userData.getString("loginTimes", "");

        HashMap hs = new HashMap();
        hs.put("account", BaseUtil.decode(muid));
        hs.put("pwd", BaseUtil.decode(mpwd));
        hs.put("phoneNum", BaseUtil.decode(mphoneNum));
        hs.put("longinToken", BaseUtil.decode(mlonginTicket));
        hs.put("userName", BaseUtil.decode(muserName));
        hs.put("loginType", BaseUtil.decode(mloginType));
        hs.put("mnickName", BaseUtil.decode(mnickName));
        hs.put("loginTimes", BaseUtil.decode(mloginTimes));
        Log.d("loginTimes2=", BaseUtil.decode(mloginTimes));
        return hs;
    }
}

更多的android 里面SharedPreferences 用法 大家可以查阅官方API 这边就不再深入了

  • flutter

原生iOS 和原生android 里面的轻量级数据缓存我们都讲了 在原生的andriod 和iOS 里面都会有数据缓存的api Android 端用的是 Sharedpreferences 来实现对于轻量级数据的缓存 , IOS端 通常使用NSUserDefaults 来实现轻量级数据的缓存 但是在flutter 有基于Android iOS 做支持的三方插件库 shared_preferences ,其实shared_preferences 这个库本身底层是基于(android ) Sharedpreferences 和(ios)NSUserDefaults 封装的
我们普通开发者在上层调用API即可

shared_preferences 使用准备工作

shared_preferences: ^0.5.3+4 
image.png

在项目里面的pubspec.yaml 添加依赖 然后在项目根目录打开控制台输入 flutter pub get 命令回去下载相对应的依赖

shared_preferences基本用法

存储基本数据类型:
int 类型

  onPressed: ()async{
                SharedPreferences prefs = await SharedPreferences.getInstance();
                int counter =  1;
                await prefs.setInt('counter', counter);
              },

String类型

  onPressed: ()async{
                SharedPreferences prefs = await SharedPreferences.getInstance();
                String  counter =  "1";
                await prefs.setString('counter', counter);
              },

bool类型

  onPressed: ()async{
                SharedPreferences prefs = await SharedPreferences.getInstance();
                bool counter =false;
                await prefs.setBool('counter', counter);
              },

double类型

  onPressed: ()async{
                SharedPreferences prefs = await SharedPreferences.getInstance();
                double counter =0.01;
                await prefs.setDouble('counter', counter);
              },

list<String>data类型

   onPressed: ()async{
                SharedPreferences prefs = await SharedPreferences.getInstance();
                List<String>counter=["1","2"];
                await prefs.setStringList('counter', counter);
              },

取值基本用法

 onPressed: ()async{
                SharedPreferences prefs = await SharedPreferences.getInstance();
                 int  counterint =prefs.getInt("counter");
                 String  counter =prefs.getString("counter");
                 bool  counterbool =prefs.getBool("counter");
                double  counterdouble =prefs.getDouble("counter");
                List  counterlist =prefs.getStringList("counter");
              },

删除指定数据

其中key就是你存贮的名称,value就是你存储的值

 SharedPreferences prefs = await SharedPreferences.getInstance();
  prefs.remove(key); //删除指定键

清空整个缓存:

 SharedPreferences prefs = await SharedPreferences.getInstance();
 prefs.clear();//清空键值对

以上是Sharedpreferences 的基础用法 ,但是我们发现没有每次写一大推重复代码 这时候我们就对Sharedpreferences 进行简单封装是我们减少重复代码的编写

  /***
   *
   * 存数据
   */

  static Object savePreference(BuildContext context , String key , Object value) async {
   SharedPreferences prefs = await SharedPreferences.getInstance();
   if(value is  int ){
     await prefs.setInt(key, value);
     }else if(value is double){
     await prefs.setDouble(key, value);
     }else if(value is bool){
     await prefs.setBool(key, value);
     }else if(value is String){
     await prefs.setString(key, value);
     }else if(value is List){
     await prefs.setStringList(key, value);
   }  else {
     throw new Exception("不能得到这种类型");
   }
 }
  /***
   * 取数据
   *
   */
     static Future  getPreference( Object context , String key ,Object defaultValue) async{
   SharedPreferences prefs = await SharedPreferences.getInstance();
   if(defaultValue is  int) {
     return prefs.getInt(key);
      }
   else if(defaultValue is  double) {
     return prefs.getDouble(key);
      }
   else if(defaultValue is bool) {
     return prefs.getBool(key);
     }
   else if(defaultValue is String) {
     return prefs.getString(key);
   }
   else if(defaultValue is List) {
     return prefs.getStringList(key);
     }
   else {
     throw new Exception("不能得到这种类型");
   }
 }
  /***
   * 删除指定数据
   */
  static void    remove(String key)async{
     SharedPreferences prefs = await SharedPreferences.getInstance();
     prefs.remove(key); //删除指定键
   }
  /***
   * 清空整个缓存
   */
  static void    clear()async{
    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.clear(); ////清空缓存
  }

工具类具体调用 :

存储数据:
  onPressed: (){
                String counter  = "1";
                SharedPreferencesUtils.savePreference(context, "counter", counter);
              },
            ),
取值

直接调用并赋值给定义的变量

 onPressed: ()async{
      String  counter = await (SharedPreferencesUtils.getPreference(context, "counter", "1")) as String ;
                 print("counter  -- > "+counter);
     },

通过then方式调用

 onPressed: ()async{
                 SharedPreferencesUtils.getPreference(context, "counter", "1").then((value){
                   print("value   --->"  +value);
                 });
              },

删除指定key的缓存数据调用:

   SharedPreferencesUtils.remove("counter");

清空整个SharedPreferences缓存:

   SharedPreferencesUtils.clear();

基本数据类型的封装使用我们就说完了 大家发现没有有时候我们需要存一个model其实
SharedPreferences 本身是不支持我们要怎么做


image.png

image.png

如上图是我们需要把用户名和密码起来保存 我们用传统 SharedPreferences 来做肯定不OK 当然有同学肯定想到说用 sqlite 本地数据库来实现 ,sqlite 确实可以实现 但是本身代码就多不够灵活 而且我们这边存储的字段并不多 我们这边选择在 SharedPreferences 上面做稍微的改造就能实现上面的需求的

之前的实现方式 :
     onPressed: ()async{
                      User user=new User();
                      user.username=_username;
                      user.password=_password;
                      datalsit.add(user);
                       String jsonStringA = jsonEncode(datalsit);
                      print("jsonStringA   --------- >"+ jsonStringA);
                      SharedPreferences prefs = await SharedPreferences.getInstance();
                      prefs.setString("data",jsonStringA);
                    },

取值转换

    onPressed: ()async{
                      SharedPreferences prefs = await SharedPreferences.getInstance();
                      getdata = await prefs.getString("data");
                     List  list= json.decode(getdata);
                    },

获取到值以后我们要通过 json.decode 将那倒json字符串转成list然后再来取值,这是我们传统的做法 代码量其实很大 而且如果我们有很多类似的数据要存储肯定做法不够简洁 我们这里也对于之前实现方式简单的封装 代码如下


  /**
   * 存储  List<Object> phoneList
   *
   * List<Object> phoneList
   */
  static void setSelectBeanList(BuildContext context,List<Object> phoneList, String key) async{
    String jsonStringA = jsonEncode(phoneList);
    print("jsonStringA   --------- >"+ jsonStringA);
    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.setString(key,jsonStringA);
  }

  /**
   * 获取  List<Object> phoneList
   *
   * List<Object> phoneList
   */
   static Future   getSelectBean(BuildContext context, String key) async {
     SharedPreferences prefs = await SharedPreferences.getInstance();
     String  getdata = await prefs.getString("data");
      List  list= json.decode(getdata);
     return list;
  }

具体调用:

存储model:
   onPressed: ()async{
                      User user=new User();
                      user.username=_username;
                      user.password=_password;
                      _userlsit.add(user);
                       SharedPreferencesUtils.setSelectBeanList(context, _userlsit, "data");
                    },
取值:
onPressed: ()async{
     List datalist= await SharedPreferencesUtils.getSelectBean(context, "data");
    },

到此整个 SharedPreferences库 数据存储的基础用法和特别技巧我们就讲完了。

最后总结

无论是原生IOS 还是原生Android系统都提供了 轻量级缓存数据 api 方法 供我们开发者调用,无论是iOS的 NSUserDefaults 还是 Android 的Sharedpreferences 都定位住轻量级数据缓存 存储的数据类型也就是基本类型 复杂的类型我们也要通过转换才能存储和取值 还有就是 Sharedpreferences 和 NSUserDefaults 这两端的轻量级缓存 不卸载app 或者你主动掉调用方法删除 数据都可以保住 更新覆盖安装也能保住 所以是比较适合我们日常app 开发的一些轻量级数据存储 例如用户token 用户偏好 账号密码等等 , flutter 作为后起之秀的跨平台方案 我们使用了 shared_preferences 这个三方库 (和Android名字很像哈)就是底层使NSUserDefaults 和 Sharedpreferences 分别IOS 端和Android 端做了封装支持 所以我们上层开发者无需担心使用问题 写这期博客也是为了让那些非原生转flutter的同学对于 flutter里面数据存储对比原生有一个更加清楚认知。最后希望我的文章能帮助到各位解决问题 ,以后我还会贡献更多有用的代码分享给大家。各位同学如果觉得文章还不错 ,麻烦给关注和star,小弟在这里谢过啦

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容