LoginSignup
12
10

More than 5 years have passed since last update.

AsyncTaskに安全にcallbackを持たせたい

Last updated at Posted at 2017-10-16

Android開発に関する初投稿です。
Android初心者なので、アドバイス・指摘大歓迎です。

背景

重い処理をUIスレッド外で行いたいときに使うAsyncTaskはコールバックで処理を受け取る形式になっていません。
しかし、迂闊にコールバックを受け取れるようにするとメモリリークの危険があります。

AsyncTaskで安全にcallbackを実行する方法

ActivityをweakReferenceで保持し、callBackをActivityに持たせてonPostExecute()内で実行します。
Activityが弱参照になっているので、Activityがdestroyされた時にActivityが適切にGCされます。

class AsyncTaskSample<T>(activity: T) : AsyncTask<String, Unit, String>() where T : AppCompatActivity, T : AsyncTaskSample.Listener {
    val weakActivity = WeakReference(activity)
    interface Listener {
        fun onCompleteAsyncTask(result: Uri?): Unit
    }

    override fun doInBackground(vararg params: String?): String? {
        return params[0]
    }

    override fun onPostExecute(result: String?) {
        super.onPostExecute(result)
        weakActivity?.onCompleteAsyncTask(result)
    }
}

ダメな例: callBackをコンストラクタに渡す

doInBackgroundの最中にActivityがdestroyされてもGCが働かず、メモリー上にActivityが残り続けます。その為、最悪の場合メモリーリークを起こします。

class AsyncTaskSample(callback: (String?) -> Unit) : AsyncTask<String, Unit, String>() {
    override fun doInBackground(vararg params: String?): String? {
    }

    override fun onPostExecute(result: String?) {
        super.onPostExecute(result)
        callback(result)
    }
}

ダメな例: callBackをWeakReferenceで保持する

callBackに渡したラムダが予期せぬタイミングでGCされ、発火しなくなることがあります。

class AsyncTaskSample(callback: (String?) -> Unit) : AsyncTask<String, Unit, String>() {
    val weakCallback = WeakReference(callback)
    override fun doInBackground(vararg params: String?): String? {
        return params[0]
    }

    override fun onPostExecute(result: String?) {
        super.onPostExecute(result)
        weakCallback.get()?.invoke(result)
    }
}

12
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
10