力技でSharedPreferencesにObjectを保存する

#はじめに
今回は宗教上の理由や一身上の都合等で外部ライブラリを利用したくない人のために、オブジェクトをSharedPreferencesに力技で保存する方法を説明していきます。
~~ちなみに私は社内のOSS利用手続きが面倒くさいしリリースも近いという理由から今回の方法で実装することにしました(小声)~~

初っ端からこの記事を否定するような事を書くのもアレですが、この手の情報を検索すると「[Gson](https://github.com/google/gson)使うと簡単に出来るよー」的な記事が幾つか出てきますので、何も制約が無いのであればそちらの方法をオススメします。

**関連記事**
[PreferenceにObjectを保存すると設定画面の構築が捗る！](http://qiita.com/ueno-yuhei/items/3810576dc391c2513586)
[SharedPrefarenceで好きな型の値を保存する](http://qiita.com/yutori_enginner/items/aa48e8d8b1c68a7c7e1f)

#実装
タイトルに力技とありますが、オブジェクトをBase64でエンコードしてSharedPreferencesにputStringするだけです。
エンコードとデコードのメソッドを作れば保存、読み出しが直ぐに出来ます。

今回はサンプルとしてユーザ情報を入力、保存し、読み込みボタンを押すと保存されている情報が読み出されるというアプリを作りました。（ソースは最後にリンクを貼ってあります）

##UserInfoクラス
名前(String)、年齢(int)、性別(enum)でそれぞれ情報を持ちます。
文字列に変換するためにクラス定義時に**implements Serializable**します。


```java:UserInfo.java
import java.io.Serializable;

/**
 * Created by masaibar on 2015/12/05.
 */
public class UserInfo implements Serializable {

    private String mName;
    private int mAge;
    private Sex mSex;

    public enum Sex {
        MALE,
        FEMALE
    }

    public UserInfo(String name, int age, Sex sex) {
        mName = name;
        mAge = age;
        mSex = sex;
    }

    public String getName() {
        return mName;
    }

    public int getAge() {
        return mAge;
    }

    public Sex getSex() {
        return mSex;
    }
}
```

##変換用メソッド
UserInfoをStringに変換するメソッドと、StringからUserInfoに戻すメソッドです。
putStringする際にはtoBase64を噛ませて文字列として保存し、逆にgetStringする際には文字列にtoUserInfoを噛ませてデータを取得します。

```java
public static String toBase64(UserInfo userInfo) {

    ByteArrayOutputStream byteArrayOutputStream = null;
    ObjectOutputStream objectOutputStream = null;

    try {
        byteArrayOutputStream = new ByteArrayOutputStream();
        objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
        objectOutputStream.writeObject(userInfo);

        byte[] bytes = byteArrayOutputStream.toByteArray();
        byte[] base64 = Base64.encode(bytes, Base64.NO_WRAP);

        return new String(base64);
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (objectOutputStream != null) {
                objectOutputStream.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            if (byteArrayOutputStream != null) {
                byteArrayOutputStream.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    return null;
}

public static UserInfo toUserInfo(String base64) {

    ByteArrayInputStream byteArrayInputStream = null;
    ObjectInputStream objectInputStream = null;

    byte[] bytes = Base64.decode(base64.getBytes(), Base64.NO_WRAP);

    try {
        byteArrayInputStream = new ByteArrayInputStream(bytes);
        objectInputStream = new ObjectInputStream(byteArrayInputStream);
        UserInfo userData = (UserInfo) objectInputStream.readObject();
        return userData;
    } catch (IOException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } finally {
        try {
            if (objectInputStream != null) {
                objectInputStream.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            if (byteArrayInputStream != null) {
                byteArrayInputStream.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    return null;
}
```

##画面イメージ
こんな感じになります。
名前、年齢を入力、性別を選択しSaveを押してSharedPreferencesに保存します。
![image](https://qiita-image-store.s3.amazonaws.com/0/68671/d0e75623-d67c-8d67-d9ac-1de159620e84.png)

一度アプリを終了して再度開くか、CLEARボタンを押して入力をまっさらにしてからLOADを押すと保存されたUserInfoから読み込んで表示します。
![image](https://qiita-image-store.s3.amazonaws.com/0/68671/9a487fe1-7863-ca68-fbb6-fa24ebef0d94.png)

#おわりに
このようにオブジェクトを定義する際にimplements Serializableしておき、Base64で変換することで文字列としてSharedPreferencesに保存することが出来ました。
最初の説明にも書きましたが、OSS利用について何も制約がないのであればGsonライブラリを使った実装のほうがいいと思います、変換後の文字列の可読性も高いしソースもすっきりするので。。。

今回のソースは下記です。
https://github.com/masaibar/SaveObjectSample