2016-05-04 6 views
6

私はAsyncTaskをKotlinに実装しています。onPostExecute()メソッドで実行されるコールバックにはWeakReferenceが必要です。​​を呼び出す前にリスナー参照を設定しましたが、が呼び出されると、WeakReferenceの値はnullになります。WeakReferenceがKotlinで機能しない

class PhotoRotationTask(uri: Uri, filePath: String, resolver: ContentResolver) : AsyncTask<Int, Int, Int>() { 
    private var weakRef : WeakReference<OnBitmapProcessedListener>? = null 

    var sourceUri : Uri 
    var resolver : ContentResolver 
    var destPath: String 

    init { 
     this.sourceUri = uri 
     this.resolver = resolver 
     this.destPath = filePath 
    } 

    fun setOnBitmapProcessedListener(listener: OnBitmapProcessedListener){ 
     weakRef = WeakReference(listener) 
     Log.d("RotationTask", "set listener ${weakRef?.get() != null}") //This Log proves that weakRef is initialized before onPostExecute() 
    } 

    override fun doInBackground(vararg params: Int?): Int? { 
     //Bitmap processing, weakRef is never called in this function 
    } 

    override fun onPostExecute(result: Int?) { 
     Log.d("RotationTask", "result: $result") //This log proves that onPostExecute() is called eventually 
     weakRef!!.get()?.onBitmapProcessed() //This implies that weakRef is not null, because app never crashes, but onBitmapProcessed is not called, so the reference is gone. 
    } 

} 

listener変数は、したがって、それは私の活動への参照を保持している、私の活動のUIを変更します。 AsyncTaskの起動後も、アクティビティは決して再作成されず、私の電話は静止していたり​​、回転したり触れたりすることはありません。 WeakReferenceはどのようにクリアされていますか?

+0

ローカル変数を 'listener'として渡しますか?他の場所に保存されていますか?アクティビティのプロパティで? – hotkey

+0

はい私はローカル変数を渡しますが、どこにも格納しません – gesuwall

答えて

5

問題はWeakReferenceと、渡すローカル変数の両方にlistenerと表示されます。

WeakReferenceknown not to keep an object from being garbage collectedあり、それには他の到達可能強い参照がない場合は、ローカル変数が終了を通してそれを参照する方法一度いつでも再利用することができます。弱い参照がnullになるので、これはあなたのケースでまさに起こります。それは活動を使用するように

溶液がどこ呼び出し元のコードにlistenerとして渡されるオブジェクトへ強い参照を格納することである(活性自体は、プロパティに格納することができる、そのようlistenerの生涯は活動のそれと一致するだろう)。例えば

、あなたはそのプロパティに作成listener保管し、その後、アクティビティコードで

lateinit var currentListener: OnBitmapProcessedListener 

プロパティを宣言:

val task = PhotoRotationTask(uri, filePath, resolver) 

task.setOnBitmapProcessedListener(object : OnBitmapProcessedListener { 
     // here goes the implementation 
    }.apply { currentListener = this } // note this line 
) 

複数のタスクとリスナーが可能な場合には、世話をしますすべてのリスナーを格納する

+0

格納された何かがStrongReferenceである必要があるときにweakReferenceを持つ目的は何ですか?これはオブジェクトがガベージコレクションから防ぐことはできませんか? (すなわち、weakReferenceの目的は、必要なときにそれに含まれるオブジェクトが解放されるようにするためです)。 – Elye

0

OnBitmapProcessedListenerを強く参照して、GCがWeakReferenceをクリアしないようにする必要があります。

関連する問題