サーチ…


パラメーター

パラメータ詳細
Params 実行時にタスクに送信されるパラメータのタイプ。
進捗バックグラウンド計算中に発行された進行単位のタイプ
結果バックグラウンド計算の結果の型。

基本的な使用法

Androidのアクティビティサービスでは 、ほとんどのコールバックはメインスレッドで実行されます 。これは、UIを更新することが簡単になりますが、メインスレッド上で、プロセッサにまたはI / O-重いタスクを実行すると、あなたのUIが(一時停止し、応答しなくなることがあります公式ドキュメント 、次に何が起こるか上を)。

これらの重いタスクをバックグラウンドスレッドに置くことでこれを解決できます。

これを行うための1つの方法は、バックグラウンドスレッドの使い方を容易にするためのフレームワークを提供するAsyncTaskを使用することです。バックグラウンドスレッドが作業を完了する前、実行中および実行後にUIスレッドタスクを実行します。

AsyncTask拡張するときにオーバーライドできるメソッド:

  • onPreExecute() :タスクが実行される前にUIスレッドで呼び出されます。
  • doInBackground()onPreExecute()実行が終了した直後にバックグラウンドスレッドで呼び出されます。
  • onProgressUpdate()publishProgress(Progress...)呼び出し後にUIスレッドで呼び出されpublishProgress(Progress...)
  • onPostExecute() :バックグラウンド計算が終了した後にUIスレッドで呼び出されます。

public class MyCustomAsyncTask extends AsyncTask<File, Void, String> {

    
    @Override
    protected void onPreExecute(){
        // This runs on the UI thread before the background thread executes.
        super.onPreExecute();
        // Do pre-thread tasks such as initializing variables. 
        Log.v("myBackgroundTask", "Starting Background Task");  
    }

    @Override
    protected String doInBackground(File... params) {
        // Disk-intensive work. This runs on a background thread.
        // Search through a file for the first line that contains "Hello", and return
        // that line.
        try (Scanner scanner = new Scanner(params[0])) {
            while (scanner.hasNextLine()) {
                final String line = scanner.nextLine();
                publishProgress(); // tell the UI thread we made progress

                if (line.contains("Hello")) {
                    return line;
                }
            }
            return null;
        }
    }

    @Override
    protected void onProgressUpdate(Void...p) {
        // Runs on the UI thread after publishProgress is invoked
        Log.v("Read another line!")
    }        

    @Override
    protected void onPostExecute(String s) {
        // This runs on the UI thread after complete execution of the doInBackground() method
        // This function receives result(String s) returned from the doInBackground() method.
        // Update UI with the found string.
        TextView view = (TextView) findViewById(R.id.found_string);
        if (s != null) {
            view.setText(s);
        } else {
            view.setText("Match not found.");
        }
    }

}

使用法:

MyCustomAsyncTask asyncTask = new MyCustomAsyncTask<File, Void, String>();
// Run the task with a user supplied filename.
asyncTask.execute(userSuppliedFilename);

または単に:

new MyCustomAsyncTask().execute(userSuppliedFilename);

注意

AsyncTaskを定義するAsyncTaskは、 < >間に3つの型を渡すことができます。
<Params, Progress, Result>パラメータセクションを参照 )として定義されています。

前の例では<File, Void, String>型を使用しています:

AsyncTask<File, Void, String>
// Params has type File
// Progress has unused type
// Result has type String

Voidは、型を未使用としてマークする場合に使用されます。

プリミティブ型( intfloatなど)をパラメータとして渡すことはできません。そのような場合は、 ラッパークラスを渡す必要があります 。たとえば、 int代わりにIntegerFloat代わりにfloatです。

AsyncTaskおよびActivityのライフサイクル

AsyncTasksはアクティビティインスタンスのライフサイクルに従いません。アクティビティ内でAsyncTaskを開始し、デバイスを回転させると、アクティビティが破棄され、新しいインスタンスが作成されます。しかし、AsyncTaskは死ぬことはありません。それは完了するまで生き続けるでしょう。

ソリューション:AsyncTaskLoader

