AsyncTaskによるスレッドの利用Androidでは普通にThreadを使うこともできるが、AsyncTaskを使うこともできる。AsyncTaskはThreadやRunnableを意識せずにメインスレッドとは別のスレッドで処理を行うことができるので、ある程度まとまった処理を行う場合には便利なクラスだ。 ただし、AsyncTaskを使ったとしてもメインスレッドとは別のスレッド、すなわちdoInBackgroundメソッドの中から直接UIを更新することはできない。この辺りはThreadやRunnableによる方法と変わらない。 スレッドとUIの基本AsyncTaskを継承したサブクラスを用意するAsyncTaskにはいくつか決まりごとがあるのでそれに沿って利用する必要がある。まずはAsyncTaskをextendsして処理のためのサブクラスを用意する。 class ButtonTask extends AsyncTask<Long, Void, Date> { @Override protected Date doInBackground(Long... params) { // TODO Auto-generated method stub Log.d("onClick", "in Thread thread id = " + Thread.currentThread().getId()); try { Thread.sleep(params[0] * 1000); // n秒待つ } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } return new Date(); } @Override protected void onPostExecute(Date result) { // TODO Auto-generated method stub super.onPostExecute(result); Log.d("onClick", "date = " + result); Log.d("onClick", "runOnUiThread thread id = " + Thread.currentThread().getId()); Toast.makeText(getApplicationContext(), "Click button1", Toast.LENGTH_SHORT).show(); } @Override protected void onPreExecute() { // TODO Auto-generated method stub super.onPreExecute(); Log.d("onClick", "before Thread thread id = " + Thread.currentThread().getId()); } } AsyncTaskのサブクラスを記述するときのGenerics(AsyncTaskの後ろの<T, T, T>)は最初から順にdoInBackground、onProgressUpdate、及びonPostExecuteの各メソッドに渡す可変長引数である。これらに指定できるのはクラスのみでint等のプリミティブは指定できない。これらのメソッドに引数を渡す必要がなければVoidを指定すれば良い。 AsyncTaskのメソッドAsyncTaskの肝であるdoInBackgroundメソッドはメインスレッドとは別のスレッドで実行される。例えば、doInBackgroundメソッドだけにString型の引数を渡したい場合、extendsするのはAsyncTask<String, Void, Void>となる。AsyncTaskのサブクラスを記述するとき、少なくともこのdoInBackgroundメソッドだけはオーバライドしなければならない。 onPreExecuteメソッドはdoInBackgroundメソッドの実行前にメインスレッドで実行されるメソッドである。Androidのクラスの中にはメインスレッドでしか利用できないクラスもあるので、そういったものはこのonPreExecuteメソッドの中で利用する等すれば良いだろう。 onPostExecuteメソッドはdoInBackgroundメソッドの実行後にメインスレッドで実行されるメソッドである。指定すればdoInBackgroundメソッドの戻り値をこのメソッドの引数として受け取ることができ、別スレッドで実行した処理の結果を受けてUIを更新する等の処理を行うと良いだろう。 onProgressUpdateメソッドはpublishProgressメソッドの呼び出しをトリガーにメインスレッドで実行されるメソッドである。doInBackgroundで行っている処理の進行状況(doInBackgroundメソッド内でpublishProgressメソッドを呼び出す)をプログレスバーで表示するとき等に利用できる。 AsyncTaskを実行する用意したAsyncTaskのサブクラスを実行するには、インスタンス化してexecuteメソッドを呼ぶだけである。doInBackgroundメソッドに渡す引数を指定した場合は、このexecuteメソッドに渡すことで生成されるスレッドにそれが伝播する。 button1 = (Button)findViewById(R.id.button1); button1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new ButtonTask().execute(new Long(5)); } }); 上記の例ではexecuteメソッドの引数として5を渡しているので、doInBackgroundメソッド内ではそれを基に5秒のwaitをしている。AsyncTaskを実行する上で大事なのは、このexecuteメソッドをメインスレッドから呼び出すこと、用意したAsyncTaskのサブクラスの各メソッドを直接呼び出さないこと、及び同じタスクを2度実行しないことである。 (2012/02/14)
Copyright(C) 2004-2013 モバイル開発系(K) All rights reserved.
[Home]
|