天天看點

android 使用SharedPreferences儲存對象

今天,簡單講講Android如何使用SharedPreferences儲存對象。

記得之前寫過一遍部落格關于android如何使用SharedPreferences儲存List<String>類型的連結清單,但是最近需要做一個需求,儲存一個對象或者是List<Object>,那麼應該怎麼辦呢?在網上查找了資料,最終是解決了問題。這裡記錄一下。

一.使用Gosn将對象轉成String後存入SharedPreferences

下面是我封裝改賬本(Book)的Bean:

package beans;

/**
 * Created by Chase on 2017/5/3.
 */

public class BookBean {
    public String bookName;
    public int bookBgSrc;

    public BookBean(){

    }


    public BookBean(String bookName,int bookBgSrc){
        this.bookName = bookName;
        this.bookBgSrc =bookBgSrc;
    }

    public String getBookName(){
        return bookName;
    }

    public int getBookBgSrc(){
        return bookBgSrc;
    }

    public void setBookBgSrc(int bookBgSrc) {
        this.bookBgSrc = bookBgSrc;
    }

    public void setBookName(String bookName) {
        this.bookName = bookName;
    }
}
           

下面編寫兩個方法用來存儲和讀取這個Bean:

public class SpUtils {
    private static SharedPreferences sp;
   /**
     * 4.存儲賬本bookBean的list
     */
    public static void putBookBean(Context ctx, List<BookBean> bookList) {
        if (sp == null) {
            sp = ctx.getSharedPreferences("config", MODE_PRIVATE);
        }
        SharedPreferences.Editor editor = sp.edit();
        Gson gson = new Gson();
        String json = gson.toJson(bookList);
        editor.putString(ConstantValue.BOOK_BEAN, json);
        editor.commit();
    }
   }
           
/**
     * 讀取賬本bookBean的list
     */
    public static List<BookBean> getBookBean(Context ctx) {
        if (sp == null) {
            sp = ctx.getSharedPreferences("config", MODE_PRIVATE);
        }
        Gson gson = new Gson();
        String json = sp.getString(ConstantValue.BOOK_BEAN, null);
        Type type = new TypeToken<List<BookBean>>() {
        }.getType();
        List<BookBean> arrayList = gson.fromJson(json, type);
        return arrayList;
    }
           

這個需要導入Gosn jar包,并且實體類需要滿足gosn對于實體類的要求,具體的大家可以查找資料。

二.使用Base64将對象編碼成String後存入SharedPreferences

由于二進制資料經過編碼後可以用SharedPreferences以字元串的形式存儲,是以儲存對象也成為了可能,但是這個類必須是可序列化即implements Serializable(實際上Serializable接口是個空接口,隻是為了标記該對象是被序列化的),然後可以通過ObjectOutputStream儲存再轉為二進制存儲。

1、儲存序列化的對象

