【问题标题】:Cancelling an Async Task In Android在 Android 中取消异步任务
【发布时间】:2015-02-23 19:32:16
【问题描述】:

我正在尝试在一段时间后取消异步任务。我已经搜索并发现了很多关于此的问题,并且所有问题的答案都与我在下面所做的一样。

问题:调用取消后,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";
    }

【问题讨论】:

  • 它没有成功

标签: android android-asynctask


【解决方案1】:

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

现在根据此处的文档,您的代码

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

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

现在你的 onCancelled() 看起来像,带有字符串参数

@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() 执行该方法。

【讨论】:

  • 你能帮帮我吗,如果你想让我发布 doinbackground 方法,我会在调用 cancel(true) 后调用 if(isCancelled)
  • @user3703305 我贴出来了
  • 我在 timertask 完成(即 45 秒)后调用取消,调用后我检查 isCancelled() 并返回 true
  • 还有在PreExecute,我有一个progressdialog,如果按下后退按钮,我会调用cancel(true) (setOnCancelListener)
  • 45 秒后,我检查另一个类中任务的状态,如果它正在运行,我将取消它。我发布我正在使用的方法,但这是它的想法
【解决方案2】:

当您取消 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() 的返回值。

【讨论】:

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