在Android中取消异步任务

时间:2015-02-23 19:32:17

标签: android android-asynctask

我试图在一段时间后取消异步任务。我已经搜索过并发现了很多关于此问题的问题,所有问题都与我在下面所做的相同。

问题:在调用cancel之后,webservice似乎没有取消,因为它永远不会到达onPostExecute。 请任何帮助将不胜感激。

我的尝试:

经过一段时间后我打电话

类TimeOut,它将asyncTask作为其参数并执行以下操作:

if (task.getStatus() == AsyncTask.Status.RUNNING )
        {task.cancel(true);}
   if(task.isCancelled()==true)
            {
                Log.e(TAG,"TASK IS CANCELLED");
            }

和我的异步类

@Override
    protected void onCancelled() {

        webServiceError=true;  //when timeout change it to true.(default false)
        Toast.makeText(context, R.string.webserviceDownloadUserDataError, Toast.LENGTH_LONG).show();
        if (pd.isShowing()) {
            pd.dismiss();
        }
        super.onCancelled();
    }

    @Override
    protected String doInBackground(String... params) {
        int paramsTracker = 0;
        webServiceError = false;


        while(webServiceError==false) {

            HttpClient httpclient = new DefaultHttpClient();

            String url = params[paramsTracker];
            paramsTracker = paramsTracker + 1;

            HttpPost httppost = new HttpPost(url);

            int paramsCount = params.length;

            try {
                List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(paramsCount);
                for (int i = 0; i < (paramsCount - 1) / 2; i++) {
                    Log.d(TAG, "parameters: " + params[paramsTracker] + " - " + params[paramsTracker + 1]);
                    nameValuePairs.add(new BasicNameValuePair(params[paramsTracker], params[paramsTracker + 1]));
                    paramsTracker = paramsTracker + 2;
                }
                httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

                // execute http post request, call web service


                response = httpclient.execute(httppost);


            }

            catch (Exception e) {
                webServiceError = true;
                Log.e(TAG, e.toString());
                try {
                    AppLogging(TAG, "Error in calling web service " + e.toString(), LogFileName.ErrorLogFilename);
                } catch (Exception a) {
                }
            }


            if (webServiceError == false) {

                int CNT = 0;
                try {

                    String query = "SELECT COUNT(*) AS CNT FROM TASKS";
                    Cursor cursor = MainActivity.myDataBase.rawQuery(query, null);
                    if (cursor.moveToFirst()) {
                        do {
                            CNT = Integer.parseInt(cursor.getString(cursor.getColumnIndex("CNT")));
                        } while (cursor.moveToNext());
                        cursor.close();
                    }
                } catch (Exception e) {
                    Log.e(TAG, e.toString());
                    try {
                        AppLogging(TAG, "Error in Database error getting task count " + e.toString(), LogFileName.ErrorLogFilename);
                    } catch (Exception a) {
                    }
                }

                if (CNT == 0) {
                    String webServiceResponse = "";
                    try {
                        Log.d(TAG, "Getting web service response");
                        // get web service response
                        HttpEntity entity = response.getEntity();
                        String content;
                        content = EntityUtils.toString(entity);
//                  Log.d(TAG, "content: "+ content);
                        // parse XML response
                        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
                        DocumentBuilder db = dbf.newDocumentBuilder();
                        InputSource is = new InputSource();
                        is.setCharacterStream(new StringReader(content));
                        Document doc = db.parse(is);
                        NodeList nodes = doc.getElementsByTagName("string");
                        Element line = (Element) nodes.item(0);
                        webServiceResponse = getCharacterDataFromElement(line);



                        String patternForON = "SET IDENTITY_INSERT \\[.*?\\] O?((N)|(FF))\\s*?;";
                        Pattern rForON = Pattern.compile(patternForON);
                        Matcher mForON = rForON.matcher(webServiceResponse);
                        String webServiceResponseWithOutIdentityInsert = mForON.replaceAll("");

                        String patternForInsert = "\\bINSERT (?!INTO)";
                        Pattern rForInsert = Pattern.compile(patternForInsert);
                        Matcher mForInsert = rForInsert.matcher(webServiceResponseWithOutIdentityInsert);
                        String webServiceResponseWITHOUTINSERTALONE = mForInsert.replaceAll("INSERT INTO ");
                        String webServiceResponsePURIFIED = webServiceResponseWITHOUTINSERTALONE.replaceAll(";;", ";");
                        Log.d(TAG, "content: " + webServiceResponsePURIFIED);
                        ///////////END OF for removing queries that are not applicable in SQLITE

                        //FOR SPLITTING THE QUERIES AND PLACING EACH AT AN INDEX IN contentArray ARRAY
                        //String contentArray [] = webServiceResponse.split(";");
                        String contentArray[] = webServiceResponsePURIFIED.split(";");
                        Log.d(TAG, "contentArray length" + contentArray.length + ""); //GETS THE NUMBER OF QUERIES
                        pd.setMax(contentArray.length); //SETTING THE PROGRESS DIALOG (MAX PROGRESS)

                        for (int i = 0; i < contentArray.length; i++) {
                            // add the downloaded data to the local database
                            String query = contentArray[i];
                            try {
                                AppLogging(TAG, "Queries Downloaded splitted and purified\n query " + i + " :" + contentArray[i], LogFileName.LogFilename);
                            } catch (Exception l) {
                            }
                            Log.d(TAG, "query: " + query);
                            // if query contains "getdate()" replace with DATETIME('now'), to render the query executable in sqlite
                            query = query.replace("GETDATE()", "DATETIME('now')");

                            try {
                                MainActivity.myDataBase.execSQL(query); //EXECUTE QUERY
                            } catch (Exception e) {
                                Log.e(TAG, e.toString());
                                try {
                                    AppLogging(TAG, "Error in performing query: " + query + "\nError: " + e, LogFileName.ErrorLogFilename);
                                } catch (Exception a) {
                                }
                            }

                            //Log.d("Initialize database, HTTPRequestGetUserData ", query);

                            publishProgress();
                        }
                    } catch (Exception e) {
                        webServiceError = true;
                        Log.e(TAG, e.toString());
                        try {
                            AppLogging(TAG, "Error:  " + e.toString(), LogFileName.ErrorLogFilename);
                        } catch (Exception a) {
                        }
                    }
                }
            }
           if (isCancelled()) return "0";
        }
        return "1";
    }

