【问题标题】:Call AsyncTask multiple times parallel多次并行调用 AsyncTask
【发布时间】:2013-10-04 11:24:30
【问题描述】:

我正在尝试从循环中调用 AsyncTask。它工作正常,但问题是执行所有请求需要更多时间。请建议我如何让它更快。

for (int i = 0; i < 6; i++) {
    response  = requestWeatherUpdate(location);
}

请求天气更新

private WeatherResponse requestWeatherUpdate(String location) {
        url = ""+ location;
        Log.d("URL for Weather Upadate", url);
        WeatherUpdateAsyncTask weatherReq = new WeatherUpdateAsyncTask();
        String weatherRequestResponse = "";
        try {
            weatherRequestResponse = weatherReq.execute(url).get();
            if (weatherRequestResponse != "") {
                parsedWeatherResponse = ParseWeatherResponseXML
                        .parseMyTripXML(weatherRequestResponse);
            }

        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return parsedWeatherResponse;

    }

使用回调

  public class WeatherUpdateAsyncTask extends AsyncTask<String, Void, String> {
    Context context;
    CallBack callBack;

    public WeatherUpdateAsyncTask(CallBack callBack) {
        this.callBack = callBack;
    }

    @Override
    protected String doInBackground(String... arg0) {
        String responseString = "";
        HttpClient client = null;
        try {
            client = new DefaultHttpClient();
            HttpGet get = new HttpGet(arg0[0]);
            client.getParams().setParameter("http.socket.timeout", 6000);
            client.getParams().setParameter("http.connection.timeout", 6000);
            HttpResponse responseGet = client.execute(get);
            HttpEntity resEntityGet = responseGet.getEntity();
            if (resEntityGet != null) {
                responseString = EntityUtils.toString(resEntityGet);
                Log.i("GET RESPONSE", responseString.trim());
            }
        } catch (Exception e) {
            Log.d("ANDRO_ASYNC_ERROR", "Error is " + e.toString());
        }
        Log.d("ANDRO_ASYNC_RESPONSE", responseString.trim());
        client.getConnectionManager().shutdown();
        return responseString.trim();

    }

    @Override
    protected void onPostExecute(String result) {
        // TODO Auto-generated method stub
        super.onPostExecute(result);
        callBack.run(result);
    }

}

请求天气更新

 private WeatherResponse requestWeatherUpdate(String location) {
    url = ""
            + location;
    Log.d("URL for Weather Upadate", url);
    WeatherUpdateAsyncTask weatherReq = new WeatherUpdateAsyncTask(new CallBack() {
        @Override
        public void run(Object result) {
            try {
                String AppResponse = (String) result;
                response = ParseWeatherResponseXML
                        .parseMyTripXML(AppResponse);

            } catch (Exception e) {
                Log.e("TAG Exception Occured",
                        "Exception is " + e.getMessage());
            }
        }
    });
    weatherReq.execute(url);
    return response;

}

我在这里打电话

for (int i = 0; i < 4; i++) {
            inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            RelativeLayout layout = (RelativeLayout) inflater.inflate(
                    R.layout.sector_details, depart_arrivals_details, false);
            depart_time = (TextView)layout.findViewById(R.id.depart_time);
            depart_airport_city = (TextView)layout.findViewById(R.id.depart_airport_city);
            temprature = (TextView)layout.findViewById(R.id.temprature);
            humidity = (TextView)layout.findViewById(R.id.humidity);
            flight_depart_image = (ImageView)layout.findViewById(R.id.flight_depart_image);


            depart_time.setText("20:45");
            depart_airport_city.setText("Mumbai");
            /*
             * This part will be updated when we will se the request and get the response 
             * then we have to set the temp and humidity for each city that we have recived
             * */
            temprature.setText("");//Here i have set the values from the response i recived from the AsynkTask
            humidity.setText("");//Here i have set the values from the response i recived from the AsynkTask

            flight_depart_image.setImageResource(R.drawable.f1);

            depart_arrivals_details.addView(layout, i);
        }

【问题讨论】:

  • 你能详细说明为什么你需要循环异步吗?
  • 如果您使用的是 4.0 或更高版本的异步任务,按调用顺序执行,而不是同时执行。尝试像这样执行:“AsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "");"
  • 看到问题是我在 for 循环中调用 asynk 任务需要更多时间,所以有什么方法可以减少执行时间
  • @invisbo 你的意思是通过调用 execute() 他们将在同一个线程中依次运行?
  • @Rahul 是的,没错

标签: android android-asynctask


【解决方案1】:
  1. AsyncTask 上调用 get() 会阻塞调用线程。不要那样做。而是将结果传递给 onPostExecute() 中的调用者。

  2. 从 Honeycomb 开始,默认实现在串行执行器上按顺序执行异步任务。要并行运行 asynctask,请使用 executeOnExecutor(THREAD_POOL_EXECUTOR, ...) 而不是 execute(...)

【讨论】:

  • 看到我已经这样做了,因为我必须设置我将从响应中获得的值对我在循环中 infalting 的布局
【解决方案2】:

您不应使用 get() 。调用 get() 不会使调用异步。而是使用execute

weatherRequestResponse = weatherReq.execute(url).get();

get()

public final Result get ()

Added in API level 3
Waits if necessary for the computation to complete, and then retrieves its result.

Returns
The computed result.
Throws
CancellationException   If the computation was cancelled.
ExecutionException  If the computation threw an exception.
InterruptedException    If the current thread was interrupted while waiting.

对于并行执行使用executeOnExecutor

  weatherReq.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);

如果您的 asynctask 是您的活动类的内部类,您可以在onPostExecute 中更新 ui。如果不是,您可以使用接口作为回调。

Retrieving a returned string from AsyncTask in Android

How do I return a boolean from AsyncTask?

从讨论中你得到 NUllPointerException @temprature.setText(parsedWeatherResponse.getTempInC()+(char) 0x00B0);

你还没有初始化parsedWeatherResponse。你只是声明了它

  parsedWeatherResponse = new WeatherResponse();

【讨论】:

  • 我还必须在我正在犯错的循环中更新布局值
  • @Rahul 你可以使用接口作为回调
  • 我用过那个,但它没有更新我的价值观,所以如果你说我可以放我的竞争代码,我就用它
  • @Rahul 检查发布的链接。如果你做得对,它会起作用。
  • @Rahul 你有什么错误吗?结果是否分配给AppResponse
【解决方案3】:

使用 executeOnExecutor(THREAD_POOL_EXECUTOR, ...) 并行运行异步任务。你也可以使用HttpURLConnection 而不是 DefaultHttpClient/HttpGet

【讨论】:

    【解决方案4】:

    如果你想从 UI 线程连接网络,这是相当困难的。 "当应用程序尝试在其主线程上执行网络操作时引发的异常。

    这仅适用于面向 Honeycomb SDK 或更高版本的应用程序。允许以早期 SDK 版本为目标的应用程序在其主事件循环线程上进行网络连接,但非常不鼓励这样做。请参阅文档为响应性而设计。”

    如果您想克服这个困难,请按照以下说明进行操作:

    解决方法如下。我从另一个答案中找到了它。它对我有用。并将下面的 import 语句放入您的 java 文件中。

    import android.os.StrictMode;
    

    将以下代码写入 onCreate

    if (android.os.Build.VERSION.SDK_INT > 9) {
        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多