【Android】AsyncTaskスレッドを安全に停止・キャンセルする方法を解説
この記事では、Androidアプリで実行中のAsyncTaskスレッドを停止(キャンセル)する方法を、実際に動作するサンプルコードとともにわかりやすく解説します。
ポイント:cancel()メソッドとisCancelled()メソッド
AsyncTaskを停止するには、cancel(boolean)メソッドを呼び出します。引数に「true」を渡すと、バックグラウンド処理を実行中のスレッドに対して割り込み(interrupt)が発生します。さらに、doInBackground()内ではisCancelled()メソッドを使ってタスクがキャンセルされたかどうかを判定し、ループを抜けるなど適切な終了処理を行うのが基本の流れです。
手順1:Android Studioで新規プロジェクトを作成する
Android Studioを起動し、「File」→「New Project」を選択して、必要な項目を入力して新しいプロジェクトを作成してください。
手順2:res/layout/activity_main.xml に以下のコードを追加する
ボタン2つ(タスク実行用・キャンセル用)と結果表示用のTextViewを配置したレイアウトです。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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">
<Button
android:id="@+id/btnDo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/btnCancel"
android:layout_centerInParent="true"
android:layout_marginBottom="25sp"
android:text="Do AsyncTask" />
<Button
android:id="@+id/btnCancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/textView"
android:layout_centerInParent="true"
android:layout_marginBottom="20dp"
android:text="Cancel" />
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textSize="20sp"
android:gravity="center_horizontal" />
</RelativeLayout>手順3:src/MainActivity.java に以下のコードを追加する
「Do AsyncTask」ボタンでタスクを開始し、「Cancel」ボタンで cancel(true) を呼び出して処理を中断します。doInBackground() 内では isCancelled() をチェックし、キャンセルされていればループを抜けます。
import android.graphics.Color;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private Button btnDo, btnCancel;
private TextView textView;
private AsyncTask myTask;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnDo = findViewById(R.id.btnDo);
btnCancel = findViewById(R.id.btnCancel);
textView = findViewById(R.id.textView);
btnDo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
textView.setText("");
myTask = new DownloadTask().execute("Task1",
"Task2", "Task3", "Task4", "Task5");
}
});
btnCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
myTask.cancel(true);
}
});
}
private class DownloadTask extends AsyncTask<String, Integer, List<String>> {
@Override
protected void onPreExecute() {
super.onPreExecute();
textView.setTextColor(Color.BLUE);
textView.setText(textView.getText() + "\n Starting Task....");
}
@Override
protected List<String> doInBackground(String... tasks) {
int count = tasks.length;
List<String> taskList= new ArrayList<>(count);
for(int i =0;i<count;i++){
String currentTask = tasks[i];
taskList.add(currentTask);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
publishProgress((int) (((i+1) / (float) count) * 100));
if(isCancelled()){
break;
}
}
return taskList;
}
@Override
protected void onCancelled() {
super.onCancelled();
textView.setTextColor(Color.RED);
textView.setText(textView.getText() + "\n Operation is cancelled..");
}
@Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
textView.setText(textView.getText()+ "\n Completed:)" + progress[0] + "%");
}
@Override
protected void onPostExecute(List<String> result) {
super.onPostExecute(result);
textView.setText(textView.getText() + "\n\n Done....");
for (int i=0;i<result.size();i++){
textView.setText(textView.getText() + "\n" +
result.get(i));
}
}
}
}手順4:androidManifest.xml に以下のコードを追加する
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="https://schemas.android.com/apk/res/android"
package="app.com.sample">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action
android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>アプリを実行して動作を確認しよう
それでは、実際にアプリを実行してみましょう。実機のAndroidスマートフォンをパソコンに接続していることを前提としています。Android Studioでプロジェクトのアクティビティファイルを開き、ツールバーの「Run」アイコンをクリックします。接続したモバイルデバイスを選択すると、端末に以下のような画面が表示されます。


補足:AsyncTaskは現在非推奨(Deprecated)
なお、AsyncTaskはAPIレベル30(Android 11)以降で非推奨(Deprecated)となっています。新規開発では、Kotlinコルーチン、ExecutorService、HandlerThread、WorkManagerなどの代替手段の利用が推奨されます。ただし、既存コードの保守やレガシーアプリの改修では依然として登場するため、本記事のように cancel(true) と isCancelled() を組み合わせた正しいキャンセル処理の理解は重要です。
-
AndroidでJSONを解析する方法を徹底解説!初心者向けステップバイステップガイド
はじめに この記事では、AndroidアプリでJSONデータを解析(パース)する方法を、実際のコード例とともにわかりやすく解説します。JSONはWeb APIなどで広く利用されているデータ形式であり、Android開発においてその扱い方をマスターすることは非常に重要です。 ステップ1:新規プロジェクトの作成 まず、Android Studioで新しいプロジェクトを作成します。メニューから「File」→「New Project」を選択し、必要な項目をすべて入力してプロジェクトを作成しましょう。 ステップ2:レイアウトファイルの作成 次に、res/layout/activity_main.xm
-
【Android】TextViewでテキストを両端揃え(ジャスティファイ)表示する方法
概要 本記事では、AndroidアプリのTextViewに表示するテキストを両端揃え(ジャスティファイ)にする方法を、サンプルコードとともにわかりやすく解説します。 TextViewで両端揃えを実現するには、android:justificationMode=inter_wordを指定するだけです。この機能はAndroid 8.0(APIレベル26)以降で有効になるため、それ以前のOSバージョンでは無視される点に注意してください。 手順1:新規プロジェクトを作成する まず、Android Studioを起動し、メニューから「File」⇒「New Project」を選択します。必要な項目をす