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

【Android】シングルトンクラスを1時間ごとに自動更新する方法を実例付きで解説

シングルトンパターンとは?

実装例に入る前に、まず「シングルトンデザインパターン」について簡単におさらいしておきましょう。シングルトンとは、あるクラスのインスタンス生成を1つだけに制限するデザインパターンです。主な用途としては、並行処理(同時アクセス)の制御や、アプリケーション全体からデータストアへアクセスするための中心的なアクセスポイントの作成などが挙げられます。

本記事では、Androidアプリにおいてシングルトンのインスタンスを1時間ごとに自動的にリフレッシュ(再生成)する方法を、実際に動くサンプルコードとともに段階的に解説していきます。

手順1:新規プロジェクトを作成する

Android Studioを開き、メニューから File → New Project を選択します。必要な項目をすべて入力して、新しいプロジェクトを作成してください。

手順2:レイアウトファイル(activity_main.xml)を編集する

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

<?xml version = "1.0" encoding = "utf-8"?>
<LinearLayout xmlns:android = "https://schemas.android.com/apk/res/android"
   xmlns:tools = "https://schemas.android.com/tools"
   android:layout_width = "match_parent"
   android:layout_height = "match_parent"
   tools:context = ".MainActivity"
   android:orientation = "vertical">
   <Button
      android:id = "@+id/show"
      android:text = "refresh singleTone"
      android:layout_width = "wrap_content"
      android:layout_height = "wrap_content" />
</LinearLayout>

上記のコードでは、ボタンを1つだけ配置しています。ユーザーがこのボタンをタップすると、トースト(Toast)が画面に表示される仕組みです。

手順3:MainActivity.java を編集する

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

package com.example.andy.myapplication;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import org.json.JSONException;
import org.json.JSONObject;
public class MainActivity extends AppCompatActivity {
    Button show;
    JSONObject jsonObject;
    singleTonExample singletonexample;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        show = findViewById(R.id.show);
        singletonexample = singleTonExample.getInstance();
        singletonexample.init(getApplicationContext());
        show.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(MainActivity.this,"Refersh Singlton class every one hour", Toast.LENGTH_LONG).show();
            }
        });
    }
}

ここでのポイントは、singleTonExample というクラスをシングルトンとして扱っている点です。続いて、singleTonExample.java という新しいクラスファイルを作成し、以下のコードを追加しましょう。

package com.example.andy.myapplication;
import android.content.Context;
import java.util.Timer;
import java.util.TimerTask;
public class singleTonExample {
    private static singleTonExample ourInstance = new singleTonExample();
    static {
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            public void run() {
                synchronized (singleTonExample.class) {
                    ourInstance = new singleTonExample();
                }
            }
        }, 60 * 60 * 1000L /* 1時間ごとに1回実行 */);
    }
    private Context appContext;
    private singleTonExample() { }
    public static Context get() {
        return getInstance().getContext();
    }
    public static synchronized singleTonExample getInstance() {
        return ourInstance;
    }
    public void init(Context context) {
        if (appContext == null) {
            this.appContext = context;
        }
    }
    private Context getContext() {
        return appContext;
    }
}

このコードの仕組み

このシングルトンクラスの核となるのは、staticイニシャライザブロック(static { })内の Timer 処理です。ポイントは以下の通りです。

  • timer.schedule() の第2引数に 60 * 60 * 1000L(= 3,600,000ミリ秒=1時間)を指定することで、起動から1時間後に1度だけタスクが実行されます。
  • タスク内では synchronized ブロックを使って排他制御を行い、ourInstance を新しいインスタンスで置き換えています。これにより、古い状態を持ったインスタンスを破棄し、最新の状態を持つ新しいシングルトンへ安全に差し替えられます。
  • synchronized getInstance() メソッドにより、マルチスレッド環境下でも常に同一のインスタンスが返されることが保証されます。
  • init(Context) はアプリケーションコンテキストを保持するためのメソッドで、nullチェックにより複数回の初期化を防止しています。

アプリを実行してみよう

それでは、作成したアプリケーションを実際に動かしてみましょう。実機のAndroidスマートフォンをパソコンに接続していることを前提としています。Android Studioからアプリを実行するには、プロジェクト内のアクティビティファイルをいずれか開き、ツールバーにある Run(再生アイコン) をクリックします。

表示された候補の中から自分のモバイルデバイスを選択すると、接続した端末の画面にアプリのデフォルト画面が表示されます。

次に、画面上のボタンをタップすると、以下のようにトーストメッセージが表示されます。

補足:より現代的な代替手段について

なお、サンプルコード中の android.support.v7.app.AppCompatActivity は旧サポートライブラリのものであり、現在のAndroid Studioでプロジェクトを作成した場合は androidx.appcompat.app.AppCompatActivity への置き換えが必要になる点に注意してください。

また、Timer / TimerTask 以外にも、定期処理の実装方法はいくつかあります。

  • Handler + postDelayed … UIスレッドとの連携が容易で、短周期の繰り返し処理に向いています。
  • WorkManager … アプリが終了していても確実に定期タスクを実行したい場合(バックグラウンド同期など)に最適な、現在推奨されているAPIです。

用途やライフサイクルの要件に応じて、最適な手法を選択するとよいでしょう。

  1. AndroidでStringBuilderクラスを使う方法を実例付きで解説

    具体的な例に入る前に、まずStringBuilderクラスの基本について確認しておきましょう。StringBuilderクラスは可変(ミュータブル)な文字列を生成するためのクラスです。スレッドセーフではないため、複数のスレッドから同時にアクセス可能という特徴があります。本記事では、AndroidアプリでStringBuilderクラスを実際に使う方法を、サンプルコードとともに段階的に解説します。StringBuilderの主な特徴文字列を自由に追加・挿入・削除・変更できる(可変)Stringと異なり、操作のたびに新しいオブジェクトを生成しないため高速スレッドセーフではない(同期が必要な場合はS

  2. Androidでフラグメント間のデータ受け渡しを実装する方法【サンプルコード付き】

    はじめに 本記事では、Androidアプリ開発において、あるフラグメント(Fragment)から別のフラグメントへデータを受け渡す方法を解説します。ここではインターフェース(コールバック)を使用し、ホストとなるActivityを経由して2つのフラグメント間でメッセージをやり取りする、定番の実装パターンをサンプルコード付きでステップごとに紹介します。 全体の仕組み 今回のサンプルでは、以下のような流れでデータを受け渡します。 FirstFragment:TextViewがタップされると、リスナー経由でメッセージを送信する MainActivity:FirstFragmentからのコールバックを