Android
 Computer >> コンピューター >  >> プログラミング >> Android

AndroidでArrayListをSharedPreferencesに保存・読み出す方法を徹底解説

SharedPreferencesとは?

Androidアプリ開発において、SharedPreferencesはキーと値のペア形式で少量のデータを永続的に保存するための仕組みです。設定情報やユーザーの入力履歴など、軽量なデータを手軽に保存・取得できるため、多くのアプリで活用されています。

SharedPreferencesで主に使われるメソッドは以下の5つです。

  • edit() ― SharedPreferencesの値を編集するためのEditorオブジェクトを取得します。
  • commit() ― 編集内容をXMLファイルに同期的に書き込みます。処理の成否が戻り値で分かります。
  • apply() ― 編集内容を非同期で反映します。UIスレッドをブロックしないため、通常はこちらが推奨されます。
  • remove(String key) ― 指定したキーと、それに対応する値を削除します。
  • putString() / putInt() など ― キーと値をSharedPreferencesに書き込むために使用します。

SharedPreferencesインスタンスの基本的な取得方法は以下の通りです。

final SharedPreferences sharedPreferences = getSharedPreferences("USER", MODE_PRIVATE);

このコードでは「USER.xml」という名前のSharedPreferencesファイルを作成しています。第2引数にMODE_PRIVATEを指定すると、自アプリからのみアクセスできるプライベートモードとなり、他のアプリからは参照できません。

なお、SharedPreferencesは文字列や数値といったプリミティブ型しか直接保存できません。そのため、ArrayListのようなオブジェクトを保存するには、Gsonライブラリを使ってJSON文字列に変換してから保存するのが一般的です。以下では、その具体的な実装手順をステップごとに紹介します。

実装例:ArrayListをSharedPreferencesに保存するサンプルアプリ

ここでは、ユーザーが入力した「名前」と「電話番号」をArrayListとしてSharedPreferencesに保存し、あとから読み出して画面に表示するサンプルアプリを作成します。

ステップ1:新規プロジェクトの作成

Android Studioを起動し、「File → New Project」を選択して必要事項を入力し、新しいプロジェクトを作成します。

ステップ2:レイアウトファイル(activity_main.xml)の編集

res/layout/activity_main.xml に以下のコードを追加します。

<?xml version = "1.0" encoding = "utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android = "https://schemas.android.com/apk/res/android"
    xmlns:app = "https://schemas.android.com/apk/res-auto"
    xmlns:tools = "https://schemas.android.com/tools"
    android:layout_width = "match_parent"
    android:layout_height = "match_parent"
    android:orientation = "vertical"
    tools:context = ".MainActivity"
    tools:layout_editor_absoluteY = "81dp">
    <EditText
        android:id = "@+id/name"
        android:layout_width = "match_parent"
        android:layout_height = "60dp"
        android:layout_marginTop = "8dp"
        android:autofillHints = ""
        android:hint = "NAME"
        app:layout_constraintTop_toTopOf = "parent"
        tools:layout_editor_absoluteX = "0dp" />
    <EditText
        android:id = "@+id/address"
        android:layout_width = "match_parent"
        android:layout_height = "wrap_content"
        android:layout_marginTop = "84dp"
        android:hint = "Phone Number"
        android:importantForAutofill = "no"
        android:inputType = ""
        app:layout_constraintTop_toTopOf = "@+id/name"
        tools:layout_editor_absoluteX = "16dp"
        tools:targetApi = "o" />
    <Button
        android:id = "@+id/button"
        android:layout_width = "108dp"
        android:layout_height = "wrap_content"
        android:layout_marginStart = "8dp"
        android:layout_marginLeft = "8dp"
        android:layout_marginTop = "120dp"
        android:layout_marginEnd = "8dp"
        android:layout_marginRight = "8dp"
        android:gravity = "center_horizontal"
        android:text = "Save"
        app:layout_constraintEnd_toEndOf = "parent"
        app:layout_constraintHorizontal_bias = "0.503"
        app:layout_constraintStart_toStartOf = "parent"
        app:layout_constraintTop_toTopOf = "@+id/address" />
    <Button
        android:id = "@+id/read"
        android:layout_width = "wrap_content"
        android:layout_height = "wrap_content"
        android:layout_marginStart = "8dp"
        android:layout_marginLeft = "8dp"
        android:layout_marginTop = "88dp"
        android:layout_marginEnd = "8dp"
        android:layout_marginRight = "8dp"
        android:gravity = "center_horizontal"
        android:text = "read"
        app:layout_constraintEnd_toEndOf = "parent"
        app:layout_constraintStart_toStartOf = "parent"
        app:layout_constraintTop_toBottomOf = "@+id/button" />
    <TextView
        android:id = "@+id/result"
        android:layout_width = "wrap_content"
        android:layout_height = "0dp"
        android:layout_marginStart = "8dp"
        android:layout_marginLeft = "8dp"
        android:layout_marginTop = "184dp"
        android:layout_marginEnd = "8dp"
        android:layout_marginRight = "8dp"
        android:text = "result"
        app:layout_constraintEnd_toEndOf = "parent"
        app:layout_constraintStart_toStartOf = "parent"
        app:layout_constraintTop_toBottomOf = "@+id/button" />
</android.support.constraint.ConstraintLayout>