一つのサブクラスローダーは AsyncTaskLoaderです。このクラスは、AsyncTaskと同じ機能を実行しますが、はるかに優れています。アクティビティの設定変更をより簡単に処理でき、フラグメントやアクティビティのライフサイクル内で動作します。いいことは、AsyncTaskLoaderは、AsyncTaskが使用されているどのような状況でも使用できることです。 Activity / Fragmentが処理するためにいつでもデータをメモリにロードする必要がある場合、AsyncTaskLoaderはより良い仕事をすることができます。

AsyncTaskのキャンセル

YourAsyncTask task = new YourAsyncTask();
task.execute();
task.cancel();

これは進行中の場合、あなたのタスクを止めません。キャンセルされたフラグを設定します。これは、 isCancelled()戻り値をチェックすることによってチェックできます(コードが現在実行中であると仮定します)。

class YourAsyncTask extends AsyncTask<Void, Void, Void> {
    @Override
    protected Void doInBackground(Void... params) {
        while(!isCancelled()) {
            ... doing long task stuff
            //Do something, you need, upload part of file, for example
            if (isCancelled()) {    
                return null; // Task was detected as canceled
            }
            if (yourTaskCompleted) {
                return null;
            }
        }
    }
}

注意

一方、AsyncTaskがキャンセルされた場合doInBackground(Params... params)まだ、その後実行されている方法onPostExecute(Result result)後に呼び出されません doInBackground(Params... params)戻ります。 AsyncTaskは代わりにonCancelled(Result result)を呼び出して、実行中にタスクがキャンセルされたことを示します。

発行の進捗状況

時には、 AsyncTaskによって行われる計算の進捗を更新する必要があります。この進展は、文字列、整数などで表すことができます。これを行うには、2つの関数を使用する必要があります。まず、設定する必要がonProgressUpdateそのパラメータの種類当社の第二種のパラメータと同じである機能AsyncTask

class YourAsyncTask extends AsyncTask<URL, Integer, Long> {
    @Override
    protected void onProgressUpdate(Integer... args) {
        setProgressPercent(args[0])
    }
}

第二に、我々は関数を使用する必要がpublishProgress上必ずしもdoInBackground機能、およびそれがすべてで、従来の方法では、すべての仕事を行います。

protected Long doInBackground(URL... urls) {
     int count = urls.length;
     long totalSize = 0;
     for (int i = 0; i < count; i++) {
         totalSize += Downloader.downloadFile(urls[i]);
         publishProgress((int) ((i / (float) count) * 100));
     }
     return totalSize;
 }

AndroidでAsyncTaskを使用して画像をダウンロードする

このチュートリアルでは、AndroidでAsyncTaskを使用してイメージをダウンロードする方法について説明します。下の例では、ダウンロード中にプログレスバーを表示しながらイメージをダウンロードしています。

Android AsyncTaskについて

非同期タスクを使用すると、Handsをスレッドに追加しなくてもMultiThreadingを実装できます。 AsyncTaskを使用すると、UIスレッドを適切かつ簡単に使用できます。バックグラウンド操作を実行し、UIスレッドで結果を渡すことができます。 UIに関連する何かを分離している、例えばリストに表示するデータをダウンロードする場合は、AsyncTaskを使用してください。

  • AsyncTasksは、短時間の操作(理想的には数秒以内)に使用するのが理想的です。
  • 非同期タスクは、Params、ProgressおよびResult、およびonPreExecute()doInBackground()onProgressUpdate()およびonPostExecute()と呼ばれる3つのジェネリックタイプによって定義されます。
  • onPreExecute()では、バックグラウンド処理を開始する前に実行する必要があるコードを定義することができます。
  • doInBackgroundにはバックグラウンドで実行する必要のあるコードがあります。ここではdoInBackground() publishProgress()メソッドで複数回結果をイベントスレッドに送信し、バックグラウンド処理が完了したことを通知して結果を返すことができます。
  • onProgressUpdate()メソッドは、 doInBackground()メソッドを介して公開されているpublishProgress()メソッドから進行状況の更新を受け取り、このメソッドはこの進行状況更新を使用してイベントスレッド
  • onPostExecute()メソッドは、 doInBackground()メソッドによって返された結果を処理します。
  • 使用されるジェネリックタイプは、
    • Params、実行時にタスクに送信されるパラメータのタイプ
    • 進捗状況:バックグラウンド計算中に発行された進捗単位のタイプ。
    • 結果、バックグラウンド計算の結果のタイプ。
  • 非同期タスクがタイプを使用していない場合は、Voidタイプとしてマークすることができます。
  • 実行中の非同期タスクは、 cancel(boolean)メソッドを呼び出すcancel(boolean)によってcancel(boolean)ことができます。

