51歳からのプログラミング　備忘　AsyncTask - reference [写経]

>https://developer.android.com/reference/android/os/AsyncTask

個人的な写経的なまとめ的なものです。誤記誤訳があったらごめんね。

[マルチスレッドまとめ的なのはここ]
(https://qiita.com/old_cat/items/a6d71f18a0789351c1a3)

**public abstract class AsyncTask extends Object**
**android.os.AsyncTask\<Param,Progress,Result>**

[非同期通信後の処理や、AsyncTaskの汎用化といか共通化？について](https://qiita.com/old_cat/items/ff4f2116192fd536fb59)

#AsyncTask概要

AsyncTaskは簡単かつ適切にUIスレッドを扱ます。ThreadやHandlerを使わずに、バックグラウンドで処理し、結果をUIスレッドに戻します。

AsyncTaskはThreadやHandlerなどを扱うヘルパークラス(インスタンス化して使う:staticメソッドはない）としてデザインされてます。一般的なスレッドフレームワークになるようには構成されてません。

AsyncTaskは数秒程度の処理に適してます。長い間スレッド処理させたい場合には、**Exesutor,ThreadPoolExecuter,FutureTask**など、java.util.concurrentパッケージで提供されるAPIsを使ってね。

非同期のタスクは、バックグラウンドスレッドで実行されてUIスレッドに渡される結果によって定義されます？。つまり、以下の引数のタイプと、4つのステップで定義します。

- **AsyncTaskの引数**
  - Param
  - Progress
  - Result
 
- **4つのステップ**
  - onPreExecute
  - doInBackground
  - onProgressUpdate
  - onPostExecut

#使い方

AsyncTaskはサブクラス化して使い、少なくとも１つ以上のメソッドをオーバーライドします(**doInBackground(Param...)**)、またほとんどの場合、2つ目もオーバーライドします(**onPostExecute(Result)**)。

以下はサブクラス化の例

```java
 private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
     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));
             // Escape early if cancel() is called
             if (isCancelled()) break;
         }
         return totalSize;
     }

     protected void onProgressUpdate(Integer... progress) {
         setProgressPercent(progress[0]);
     }

     protected void onPostExecute(Long result) {
         showDialog("Downloaded " + result + " bytes");
     }
 }
```
一度生成すれば、タスクの実行は実に簡単！

```
 new DownloadFilesTask().execute(url1, url2, url3);
```
---
###AsyncTaskの引数<総称型タイプ>

**AsyncTaskM\<Param,Progress,Result>**

1.**Param**<br>実行時にタスクに渡すパラメータタイプ
2.**Progress**<br>バックグランド処理の間に表示させる進捗ユニットのタイプ
3.**Result**<br>バックグラウンド処理の結果のタイプ

全てのタイプを使う必要はなく、voidで済ますこともできます。
こんな感じで

     private class MyTask extends AsyncTask<Void,Void,Void>

###4つのステップ
非同期タスクが実行されるとき、タスクは4つのステップを踏みます。

1. **onPreExecute()**<br>タスクが処理される前にUIスレッドに呼び出す準備的なメソッド。例えば、Execute()の実行時に、プログレスバーを表示させたい時などに、onPreExecute()でプログレスバーの表示を準備させたりするって感じ。
2. <strong><font color="#05f">doInBackground(Params...)</font></strong>:オーバーライド必須<br>onPreExecute()処理後、すぐにバックグラウンドスレッドで呼び出されます。バックグラウンド処理に時間を要してもOKだよっていう処理に使うステップです。このステップで、非同期タスクのパラメータが引き渡されます。処理結果は必ずこのステップで返され、最後のステップに結果を渡します。このステップは、プログレスのユニットを表示するpublishProgress(Progress)にも使え、そのケースではonProgressUpdate(Progress...)のステップでUIスレッドに表示されます。
3. **onProgressUpdate(Progress...)**<br>publishProgress(Progress...)の実行後にUIスレッドに呼び出されます。実行のタイミングは定義されてません。このメソッドは色んなプログレスフォームを表示するのに使われます。プログレスのフォームは、バックグラウンド処理の間、UIに表示されます。例えばアニメーションプログレスバーとか、テキストフィールドでのログ表示とか。
4. **onPostExecute(Result)**<br>バックグラウンド処理の終了後にUIスレッドに呼ばれます。バックグラウンド処理の結果はこのステップにパラメーターとして返されます。

---
###タスクキャンセル
タスクキャンセルはcancel(boolea)で実行してね。cancel()を実行すると（成功すると）、後でisCancelled()が呼ばれてtrueを返します。通常ならdoInBackground(java.lang.Object[])を実行するとonPostExecute(java.lang.Object)が実行されますが、cannel()を実行すると、onPostExecute()の代わりにonCannelled(java.lang.Object)が実行されるって感じの流れ。タスクがちゃんとキャンセルされてるか確認するために、doInBackground(java.lang.Object[])からisCancelled()の戻り値(キャンセルされてればtrue！)が発行されるので、可能な限り素早くチェック！

---
###スレッドルール
スレッドを適切に使うために、幾つかのルールがあります。

- AsyncTaskはUIスレッド側で呼び出します。AndroidのバージョンがJELLY_BEAN以降は自動的にそうなります。
- **タスクインスタンスはUIスレッド側で作成**
- **UI側でexecute(Params...)を実行**
- 直接、onPreExesute(),onPostExecute(Result),doInBackground(Prams...),onProgressUpdate(Progress...)を呼び出さないでね。Androidシステムに任せてください！
- タスクは１回だけ実行できます。もし２回目が実行されると、例外を投げられます。

---
###メモリの確認
AsyncTaskは、明示的に同期するケースを除き、以下を確認するために、全てのコールバック関数の呼び出しが同期されることを保証します。

- onPreExecute()のメモリへの影響、execute(Params...)の呼び出し前に実行されたメソッド等(AsyncTaskオブジェクトの構築)のメモリへの影響は、doInBackground(Params...)に表示される
- doInBackground(Params...)
メモリへの影響は、onPostExecute(Result)に表示される
- publishProgress(Progres...)を呼び出す前のdoInBackgrund(Params...)のメモリへの影響は、対応するonProgressUpdate(Progress..)で表示される。ただし、doInBackground(Params...)は引き続き実行されるため、doInBackground(Params...)の更新が、進行中のonProgressUpdata(Progress...)
 の呼び出しに干渉しないように注意が必要。
- cancel(boolean)のメモリへの影響は、calcek(boolean)に先行して呼び出されるisCancelled()（実行結果でtrueを返す）の呼び出しの後とか、onCancelled()の呼び出し中や実行後に表示されます。

#AsyncTaskの生い立ち
当初、AsyncTasksはバックグラウンドのシングルスレッドで順次処理されてました。AndroidのバージョンがBuild.VERSION_CODES.DONUTからは、並行処理するマルチタスクを扱えるように、スレッドプールに変化してきた。AndroidバージョンがBuild.VERSION_CODES.HONEYCOMBからは、並行処理が原因で発生するアプリケーションエラーを避けるため、タスクはシングルスレッドで実行するようになっています。

<font color="#05a">もし、並行処理をするのなら</font>、<font color="#05f">**THREAD_POOL_EXECUTOR**とともに**executeOnExecutor**(java.util.concurrent.Executor,java.lang.Object[])</font>を実行しよう！。

#概要

#####■　Nested classes
<table>
<tr><td>enum</td></tr>
<tr><td><font color="#05f">AsiyncTask.Status</td></tr>
<tr><td>タスクの現在のステータスを示す</td></tr>
</table>

#####■　Fields
public static final Executor

<table>
<tr><td><font color="#05f">SERIAL_EXECUTOR</td></tr>
<tr><td>タスクを一つずつ順次処理させるExecutor</td></tr>
<tr><td><font color="#05f">HREAD_POOL_EXECUTOR</td></tr>
<tr><td>並列処理時に使われるExecutor</td></tr>
</table>

#####■　Public constructors
<table>
<tr><td><font color="#05f">AsyncTask<></td></tr>
<tr><td>新しい同期タスクを生成</td></tr>
</table>

#####■　Public methods

<table>
<tr>
  <td>final boolean</td>
  <td><font color="#05f">cancel(boolean mayInterruptIfRunning)</font><br>タスクをキャンセル処理<
  /td>
</tr>

<tr>
  <td>final <font color="#05f">AsyncTask</font><Param,Progress,Result></td>
  <td><font color="#05f">execute(Params... param)</font><br>パラメーターを指定してタスクを処理</td>
</tr>

<tr>
  <td>static void</td>
  <td><font color="#05f">execute(Runnable runnable)</font><br>シンプルなRunnableオブジェクトを、手軽に処理するためのexecute(java.lang.Object)</td>
</tr>

<tr>
  <td>final <font color="#05f">AsyncTask</font><Param,Progress,Result></td>
  <td><font color="#05f">executeOnExecutor(Executor</font> exec,Params... param><br>パラメータを指定してタスクを処理</td>
</tr>

<tr>
  <td>final Result</td>
  <td><font color="#05f">get</font>(long timeout,<font color="#05f">TimeUnit</font> unit)<br>
      処理を完遂するのに時間がかかる場合に待機して結果を取得する</td>
</tr>

<tr>
  <td>final Result</td>
  <td><font color="#05f">get</font>()<br>
      処理を完遂するのに必要なら待機して結果を取得する</td>
</tr>

<tr>
  <td>final <font color="#05f">AsyncTask.Status</td>
  <td><font color="#05f">getStatus</font><br>タスクの現在の状態を返す</td>
</tr>

<tr>
  <td>final boolean</td>
  <td><font color="#05f">isCancelled</font>()<br>
      タスクが正常に終了する前にキャンセルが成功したらtrueを返す</td>
</tr>
</table>
<font color="#0f5"></font>

#####Protected methods

<table>
<tr>
  <td>abstract Result</td>
  <td><font color="#05f">doInBackground</font>(Params... params)<br>
      バックグラウンドスレッドで処理を実行するのにオバーライドするメソッド</td>
</tr>

<tr>
  <td>void</td>
  <td><font color="#05f">onCancelled</font>()<br>
      できれば<font color="#05f">onCancelled(java.lang.Object)</font>をオーバーライドしよう！</td>
</tr>

<tr>
  <td>void</td>
  <td><font color="#05f">onCancelled</font>(Result result)<br>
     <font color="#05f">cancel(boolean)</font>を実行し、<font color="#05f">doInBackground(java.lang.Object[])</font>が終了した後で、UIスレッドで稼働する</td>
</tr>

<tr>
  <td>void</td>
  <td><font color="#05f">onPostExecute</font>(Result result)<br>
   <font color="#05f">doInBackground(Params...)</font>の後でUIスレッドで稼働する</td>
</tr>

<tr>
  <td>void</td>
  <td><font color="#05f">onPreExecute</font>()<br>
    <font color="#05f">doInBackground(Params...)</font>の前にUIスレッドで稼働する</td>
</tr>

<tr>
  <td>void</td>
  <td><font color="#05f">onProgressUpdate</font>(Progress... values)<br>
    <font color="#05f">publishProgress(Progress...)</font>が呼び出された後に、UIスレッドで稼働する</td>
</tr>

<tr>
  <td>final void</td>
  <td><font color="#05f">publishProgress(Progress... values)</font><br>
    このメソッドは、バックグラウンドで処理中にUIスレッドでアップデートするために<font color="#05f">doInBackground(Params...)</font>から呼び出される</td>
</tr>

</table>

#####継承されたメソッド
<table><td>
<font color="#05f">From class java.lang.Object</font>
</td></table>

#AsyncTaskまとめ的な
AsyncTaskはサブクラス化して使う
AsyncTask\<Params,Progress,Result>

- Params<br>doInBackground()で使う引数型を指定
- Progress<br>実行中の情報をユーザーに表示するメソッドの型<br>publishProgress(),onProgressUpdate()で使う引数型を指定
- Result<br>結果表示のメソッド<br>onPostExecute()で使う引数型を指定

AsyncTaskが引数不要なら、AsyncTask\<void,void,void>

###主なメソッド

- execute()
- publishProgress()

- @Overrideメソッド（軌道はAndroidシステムに任せてね）
  - onPreExecute()
  - doInBackground()
  - onProgressUpdate()
  - onPostExecute()

#####・execute(Params... params)
UIスレッド側で実行するメソッド。オーバーライドメソッドのdoInBackground()に引数を渡してdoInBackgroundを実行するよ！。

引数の型はAsyncTaskの引数型を参照してね
引数はdoInBackground()を実行するに使います。

#####・onPreExecute
Execute()実行前にしたい処理があればここで！

#####・doInBackground()
<font color="#f55">オーバーライド必須のメソッド！</font>
execute()から引数を受け取って、バックグラウンドでタスク処理。
doInBackground()処理後にonPostExecute()を呼び、doInBackground()処理の結果をonPostExecute()に渡します。もしcancel()を使うとonPostExecute()の代わりに、onCannelled()が呼ばれるよ。
doInBackground()はタスク処理専用。UIスレッドの更新は他のメソッドで！

#####・onPostExecute()
doInBackground()内で使って、doInBackground()の結果を、UIスレッド側で表示するメソッド。AsyncTaskの引数Resultを使うのです。

#####・publishProgress()
進捗表示を使いたいときにどうぞ！
doInBackground()でpublishProgress()を実行すると、Androidシステムは、UIスレッドでonProgressUpdate()を実行します。

#####・onProgressUpdate()
doInBackground()でpublishProgress()を実行すると、Androidシステムは、UIスレッドでonProgressUpdate()を実行
引数はAsyncTaskの引数を参照

---
###サンプルコード:execute()とdoInBackground()

- MainActivity.java<br>AsyncTask<>をサブクラス化し、execute()を実行する
- AsyncTask<>クラスを拡張して、MyAsyncTaskクラスを生成<br>doInBackground()は、MainActivity.javaのexecute()によって処理を実行する(todo)。doInBackground()はexecute()から引数を受け取るって処理に使うよ。

```java
public class MainActivity extends AppCompatActivity {

    public static TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // タスクインスタンスを生成。execute()で引数をonInBackground()に渡す
        // new MyAsyncTask().execute();  でもOK
        MyAsyncTask myAsyncTask = new MyAsyncTask();
        myAsyncTask.execute();

    }
}

class MyAsyncTask extends AsyncTask<Void,Void,Void> {
    @Override
    protected Void doInBackground(Void... aVoid) {
        // todo
        Log.d("msg","In MyAsyncTask");
        return null;
    }
}
```

###サンプルコード:幾つかメソッドを入れてみる

3秒毎にtextViewの表示を変えるコード

- **MyActivity.onCreate()**<br>myAsncTask.<font color="#05f">excute</font>("In doInBackground")
- **class MyAsyncTask**<br>
  - <font color="#05f">onPreExecute()</font><br>textView.setText("onPreExecute")
  - <font color="#05f">doInBackground()</font><br>sleep(1000*3)　->　<font color ="#05f">publishProgress</font>(string[0])　->　sleep(1000*3)　->　<font color="#05f">return "End doInBackground"</font>
  - <font color="#05f">onProgressUpdate()</font><br>textView.setText(string[0])
  - <font color="#05f">onPostExecute()</font><br>textView.setText(s)

```java
public class MainActivity extends AppCompatActivity {

    TextView textView;

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

        textView = findViewById(R.id.textView);

        // タスクインスタンスを生成。execute()で引数をonInBackground()に渡す
        // new MyAsyncTask<>.execute();  でもOK
        MyAsyncTask myAsyncTask = new MyAsyncTask();
        // doInBackground()に文字列("In doInBackground")を渡して
        // onPreExecute()の処理後に、doInBackground()を実行
        myAsyncTask.execute("In doInBackground");

    }

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

        // execute("In doInBackground")処理前に実行。UIスレッドのtextViewに表示
        @Override
        protected void onPreExecute(){
            textView.setText("onPreExecute");
        }

        // execute()から文字列"In doInBackground"を受け取る
        @Override
        protected String doInBackground(String... string) {

            // 3秒待機
            try {
                sleep(1000*3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            // doInBackground処理中に、textViewを表示させるonPublishUpdate()を呼ぶ
            publishProgress(string[0]);

            // 3秒待機
            try {
                sleep(1000*3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            // onPostExecute()に文字列"End doInBackground"を渡す
            return "End doInBackground";
        }

        // doInBackground内のpublishProgress()から文字列を受け取り、UIスレッドのtextViewに表示
        protected void onProgressUpdate(String... string){
            textView.setText(string[0]);
        }

        // doInBackground()からreturn値("End doInBackground")を受け取り、UIスレッドのtextViewに表示
        @Override
        protected void onPostExecute(String s){
            textView.setText(s);
        }
    }
}
```

#ActivityからAsyncTaskにパラメータを渡す
## 複数のパラメータを一つ一つ渡す

```java:MainActivity
...
new MyAsyncTask().execute("param1","param2");
```

```java:MyAsyncTask
...
@Override
protected String doInBackground(String... string){
   String param1 = string[0];
   String param2 = string[1];
return null
}
```

## 複数のパラメータを配列にして渡す
```java:MainActivity
Map<String,String> map = new HashMap<String,String>();
   map.put("param1","data1");
   map.put("param2","data2");
   map.put("param3","data3");

new MyAsyncTask().execute(map);
```

```java:MyAsyncTask
public class MyAsyncTask extends AsyncTask<Map<String,String>,Void,Map<String,String>>{

   @Override
   protected Map<String,String> doInBackground(Map<String,String>... map){
      Map<String,String> mp = map[0];
      // mpをJsonにするのなら
      // JSONObject jsonMap = new JSONObject(mp);
      return mp;
   }

   @Override
   protected void onPostExecute(Map<String,String> mp){
      super.onPostExecute(mp);
      String val1 = mp.get("param1"); // val1にdata1が格納された
      String val2 = mp.get("param1"); // val2にdata2が格納された
      String val3 = mp.get("param3"); // val3にdata3が格納された
   }
}
```

ちょっと時間かかったね。いつも通り亀の歩み。