Issue
I have created a UDP communication application and it is working very well (so far). To receive UDP packets I am using an AsyncTask
extension class.
For the sake of clarity (and brevity) I have divided the code into separate kotlin files.
MainActivity.kt handles the UI stuff like button press and creating objects
LongTask.kt defines a LongTask
class that extends the AsyncTask
(UDP receiver code)
I create a instance of LongTask
on a button press event using the following
task = object : LongTask("$idx"){
override fun onProgressUpdate(vararg values: String?) {
super.onProgressUpdate(*values)
Log.d(TAG, "On UI thread")
}
}
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "")
However, the above lines of code are highlighted in yellow and keep warning of a possible memory leak.
How to write a leak proof code to get past this warning?
Solution
task = object : LongTask("$idx"){
override fun onProgressUpdate(vararg values: String?) {
super.onProgressUpdate(*values)
Log.d(TAG, "On UI thread")
}
}
This line will create an anonymous inner class which extends from LongTask
class. An inner class have an implicit reference to their outer class, in this case MainActivity
class.
If the activity is finished before the asynctask completed, then the activity will be leaked or not collected by GC because it's still referred by the asynctask.
Solution: To avoid that we should use WeakReference
API. In addition, LongTask
is a separate class so we need to define an interface to pass data back to the activity.
First, declare an interface
OnProgressUpdateListener.kt
interface OnProgressUpdateListener {
fun onProgressUpdate(vararg values: String?)
}
Second, modify the asynctask class. Just focus on OnProgressUpdateListener
part because I don't know what exactly your class look like.
LongTask.kt
class LongTask(val idx: String, listener: OnProgressUpdateListener) : AsyncTask<String, String, Unit>() {
private val mListener: WeakReference<OnProgressUpdateListener>? = WeakReference(listener)
override fun doInBackground(vararg params: String?) {
}
override fun onProgressUpdate(vararg values: String?) {
mListener?.get()?.onProgressUpdate(*values)
}
}
Finally, let the activity implements OnProgressUpdateListener
.
MainActivity.kt
class MainActivity : AppCompatActivity(), OnProgressUpdateListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
task = LongTask("$idx", this)
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "")
}
override fun onProgressUpdate(vararg values: String?) {
// Update your progress on UI thread here
Log.d(TAG, "On UI thread")
}
}
Answered By - Son Truong
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.