Android AsyncTaskを使用して画像をダウンロードする

.xmlレイアウト

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

<Button
    android:id="@+id/downloadButton"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Click Here to Download" />

<ImageView
    android:id="@+id/imageView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:contentDescription="Your image will appear here" />

</LinearLayout>

.javaクラス

package com.javatechig.droid;

import java.io.InputStream;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.app.Activity;
import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;

public class ImageDownladerActivity extends Activity {

    private ImageView downloadedImg;
    private ProgressDialog simpleWaitDialog;
    private String downloadUrl = "http://www.9ori.com/store/media/images/8ab579a656.jpg";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.asynch);
        Button imageDownloaderBtn = (Button) findViewById(R.id.downloadButton);

        downloadedImg = (ImageView) findViewById(R.id.imageView);

        imageDownloaderBtn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                new ImageDownloader().execute(downloadUrl);
            }

        });
    }

    private class ImageDownloader extends AsyncTask {

        @Override
        protected Bitmap doInBackground(String... param) {
            // TODO Auto-generated method stub
            return downloadBitmap(param[0]);
        }

        @Override
        protected void onPreExecute() {
            Log.i("Async-Example", "onPreExecute Called");
            simpleWaitDialog = ProgressDialog.show(ImageDownladerActivity.this,
                    "Wait", "Downloading Image");

        }

        @Override
        protected void onPostExecute(Bitmap result) {
            Log.i("Async-Example", "onPostExecute Called");
            downloadedImg.setImageBitmap(result);
            simpleWaitDialog.dismiss();

        }

        private Bitmap downloadBitmap(String url) {
            // initilize the default HTTP client object
            final DefaultHttpClient client = new DefaultHttpClient();

            //forming a HttpGet request 
            final HttpGet getRequest = new HttpGet(url);
            try {

                HttpResponse response = client.execute(getRequest);

                //check 200 OK for success
                final int statusCode = response.getStatusLine().getStatusCode();

                if (statusCode != HttpStatus.SC_OK) {
                    Log.w("ImageDownloader", "Error " + statusCode + 
                            " while retrieving bitmap from " + url);
                    return null;

                }

                final HttpEntity entity = response.getEntity();
                if (entity != null) {
                    InputStream inputStream = null;
                    try {
                        // getting contents from the stream 
                        inputStream = entity.getContent();

                        // decoding stream data back into image Bitmap that android understands
                        final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);

                        return bitmap;
                    } finally {
                        if (inputStream != null) {
                            inputStream.close();
                        }
                        entity.consumeContent();
                    }
                }
            } catch (Exception e) {
                // You Could provide a more explicit error message for IOException
                getRequest.abort();
                Log.e("ImageDownloader", "Something went wrong while" +
                        " retrieving bitmap from " + url + e.toString());
            } 

            return null;
        }
    }
}

現在のところ、例のためのコメントフィールドがない(または私はそれを見つけられていないか、または私はそれのための許可を得ていない)ので、ここにいくつかのコメントがあります:

これは、AsyncTaskで何ができるかを示す良い例です。

しかし、この例では現在、

  • メモリリークの可能性
  • 非同期タスクが完了する直前に画面が回転した場合、アプリケーションがクラッシュする

詳細は、以下を参照してください。

WeakReferenceとしてアクティビティを渡してメモリリークを回避する

AsyncTaskは、それを呼び出すアクティビティへの参照を要求するのが一般的です。

AsyncTaskがActivityの内部クラスである場合、AsyncTaskとそのメンバー変数/メソッドを直接参照できます。

ただし、AsyncTaskがActivityの内部クラスでない場合は、Activity参照をAsyncTaskに渡す必要があります。これを行うと、発生する可能性のある問題の1つは、AsyncTaskがそのバックグラウンドスレッドで作業を完了するまで、AsyncTaskがアクティビティの参照を保持することです。 AsyncTaskのバックグラウンドスレッドの作業が完了する前にアクティビティが終了または終了すると、AsyncTaskはアクティビティへの参照を保持しているため、ガベージコレクションできません。

その結果、メモリリークが発生します。

これを防ぐには、アクティビティへの直接参照ではなくAsyncTaskでWeakReferenceを使用します。