このレイアウトには、名前用と電話番号用の2つのEditText、保存用の「Save」ボタン、読み出し用の「read」ボタン、そして結果表示用のTextViewが配置されています。「Save」ボタンをタップすると入力値が配列としてSharedPreferencesに保存され、「read」ボタンをタップすると保存済みのデータを読み出してTextViewに表示される仕組みです。

ステップ3:MainActivity.java の実装

src/MainActivity.java に以下のコードを記述します。

package com.example.andy.myapplication;
import android.annotation.SuppressLint;
import android.content.SharedPreferences;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        final ArrayList<String> arrPackage;
        setContentView(R.layout.activity_main);
        final SharedPreferences sharedPreferences = getSharedPreferences("USER",MODE_PRIVATE);
        final EditText name = findViewById(R.id.name);
        final EditText address = findViewById(R.id.address);
        final TextView result = findViewById(R.id.result);
        Button save = findViewById(R.id.button);
        Button read = findViewById(R.id.read);
        arrPackage = new ArrayList<>();
        read.setOnClickListener(new View.OnClickListener() {
            @SuppressLint("LongLogTag")
            @Override
            public void onClick(View v) {
                Gson gson = new Gson();
                String json = sharedPreferences.getString("Set", "");
                if (json.isEmpty()) {
                    Toast.makeText(MainActivity.this,"There is something error",Toast.LENGTH_LONG).show();
                } else {
                    Type type = new TypeToken<List<String>>() {
                    }.getType();
                    List<String> arrPackageData = gson.fromJson(json, type);
                    for(String data:arrPackageData) {
                        result.setText(data);
                    }
                }
            }
        });
        save.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(name.getText().toString().isEmpty() && address.getText().toString().isEmpty()) {
                    Toast.makeText(MainActivity.this,"Plz Enter all the data",Toast.LENGTH_LONG).show();
                }else{
                    String nameData = name.getText().toString().trim();
                    String addressData = address.getText().toString().trim();
                    arrPackage.add(nameData);
                    arrPackage.add(addressData);
                    Gson gson = new Gson();
                    String json = gson.toJson(arrPackage);
                    SharedPreferences.Editor editor = sharedPreferences.edit();
                    editor.putString("Set",json );
                    editor.commit();
                }
            }
        });
    }

このコードのポイントは、ArrayListをGsonでJSON文字列にシリアライズしてSharedPreferencesに保存し、読み出し時にはJSON文字列をTypeTokenを使って再びList<String>にデシリアライズしている点です。これにより、配列データをそのまま文字列として永続化できます。

ステップ4:build.gradleにGsonライブラリを追加

Gsonを利用するには、appレベルのbuild.gradleのdependenciesブロックに以下の依存関係を追加します。

apply plugin: 'com.android.application'
android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.example.andy.myapplication"
        minSdkVersion 15
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.google.code.gson:gson:2.8.5'
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'

ステップ5:アプリの実行

manifest.xmlを変更する必要はありません。そのままアプリを実行してみましょう。

Android端末をPCに接続している場合は、Android Studioでプロジェクト内のアクティビティファイルを開き、ツールバーの「Run」アイコンをクリックします。接続中の実機を選択して実行すると、端末に以下の初期画面が表示されます。

AndroidでArrayListをSharedPreferencesに保存・読み出す方法を徹底解説

上の画面では、名前と電話番号を入力して「Save」ボタンをタップしたところです。この時点で、入力データはArrayListとしてJSON形式に変換され、SharedPreferencesに保存されています。

AndroidでArrayListをSharedPreferencesに保存・読み出す方法を徹底解説

続いて「read」ボタンをタップすると、SharedPreferencesから保存済みのデータが読み出され、TextViewに表示されます。

まとめ

SharedPreferencesは単純なキーバリュー保存のための仕組みですが、Gsonと組み合わせることでArrayListやカスタムオブジェクトも簡単に永続化できます。ただし、保存できるのはあくまで文字列として変換したデータなので、大量のデータや複雑なリレーションを扱う場合は、Roomなどのデータベースの利用も併せて検討するとよいでしょう。

  1. AndroidでGmailの添付ファイルを保存する2つの簡単な方法

    以前のAndroidでは、Gmailの添付ファイルをスマホに保存するのはかなり面倒な作業でした。しかし、昨年のGmailアプリの大型アップデート以降、操作は格段に簡単になりました。なんと、添付ファイルが含まれたメール本文を開かなくても、受信トレイから直接ダウンロードできるようになったのです。 この記事では、AndroidでGmailの添付ファイルを保存する2つの方法をわかりやすくご紹介します。 方法1:受信トレイから直接保存する 最新版のGmailアプリでは、メールを開かずとも受信トレイから添付ファイルへ直接アクセスできます。 注意: 受信トレイに添付ファイルを表示するには、「会話

  2. AndroidでTwitter(X)のGIFを保存する方法【アプリ・サイト別に解説】

    Twitter(現X)は、単なるSNSの枠を超え、世界で起きている出来事の情報収集だけでなく、企業や有名人、政治家、学生など、さまざまな人々が意見を発信・拡散するためのプラットフォームとして活用されています。このミニブログサービスでは、一般ユーザーでもTwitterハンドル(ユーザー名)を使ってメンションするだけで、著名人と直接やり取りすることも可能です。 Twitter上では、動画や写真から、今や大人気のGIFやミームまで、あらゆる形式のメディアが投稿されています。発音をめぐる議論はさておき、こうした短い動画クリップが、長文の文章に代わって感情や考えを伝える手段として定着しつつあるのは間違い