【问题标题】:AsyncTask without leaks没有泄漏的 AsyncTask
【发布时间】:2017-10-19 18:20:24
【问题描述】:

这个 AsyncTask 类应该是静态的,否则可能会发生泄漏

为什么我的 AsyncTask 不起作用?

致电:PlacesTask(this).execute(...)

代码:

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
    }

错误:java.lang.IllegalArgumentException:参数指定为 非空为空:方法 kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull,参数 结果

请帮忙。我错过了什么?

【问题讨论】:

    标签: android memory-leaks android-asynctask kotlin


    【解决方案1】:

    正如例外所说,参数resultnull,而您已将其定义为不可为空。

    由于该参数是doInBackground 返回的值,因此发生这种情况是因为downloadUrl 抛出了异常,将data 变量保留为null

    要修复它,请执行以下任一选项:

    1. 当异常发生时定义一个非空的默认返回值,确保doInBackground永远不会返回空。
    2. onPostExecute的参数类型改为String?,并处理异常发生时可能为null的情况。

    【讨论】:

      【解决方案2】:

      我明白了。

      1. AsyncTask 应该是 static
      2. AsyncTask 移至 -> companion object {}
      3. WeakReference - 对于AsyncTask 没有泄漏(良好的exp。)

      示例:无泄漏的 AsyncTask

      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))
                      }
                  }
              }
      }
      

      致电:placesTask = PlacesTask(this).execute("https://maps.googleapis.com/maps/api/place/nearbysearch/json?location="...) as PlacesTask?

      祝你好运!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-05-16
        • 1970-01-01
        • 1970-01-01
        • 2019-12-20
        • 1970-01-01
        • 1970-01-01
        • 2019-02-13
        • 2021-12-27
        相关资源
        最近更新 更多