Reputation:
This AsyncTask class should be static or leaks might occur
Why my AsyncTask don't work?
Call: PlacesTask(this).execute(...)
Code:
private class PlacesTask internal constructor(activity: MainActivity) : AsyncTask<String, Int, String>() {
var data: String? = null
private val mRef: WeakReference<MainActivity> = WeakReference(activity)
override fun doInBackground(vararg url: String): String? {
try {
data = MainActivity().downloadUrl(url[0])
} catch (e: Exception) {
Log.d("Background Task", e.toString())
}
return data
}
override fun onPostExecute(result: String) {
val asyncTaskLeak = mRef.get()
if (asyncTaskLeak != null) SetPlaceTask().execute(result)
}
}
private class SetPlaceTask : AsyncTask<String, Int, List<HashMap<String, String>>>() {
var places: List<HashMap<String, String>>? = null
override fun doInBackground(vararg jsonData: String): List<HashMap<String, String>>? {
try {
places = PlaceJSONParser().parse(JSONObject(jsonData[0]))
} catch (e: Exception) {
Log.d("Exception", e.toString())
}
return places
}
override fun onPostExecute(list: List<HashMap<String, String>>) {
...
}
}
@Throws(IOException::class)
private fun downloadUrl(strUrl: String): String {
var data = ""
var iStream: InputStream? = null
var urlConnection: HttpURLConnection? = null
try {
urlConnection = URL(strUrl).openConnection() as HttpURLConnection
urlConnection.connect()
iStream = urlConnection.inputStream
val br = BufferedReader(InputStreamReader(iStream!!))
val sb = StringBuilder()
var line: String? = null
while ({line = br.readLine(); line }() != null) sb.append(line)
data = sb.toString()
br.close()
} catch (e: Exception) {
Log.d("downloading url", e.toString())
} finally {
if (iStream != null) iStream.close()
if (urlConnection != null) urlConnection.disconnect()
}
return data
}
Error: java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter result
Please help. What am I missing?
Upvotes: 0
Views: 898
Reputation:
I understood.
AsyncTask
should be static
AsyncTask
move to -> companion object {}
.AsyncTask
without leak (Good exp.)Example: AsyncTask without leak
override fun onPause() {
super.onPause()
...
when {
placesTask != null -> {
placesTask!!.cancel(true)
placesTask = null
}
setPlacesTask != null -> {
setPlacesTask!!.cancel(true)
setPlacesTask = null
}
}
}
...
@Throws(IOException::class)
private fun downloadUrl(strUrl: String): String {
var data = ""
var iStream: InputStream? = null
var urlConnection: HttpURLConnection? = null
try {
urlConnection = URL(strUrl).openConnection() as HttpURLConnection
urlConnection.connect()
iStream = urlConnection.inputStream
val br = BufferedReader(InputStreamReader(iStream!!))
val sb = StringBuilder()
var line: String? = null
while ({line = br.readLine(); line }() != null) sb.append(line)
data = sb.toString()
br.close()
} catch (e: Exception) {
Log.d("downloading url", e.toString())
} finally {
if (iStream != null) iStream.close()
if (urlConnection != null) urlConnection.disconnect()
}
return data
}
companion object {
...
var placesTask: PlacesTask? = null
var setPlacesTask: SetPlaceTask? = null
class PlacesTask(mainActivity: MainActivity) : AsyncTask<String, Int, String>() {
private val mRef: WeakReference<MainActivity> = WeakReference(mainActivity)
override fun doInBackground(vararg url: String): String? {
var data: String? = null
try {
data = mRef.get()?.downloadUrl(url[0])
} catch (e: Exception) {
Log.d("Background Task", e.toString())
}
return data
}
override fun onPostExecute(result: String) {
setPlacesTask = SetPlaceTask(mRef.get()!!).execute(result) as SetPlaceTask?
}
}
class SetPlaceTask(mainActivity: MainActivity) : AsyncTask<String, Int, List<HashMap<String, String>>>() {
private val mRef: WeakReference<MainActivity> = WeakReference(mainActivity)
override fun doInBackground(vararg jsonData: String): List<HashMap<String, String>>? {
var places: List<HashMap<String, String>>? = null
try {
places = PlaceJSONParser().parse(JSONObject(jsonData[0]))
} catch (e: Exception) {
Log.d("Exception", e.toString())
}
return places
}
override fun onPostExecute(list: List<HashMap<String, String>>) {
for (i in list.indices) {
val hmPlace = list[i]
mRef.get()?.parkingLatLng = LatLng(hmPlace["lat"]!!.toDouble(), hmPlace["lng"]!!.toDouble())
mRef.get()?.mMarkerPlaceLink!!.put(mRef.get()?.map!!.addMarker(MarkerOptions().icon(mRef.get()?.vectorToBitmap(R.drawable.ic_local_parking_black_12dp, ContextCompat.getColor(mRef.get()?.applicationContext, R.color.colorPrimaryDark))).position(mRef.get()?.parkingLatLng!!).title(hmPlace["place_name"] + "\n" + hmPlace["vicinity"])).id, hmPlace["reference"].toString())
mRef.get()?.map!!.addCircle(CircleOptions().center(mRef.get()?.parkingLatLng).radius(1.0).strokeColor(Color.BLACK).fillColor(Color.WHITE).strokeWidth(1f).zIndex(1f))
}
}
}
}
Call: placesTask = PlacesTask(this).execute("https://maps.googleapis.com/maps/api/place/nearbysearch/json?location="...) as PlacesTask?
Good luck!
Upvotes: 0
Reputation: 25573
As the exception says, the parameter result
is null
while you've defined it as non-nullable.
Since that parameter is the value returned by doInBackground
, it happens because downloadUrl
threw an exception, leaving the data
variable as null
.
To fix it, do either of these options:
doInBackground
never returns a null.onPostExecute
to String?
and handle the case where it might be null when an exception happens.Upvotes: 1