AsyncTaskによるメモリ漏洩

2357 ワード

原文出典:https://www.jianshu.com/p/ca65b59a6bf3
AsyncTaskがAndroidに導入されると、「無憂スレッド」というラベルが貼られます.UIスレッドと対話するサブスレッドを容易にすることを目的としている.AsyncTaskの本質は、5つのコアスレッドからなり、最も大きなキュー数が128のスレッドプールである.我々は使用中、通常doInBackground(Params...)メソッドを書き換え、比較的時間のかかる操作はここに置くことができます.この方法はサブスレッドではUIを直接操作することはできない.この方法はバックグラウンドスレッドで実行され、タスクの主な作業を完了するのに通常長い時間がかかります.実行中にonPostExecute(Result)メソッドを呼び出すことができ、HandlerがUIを処理する方法に相当し、doInBackgroundで得られた結果を用いて操作UIを処理することができる.このメソッドはメインスレッドで実行され、タスク実行の結果はこのメソッドのパラメータとして返されます.
AsyncTaskの使い方は簡単ですが、次のコードを見てみましょう.このように書くのは正しいですか.
private TextView mTextview;

new AsyncTask<...> {

@Override

protected void onPostExecute(Objecto) {

mTextview.setText("text");

}

}.execute();

一見問題ないようですが、このコードはメモリの漏洩を引き起こし、スレッドが現在のActivityのライフサイクルを超えてrunに残る可能性があります.この時点でスレッドは制御されていないからです.Activityライフサイクルは終了しており、システムによって回収される必要がありますが、AsyncTaskはTextViewの参照を持っており、メモリの漏洩を招いています.
では、上のコードを変更します.
private TextView mTextview;

new AsyncTask<...> {

@Override

protected void onPostExecute(Objecto) {

//mTextview.setText("text");

}

}.execute();

まあ、直すのがおっくうで、私は直接注釈して、UIの操作をしないで、このようにいつも問題がないでしょう.本当ですか.よく見ると、ここは内部クラスで、Java内部クラスの特徴のため、AsyncTask内部クラスは外部クラスの暗黙的な参照を持っています.私がAsyncTaskに外部からの参照を持っていないことをコードから見ても、Activityに書くとcontextに強い参照があります.これにより、スレッドがActivityライフサイクルを超えると、Activityは回収できず、メモリが漏洩します.
では、どのように解決するかには、2つの方法があります.1つ目は、Activityのライフサイクルが終わる前に、cancel AsyncTaskに行きます.Activityはすべて破棄されるので、この時にスレッドを走って、UIを描くのは明らかに意味がありません.第二に,必ず内部クラスの形式で書かなければならない場合,contextに対してWeakReferenceを用い,使用前に空か否かを判断する.
作者:ユンスター
リンク:https://www.jianshu.com/p/ca65b59a6bf3
出典:簡書
簡書の著作権は著者の所有であり、いかなる形式の転載も著者に連絡して授権を得て出典を明記してください.