Android 登enant Wait Indicator実装

AsyncTaskの使用方法を解説した前回の記事に続き、今回は、ログインボタン押下時に表示される著名的な「ローディング中」の UI 作为一种の実装方法を紹介します。ユーザーがログイン情報を入力した後、ボタンをタップすると、一時的な待機ダイアログが表示され、処理が完了するまでユーザーにフィードバックを与えます。 以下にこの機能を簡易的に実装する方法を示します。

1. レイアウト定義 (activity_main.xml)

メールアドレスとパスワードを入力するフィールドと、ログイン/登録ボタンを配置します。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/tvEmailLabel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="メールアドレス" />

    <EditText
        android:id="@+id/etEmail"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/tvEmailLabel"
        android:layout_alignBaseline="@id/tvEmailLabel"
        android:inputType="textEmailAddress" />

    <TextView
        android:id="@+id/tvPasswordLabel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/etEmail"
        android:layout_marginTop="24dp"
        android:text="パスワード" />

    <EditText
        android:id="@+id/etPassword"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/tvPasswordLabel"
        android:layout_alignBaseline="@id/tvPasswordLabel"
        android:inputType="textPassword" />

    <Button
        android:id="@+id/btnLogin"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/etPassword"
        android:layout_marginTop="32dp"
        android:text="ログイン" />

    <Button
        android:id="@+id/btnRegister"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/btnLogin"
        android:layout_alignTop="@id/btnLogin"
        android:layout_marginLeft="24dp"
        android:text="登録" />

</RelativeLayout>

2. Activity 実装

ボタンクリック時に入力値を取得し、AsyncTask を起動して非同期処理を実行。処理前にProgressDialogを表示し、完了時に閉じて結果を通知します。

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private EditText mEmailInput;
    private EditText mPasswordInput;
    private Button mLoginButton;
    private Button mRegisterButton;

    private String email;
    private String password;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bindViews();
    }

    private void bindViews() {
        mEmailInput = findViewById(R.id.etEmail);
        mPasswordInput = findViewById(R.id.etPassword);
        mLoginButton = findViewById(R.id.btnLogin);
        mRegisterButton = findViewById(R.id.btnRegister);

        mLoginButton.setOnClickListener(this);
        mRegisterButton.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        int id = view.getId();
        if (id == R.id.btnLogin) {
            email = mEmailInput.getText().toString().trim();
            password = mPasswordInput.getText().toString().trim();

            new LoginTask().execute();
        } else if (id == R.id.btnRegister) {
            Toast.makeText(this, "登録画面へ遷移中…", Toast.LENGTH_SHORT).show();
        }
    }

    private class LoginTask extends AsyncTask {

        private ProgressDialog loader;

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            loader = new ProgressDialog(this);
            loader.setMessage("処理中です。しばらくお待ちください…");
            loader.setIndeterminate(true);
            loader.setCancelable(false);
            loader.show();
        }

        @Override
        protected Boolean doInBackground(Void... params) {
            // モックサーバーとの通信を模倣
            try {
                Thread.sleep(3000);
            } catch (InterruptedException ignored) {
                return false;
            }

            return "user@example.com".equals(email) && "pass123".equals(password);
        }

        @Override
        protected void onPostExecute(Boolean result) {
            super.onPostExecute(result);
            if (loader != null && loader.isShowing()) {
                loader.dismiss();
            }

            if (result) {
                Toast.makeText(MainActivity.this, "ログイン成功", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(MainActivity.this, "ユーザー名またはパスワードが不正です", Toast.LENGTH_SHORT).show();
            }
        }
    }
}

3. サーバー側モック(※簡易実装)

ネットワーク通信を模擬するためのクラス。実際のサーバー連携部に相当します。

public class MockAuthClient {

    public boolean authenticate(String email, String password) {
        // 模拟IOおよび通信遅延
        try {
            Thread.sleep(2500);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }

        return "test@test.com".equals(email) && "secret".equals(password);
    }
}

※本番環境では、HTTPリクエスト送信やエラーハンドリング、 HTTPS通信などが必要であり、AndroidManifest.xml での <uses-permission android:name="android.permission.INTERNET" /> の宣言も忘れずに。

タグ: Android asynctask ProgressDialog 非同期処理 UIインタラクション

7月7日 17:20 投稿