/**
     * @param user
     */
    public static void saveUser(Context context, String preferenceName,String key,User user) throws Exception {
        if(user instanceof Serializable) {
            SharedPreferences sharedPreferences = context.getSharedPreferences(preferenceName, context.MODE_PRIVATE);
            SharedPreferences.Editor editor = sharedPreferences.edit();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            try {
                ObjectOutputStream oos = new ObjectOutputStream(baos);
                oos.writeObject(user);//把對象寫到流裡
                String temp = new String(Base64.encode(baos.toByteArray(), Base64.DEFAULT));
                editor.putString(key, temp);
                editor.commit();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }else {
            throw new Exception("User must implements Serializable");
        }
    }
           
android 使用SharedPreferences儲存對象

2、讀取序列化的對象

public static User getUser(Context context, String preferenceName,String key) {
        SharedPreferences sharedPreferences=context.getSharedPreferences(preferenceName,context.MODE_PRIVATE);
        String temp = sharedPreferences.getString(key, "");
        ByteArrayInputStream bais =  new ByteArrayInputStream(Base64.decode(temp.getBytes(), Base64.DEFAULT));
        User user = null;
        try {
            ObjectInputStream ois = new ObjectInputStream(bais);
            user = (User) ois.readObject();
        } catch (IOException e) {
        }catch(ClassNotFoundException e1) {

        }
        return user;
    }
           

當然Sharedpreferences也是可以存儲各種集合類的比如說List,都可以通過轉為ObjectOutputStream輸出流進而編碼存儲:

public static String listToString(List<?> list)throws IOException {
        // 執行個體化一個ByteArrayOutputStream對象,用來裝載壓縮後的位元組檔案。
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        // 然後将得到的字元資料裝載到ObjectOutputStream
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(
                byteArrayOutputStream);
        // writeObject 方法負責寫入特定類的對象的狀态,以便相應的 readObject 方法可以還原它
        objectOutputStream.writeObject(list);
        // 最後,用Base64.encode将位元組檔案轉換成Base64編碼儲存在String中
        String listString = new String(Base64.encode(
                byteArrayOutputStream.toByteArray(), Base64.DEFAULT));
        // 關閉objectOutputStream
        objectOutputStream.close();
        return listString;
    }

    @SuppressWarnings("unchecked")
    public static List<?> StringToList(String listString) throws StreamCorruptedException, IOException,
            ClassNotFoundException {
        byte[] mobileBytes = Base64.decode(listString.getBytes(),
                Base64.DEFAULT);
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(
                mobileBytes);
        ObjectInputStream objectInputStream = new ObjectInputStream(
                byteArrayInputStream);
        List<?> WeatherList = (List<?>) objectInputStream
                .readObject();
        objectInputStream.close();
        return WeatherList;
    }
           

這個我自己測試過,是可以正常使用的,不過實體類需要實作Serializable接口,而且效率可能比較低,這個大家可以去網上查找資料。

三、關于Base64

public static void main(String[] args) {  
        BASE64Encoder encoder = new BASE64Encoder();  
        String s = "Man";  
        String encoded = encoder.encode(s.getBytes());  
        System.out.println("ecoded Man " + encoded);  
        s = "Mo";  
        String encoded = encoder.encode(s.getBytes());  
        System.out.println("ecoded Mo" + encoded);
        s = "c";  
        String encoded = encoder.encode(s.getBytes());  
        System.out.println("ecoded c" + encoded);

    } 
           

Base64是一種基于64個可列印字元來表示二進制資料的表示方法。由于2的6次方等于64,是以每6個比特為一個單元,對應某個可列印字元。三個位元組有24個比特,對應于4個Base64單元,即3個位元組可表示4個可列印字元。它可用來作為電子郵件的傳輸編碼。在Base64中的可列印字元包括字母A-Z、a-z、0-9,這樣共有62個字元,此外兩個可列印符号在不同的系統中而不同。Base64是一種可逆的編碼方式。最常見的表現就是在于可以用Base64對圖檔編碼變成流,反過來也可以把流轉為圖檔,Base64常用于在通常處理文本資料的場合,表示、傳輸、存儲一些二進制資料。包括MIME的email、在XML中存儲複雜資料。

這是編碼後的資料是一個字元串,其中包含的字元為:A-Z、a-z、0-9、+、/共64個字元(其實是65個字元,而“=”是填充字元)。

android 使用SharedPreferences儲存對象

當長度為3個位元組的資料經過Base64編碼後就變為4個位元組,比如

android 使用SharedPreferences儲存對象

如果要編碼的位元組數不能被3整除,最後會多出1個或2個位元組,那麼可以使用下面的方法進行處理:先使用0位元組值在末尾補足,使其能夠被3整除,然後再進行base64的編碼。在編碼後的base64文本後加上一個或兩個’=’号,代表補足的位元組數。也就是說,當最後剩餘一個八位位元組(一個byte)時,最後一個6位的base64位元組塊有四位是0值,最後附加上兩個等号;如果最後剩餘兩個八位位元組(2個byte)時,最後一個6位的base位元組塊有兩位是0值,最後附加一個等号。 參考下表:

android 使用SharedPreferences儲存對象

android 使用SharedPreferences儲存對象就講完了。

就這麼簡單。