2 个答案:

答案 0 :(得分:3)

根据Android AsyncTask文档,在AsyncTask上调用cancel()后,它将不会调用onPostExecute()而是调用onCancelled()。所以需要流动。

现在按照此处的文档,您的代码

@Override
    protected String doInBackground(String... params) {

       while(webServiceError=false) {
                 .....//calling webservice
             if (isCancelled()) return "0";
        }
      return "1";
}

现在你的onCancelled()看起来像是String参数

@Override
protected void onCancelled(String object) { // Here object should be 0

    webServiceError=true;  //when timeout change it to true.(default false)
    Toast.makeText(context, R.string.webserviceDownloadUserDataError, Toast.LENGTH_LONG).show();
    if (pd.isShowing()) {
        pd.dismiss();
    }
    super.onCancelled();
}

现在使用此方法参数object will be 0。不要担心方法onPostExecute()onCancelled()将在主UI线程上运行。

现在我建议您创建一个私有方法,您希望从onPostExecute()onCancelled()使用String参数执行该方法。

答案 1 :(得分:0)

取消AsyncTask时,它永远不会触及OnPostExecute过程。 API Doc:

中提到了这一点

http://developer.android.com/reference/android/os/AsyncTask.html

  

可以通过调用cancel(boolean)随时取消任务。调用此方法将导致后续调用isCancelled()返回true。调用此方法后,将在doInBackground(Object [])返回后调用onCancelled(Object)而不是onPostExecute(Object)。为确保尽快取消任务,应始终定期从doInBackground(Object [])检查isCancelled()的返回值(如果可能)(例如在循环内)。