WeakReferenceを利用するAsyncTaskの例を次に示します。

private class MyAsyncTask extends AsyncTask<String, Void, Void> {

    private WeakReference<Activity> mActivity;

    public MyAsyncTask(Activity activity) {
        mActivity = new WeakReference<Activity>(activity);
    }

    @Override
    protected void onPreExecute() {
        final Activity activity = mActivity.get();
        if (activity != null) {
            ....
        }
    }

    @Override
    protected Void doInBackground(String... params) {
        //Do something
        String param1 = params[0];
        String param2 = params[1];
        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        final Activity activity = mActivity.get();
        if (activity != null) {
            activity.updateUI();
        }
    }
} 

アクティビティからAsyncTaskを呼び出す:

new MyAsyncTask(this).execute("param1", "param2");

フラグメントからAsyncTaskを呼び出す:

new MyAsyncTask(getActivity()).execute("param1", "param2");

実行命令

最初に導入されたとき、 AsyncTasksは1つのバックグラウンドスレッドで連続して実行されました。 DONUTから始めて、これはスレッドのプールに変更され、複数のタスクを並列に動作させることができました。 HONEYCOMB開始すると、タスクは1つのスレッド上で実行され、並列実行によって発生する一般的なアプリケーションエラーを回避します。

あなたが本当に並列実行したい場合は、呼び出すことができますexecuteOnExecutor(java.util.concurrent.Executor, Object[])THREAD_POOL_EXECUTOR

SERIAL_EXECUTOR - >一度に1つのタスクを連続して実行するExecutor。

THREAD_POOL_EXECUTOR - >タスクを並行して実行するために使用できるExecutor。

サンプル :

Task task = new Task();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
    task.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, data);
else
    task.execute(data);

AsyncTask:タスクの連続実行と並列実行

AsyncTaskは抽象クラスであり、 Threadクラスを継承しません。 抽象メソッドdoInBackground(Params... params)があり、タスクを実行するためにオーバーライドされています。このメソッドはAsyncTask.call()から呼び出されます。

Executorはjava.util.concurrentパッケージの一部です。

さらに、AsyncTaskには2つのExecutorが含まれています

THREAD_POOL_EXECUTOR

ワーカースレッドを使用してタスクを並行して実行します。

public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);

SERIAL_EXECUTOR

それは、タスクを連続的に、すなわち1つずつ実行する。

private static class SerialExecutor implements Executor { }

どちらのExecutor sが静的であり、それゆえ一つだけTHREAD_POOL_EXECUTORと1 SerialExecutorオブジェクトが存在しますが、あなたはいくつか作成することができAsyncTaskオブジェクトを。

したがって、デフォルトのExecutor( SerialExecutor )で複数のバックグラウンドタスクを実行しようとすると、これらのタスクはキューに入れられ、順次実行されます。

THREAD_POOL_EXECUTORで複数のバックグラウンドタスクを実行しようとすると、それらは並列に実行されます。

例:

public class MainActivity extends Activity {
    private Button bt;
    private int CountTask = 0;
    private static final String TAG = "AsyncTaskExample";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bt = (Button) findViewById(R.id.button);
        bt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                BackgroundTask backgroundTask = new BackgroundTask ();
                Integer data[] = { ++CountTask, null, null };

                // Task Executed in thread pool ( 1 )
                backgroundTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, data);

                // Task executed Serially ( 2 )
                // Uncomment the below code and comment the above code of Thread
                // pool Executor and check
                // backgroundTask.execute(data);
                Log.d(TAG, "Task = " + (int) CountTask + " Task Queued");

            }
        });

    }

    private class BackgroundTask extends AsyncTask<Integer, Integer, Integer> {
        int taskNumber;

        @Override
        protected Integer doInBackground(Integer... integers) {
            taskNumber = integers[0];

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            Log.d(TAG, "Task = " + taskNumber + " Task Running in Background");

            publishProgress(taskNumber);
            return null;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected void onPostExecute(Integer aLong) {
            super.onPostExecute(aLong);
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            Log.d(TAG, "Task = " + (int) values[0]
                    + " Task Execution Completed");
        }
    }
}

Performボタンを数回クリックすると、タスクが開始され、結果が表示されます。

スレッドプール(1)で実行されたタスク

