「ListActivityを継承したActivityクラスで、AsyncTaskで重い処理を行った後リストを更新するには」の記事を書きましたが、Twitterでブログを書いたとつぶやいたところ、フォロワーより
- AsyncTaskを継承したクラスのコンストラクタの引数にContextとListActivityの両方のthisを入れるのはなぜ?
- ListActivityはクリックリスナーを持っているのに、AsyncTaskを継承したクラスのコンストラクタの引数にわざわざ、OnItemLongClickListenerのthisを入れるのはなぜ?
というツッコミをいただきました。
まず、2に関してですが、自分が今開発しているアプリでは、リストの項目をタップして音声ファイルを再生して、項目をロングタップして、メニューを開いて、なんらかの処理を行うため、ActivityがOnItemLongClickListenerインターフェースを実装する必要があります。そのため、AsyncTaskを継承したクラスのコンストラクタの引数にOnItemLongClickListenerのthisを入れました。しかし、よくよく考えたら、継承するクラスや実装するインターフェースのthisを引数にする必要もありませんね。コンストラクタの引数には、ListActivityクラスを継承して、OnItemLongClickListenerインターフェースを実装したクラスのthisを渡せばよさそうです。以前は、時間がかかる処理をHandlerを使って行っていたのですが、最近、AsyncTaskを使うようになりました。しかし、AsyncTask側からUIにアクセスするのにContext型の変数しか使えないんではと思い込んでいて、ListActivityクラスを継承して、OnItemLongClickListenerインターフェースを実装したクラスの型の変数を使うのには考えが及びませんでした。(と言っても、先のブログ記事では、ListActivityやOnItemLongClickListener型の変数を使っていましたが (^^); )
そこで、前回書いたブログの内容を書き換えます。
ListActivityを継承して、OnItemLongClickListenerインターフェースを実装したクラスをFooActivityとします。
AsyncTaskを継承したクラスHogeAsyncTaskで、コンストラクタを
public HogeAsyncTask(FooActivity activity) { mActivity = activity; helper = new CreateProductHelper(mContext); dataDao = new DataDao(helper); }
と定義して、FooAcitvityでは、
new HogeAsyncTask(FooActivity.this).execute();
で、AsyncTaskの処理を呼びます。そして、リスト更新は、AsyncTaskを継承したクラスのonPostExecute内で、
dataList = dataDao.select(); if (dataList != null) { mAdapter = new CustomAdapter(mActivity, dataList); mActivity.setListAdapter(mAdapter); ListView lv = mActivity.getListView(); lv.setOnItemLongClickListener(mActivity); }
で行います。前回の記事のmContextをmActivityに、mListActivityをmActivityに、mOnItemLongClickListenerをmActivityに書き換えています。これはContexがActivityのスーパークラス、AcitivityがListActivityのスーパークラスであり、mActivity型の変数のクラスがOnItemLongClickListenerを実装しているため可能です。なお、ここで書いたコードは断片コードですが、CreateProductHelperはSQLiteOpenHelperを継承したクラス、CustomAdapterはArrayAdapterを継承したクラスです。