Android/非同期処理/asynctask/基本
提供: 初心者エンジニアの簡易メモ
バックエンドで同期処理を行う。 例えば、ファイルを連続ダウンロードさせて、進捗ダイアログを出すときなどに使う。
サンプル
- AsyncTestActivity.java
import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class AsyncTestActivity extends Activity implements OnClickListener { final String TAG = "AsyncTestActivity"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); ((Button)findViewById(R.id.button1)) .setOnClickListener(this); } @Override public void onClick(View v) { if (v.getId() == R.id.button1){ MyAsyncTask sync = new MyAsyncTask(this); sync.setActivity(this); sync.setHoge("test"); sync.execute("http://yahoo.co.jp", "http://google.co.jp", "http://www.msn.com"); } } }
- MyAsyncTask.java
import android.app.Activity; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnCancelListener; import android.os.AsyncTask; import android.util.Log; public class MyAsyncTask extends AsyncTask<String, Integer, Long> implements OnCancelListener { private final String TAG = "MyAsyncTask"; private ProgressDialog mDialog; private Context mContext; private Activity mActivity; private String hoge; public MyAsyncTask(Context context) { this.mContext = context; } public void setActivity(Activity activity) { mActivity = activity; } public void setHoge(String hoge) { this.hoge = hoge; } @Override protected void onPreExecute() { Log.d(TAG, "onPreExecute"); if (mActivity == null) return; mDialog = new ProgressDialog(mContext); mDialog.setTitle("Please wait"); mDialog.setMessage("Loading data..."); mDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); mDialog.setCancelable(true); mDialog.setOnCancelListener(this); mDialog.setMax(100); mDialog.setProgress(0); mDialog.show(); } @Override protected Long doInBackground(String... urls) { Log.d(TAG, "hoge" + this.hoge); int count = urls.length; try { for (int i = 0; i < count; i++) { Log.d(TAG, "url=" + urls[i]); if (isCancelled()) break; Thread.sleep(1000); publishProgress((i+1) * 100 / count); } } catch (InterruptedException e) { Log.d(TAG, "InterruptedException in doInBackground"); } return 123L; } @Override protected void onProgressUpdate(Integer... values) { Log.d(TAG, "onProgressUpdate=" + values[0]); if (mDialog == null) return; mDialog.setProgress(values[0]); } @Override protected void onCancelled() { Log.d(TAG, "onCancelled"); if (mDialog == null) return; mDialog.dismiss(); } @Override protected void onPostExecute(Long result) { Log.d(TAG, "onPostExecute=" + result); if (mDialog == null) return; mDialog.dismiss(); } public void onCancel(DialogInterface dialog) { Log.d(TAG, "Dialog onCancell... calling cancel(true)"); this.cancel(true); } }
- res/layout/main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" > <Button android:id="@+id/button1" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="text"> </Button> </LinearLayout>
以下エラー対応方法
android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
new MyAsyncTask(this);のところをactivity由来のcontextであるthisで渡せばok。
もしくはProgressDialogのところにだけactivityのインスタンスを入れる。