各タスクは完了するのに1000msかかる。

t = 36sでは、タスク2,3,4は並行して実行されているためキューに入れられ、実行も開始されます。

08-02 19:48:35.815: D/AsyncTaskExample(11693): Task = 1 Task Queued
08-02 19:48:35.815: D/AsyncTaskExample(11693): Task = 1 Task Running in Background
08-02 19:48:**36.025**: D/AsyncTaskExample(11693): Task = 2 Task Queued
08-02 19:48:**36.025**: D/AsyncTaskExample(11693): Task = 2 Task Running in Background
08-02 19:48:**36.165**: D/AsyncTaskExample(11693): Task = 3 Task Queued
08-02 19:48:**36.165**: D/AsyncTaskExample(11693): Task = 3 Task Running in Background
08-02 19:48:**36.325**: D/AsyncTaskExample(11693): Task = 4 Task Queued
08-02 19:48:**36.325**: D/AsyncTaskExample(11693): Task = 4 Task Running in Background
08-02 19:48:**36.815**: D/AsyncTaskExample(11693): Task = 1 Task Execution Completed
08-02 19:48:**36.915**: D/AsyncTaskExample(11693): Task = 5 Task Queued
08-02 19:48:**36.915**: D/AsyncTaskExample(11693): Task = 5 Task Running in Background
08-02 19:48:37.025: D/AsyncTaskExample(11693): Task = 2 Task Execution Completed
08-02 19:48:37.165: D/AsyncTaskExample(11693): Task = 3 Task Execution Completed
----------

コメントTask Executed in thread pool (1)でTask executed Serially (2)でTask executed Seriallyコメントを外します。

Performボタンを数回クリックすると、タスクが開始され、結果が表示されます。

逐次的にタスクを実行しているため、現在のタスクの実行が完了した後にすべてのタスクが開始されます。したがって、タスク1の実行が完了すると、タスク2のみがバックグラウンドで実行を開始します。逆に。

08-02 19:42:57.505: D/AsyncTaskExample(10299): Task = 1 Task Queued
08-02 19:42:57.505: D/AsyncTaskExample(10299): Task = 1 Task Running in Background
08-02 19:42:57.675: D/AsyncTaskExample(10299): Task = 2 Task Queued
08-02 19:42:57.835: D/AsyncTaskExample(10299): Task = 3 Task Queued
08-02 19:42:58.005: D/AsyncTaskExample(10299): Task = 4 Task Queued
08-02 19:42:58.155: D/AsyncTaskExample(10299): Task = 5 Task Queued
08-02 19:42:58.505: D/AsyncTaskExample(10299): Task = 1 Task Execution Completed
08-02 19:42:58.505: D/AsyncTaskExample(10299): Task = 2 Task Running in Background
08-02 19:42:58.755: D/AsyncTaskExample(10299): Task = 6 Task Queued
08-02 19:42:59.295: D/AsyncTaskExample(10299): Task = 7 Task Queued
08-02 19:42:59.505: D/AsyncTaskExample(10299): Task = 2 Task Execution Completed
08-02 19:42:59.505: D/AsyncTaskExample(10299): Task = 3 Task Running in Background
08-02 19:43:00.035: D/AsyncTaskExample(10299): Task = 8 Task Queued
08-02 19:43:00.505: D/AsyncTaskExample(10299): Task = 3 Task Execution Completed
08-02 19:43:**00.505**: D/AsyncTaskExample(10299): Task = 4 Task Running in Background
08-02 19:43:**01.505**: D/AsyncTaskExample(10299): Task = 4 Task Execution Completed
08-02 19:43:**01.515**: D/AsyncTaskExample(10299): Task = 5 Task Running in Background
08-02 19:43:**02.515**: D/AsyncTaskExample(10299): Task = 5 Task Execution Completed
08-02 19:43:**02.515**: D/AsyncTaskExample(10299): Task = 6 Task Running in Background
08-02 19:43:**03.515**: D/AsyncTaskExample(10299): Task = 7 Task Running in Background
08-02 19:43:**03.515**: D/AsyncTaskExample(10299): Task = 6 Task Execution Completed
08-02 19:43:04.515: D/AsyncTaskExample(10299): Task = 8 Task Running in Background
08-02 19:43:**04.515**: D/AsyncTaskExample(10299): Task = 7 Task Execution Completed


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow