繁体   English   中英

我应该如何实现我的 AsyncTask class?

[英]How should I implement my AsyncTask class?

我正在制作一个天气应用程序,我使用 AsyncTask 从 API 获取响应,然后设置 UI。 经过简单处理后,我的代码如下所示:

class MainActivity : AppCompatActivity() {


    /*
    SOME INSIGNIFICANT CODE HERE
    */

    private fun setUI(currentWeather: Root){
        tv_city.text = "${currentWeather.name}, ${currentWeather.sys.country}"
        /*
        ...
        */
    }

    inner class WeatherByNameTask: AsyncTask<String, Unit, Unit>(){

        override fun doInBackground(vararg p0: String?) {
            val city: String? = p0[0]
            val call = weatherApi.getCurrentWeatherByCityName(city!!, API_KEY, "metric")
            call.enqueue(object: Callback<Root>{
                override fun onResponse(call: Call<Root>, response: Response<Root>) {
                    if (!response.isSuccessful){
                        Toast.makeText(this@MainActivity, "Code: ${response.code()}", Toast.LENGTH_LONG).show()
                    } else {
                        val currentWeather = response.body()
                        setUI(currentWeather!!)
                    }
                }

                override fun onFailure(call: Call<Root>, t: Throwable) {
                    Toast.makeText(this@MainActivity, "Code: ${t.message}", Toast.LENGTH_LONG).show()
                }
            })
        }
    }

    inner class WeatherByCoordTask: AsyncTask<Location, Unit, Unit>(){

        override fun doInBackground(vararg p0: Location?) {
            val lat: String = p0[0]?.latitude.toString()
            val lon: String = p0[0]?.longitude.toString()
            val call = weatherApi.getCurrentWeatherByCoordinates(lat, lon, API_KEY, "metric")
            call.enqueue(object: Callback<Root>{
                @SuppressLint("SetTextI18n")
                override fun onResponse(call: Call<Root>, response: Response<Root>) {
                    if (!response.isSuccessful){
                        Toast.makeText(this@MainActivity, "Code: ${response.code()}", Toast.LENGTH_LONG).show()
                    } else {
                        val currentWeather = response.body()
                        setUI(currentWeather!!)
                    }
                }

                override fun onFailure(call: Call<Root>, t: Throwable) {
                    Toast.makeText(this@MainActivity, "Code: ${t.message}", Toast.LENGTH_LONG).show()
                }
            })
        }
    }
}

它有效,但我收到警告:

此 AsyncTask class 应为 static 否则可能会发生泄漏

我想以正确的方式做到这一点。 我试图在 MainActivity class 之外实现它,将上下文作为参数传递,但是 setUI function 呢? 我想公开它是个坏主意。

此 AsyncTask class 应为 static 否则可能会发生泄漏

MainActivity中,有 2 个带有inner修饰符的AsyncTask class,这意味着内部 class 将保持对外部 class 的强引用。 警告告诉您,当AsyncTask在后台执行其工作时,如果用户离开当前活动(按 Back 键或调用finish()方法),那么活动实例将被泄露,因为AsyncTask仍然保持对它。

解决方案

使用WeakReferenceAsyncTask保持对MainActivity的弱引用。

class WeatherByNameTask (activity: MainActivity): AsyncTask<String, Unit, Unit>(){
    private val activityRef = WeakReference<MainActivity>(activity)

    override fun doInBackground(vararg p0: String?) {
        val city: String? = p0[0]
        val call = weatherApi.getCurrentWeatherByCityName(city!!, API_KEY, "metric")
        call.enqueue(object: Callback<Root>{
            override fun onResponse(call: Call<Root>, response: Response<Root>) {
                if (!response.isSuccessful){
                    activityRef.get()?.let {
                        Toast.makeText(it, "Code: ${response.code()}", Toast.LENGTH_LONG).show()
                    }
                } else {
                    val currentWeather = response.body()
                    activityRef.get()?.setUI(currentWeather!!)
                }
            }

            override fun onFailure(call: Call<Root>, t: Throwable) {
                activityRef.get().let {
                    Toast.makeText(it, "Code: ${t.message}", Toast.LENGTH_LONG).show()
                }
            }
        })
    }
}

class WeatherByCoordTask (activity: MainActivity): AsyncTask<Location, Unit, Unit>(){
    private val activityRef = WeakReference<MainActivity>(activity)

    override fun doInBackground(vararg p0: Location?) {
        val lat: String = p0[0]?.latitude.toString()
        val lon: String = p0[0]?.longitude.toString()
        val call = weatherApi.getCurrentWeatherByCoordinates(lat, lon, API_KEY, "metric")
        call.enqueue(object: Callback<Root>{
            @SuppressLint("SetTextI18n")
            override fun onResponse(call: Call<Root>, response: Response<Root>) {
                if (!response.isSuccessful){
                    activityRef.get()?.let {
                        Toast.makeText(it, "Code: ${response.code()}", Toast.LENGTH_LONG).show()
                    }
                } else {
                    val currentWeather = response.body()
                    activityRef.get()?.setUI(currentWeather!!)
                }
            }

            override fun onFailure(call: Call<Root>, t: Throwable) {
                activityRef.get().let {
                    Toast.makeText(it, "Code: ${t.message}", Toast.LENGTH_LONG).show()
                }
            }
        })
    }
}

从活动中使用

val weatherByNameTask = WeatherByNameTask(this)
val weatherByCoordTask = WeatherByCoordTask(this)

以下是制作AsyncTask的方法:

private class AsyncTaskGetPlaces extends AsyncTask<Void, Void, AsyncTaskResult<Object>>
    {
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected AsyncTaskResult<Object> doInBackground(Void... params)
        {
            try
            {
                LibHttp libHttp = new LibHttp();

                String res = libHttp.listBusiness("21","test@ns.com");

                return new AsyncTaskResult<Object>(res);
            }
            catch (Exception e)
            {
                e.printStackTrace();

                return new AsyncTaskResult<Object>(e);
            }
        }

        @Override
        protected void onPostExecute(AsyncTaskResult<Object> result)
        {

            if(result.getError()!= null)
            {
                showOKAlertMsg("App",getResources().getString(R.string.txt_data_not_found), false);
            }
            else
            {
                String res = result.getResult().toString();

                try {
                    JSONObject resObj = new JSONObject(res);

                    if(resObj.getString("status_code").equals("1")){
                        //parse
                        // Do your task here

                    }

                } catch (JSONException e) {
                    e.printStackTrace();
                    showOKAlertMsg("",getResources().getString(R.string.txt_internal_server_error), false);
                }
            }
        }
    }

AsyncTaskResult 在哪里

  public class AsyncTaskResult<T> 
{
    private T result;

    private Exception error;

    public T getResult() 
    {
        return result;
    }

    public Exception getError()
    {
        return error;
    }

    public AsyncTaskResult(T result) 
    {
        this.result = result;
    }

    public AsyncTaskResult(Exception error) 
    {
        this.error = error;
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM