AsyncTask; 在调用onPreExecute()方法后,doInBackground()方法未被调用

31
我在我的项目中添加了async库并已经检查过,但我不知道为什么代码流程没有进入asynctask。
代码
public void doMysql()
{
    Log.v("doMysql", "accessed");

    new AsyncTask<Void, Void, String>() {
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            Log.e("AsyncTask", "onPreExecute");
        }
        @Override
        protected String doInBackground(Void... params) {
            Log.v("AsyncTask", "doInBackground");

            String msg = "";

            DefaultHttpClient httpclient = new DefaultHttpClient();
            HttpPost httppost = new HttpPost("http://172.16.100.172:52273/mysql");

            ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();

            nameValuePairs.add(new BasicNameValuePair("myday", Integer.toString(day_picker.getYear()) + 
                    addZero(day_picker.getMonth() + 1) + 
                    addZero(day_picker.getDayOfMonth())));
            nameValuePairs.add(new BasicNameValuePair("mystar", changeStar(day_picker.getMonth() + 1, day_picker.getDayOfMonth())));
            nameValuePairs.add(new BasicNameValuePair("mybt", changeBloodType(blood_picker.getValue())));
            nameValuePairs.add(new BasicNameValuePair("mynum", "" + myPhone.getText()));
            nameValuePairs.add(new BasicNameValuePair("yournum", "" + partnerPhone.getText()));
            nameValuePairs.add(new BasicNameValuePair("myregID", regid));
            try {
                Log.v("setEntity", "before");
                httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
                Log.v("setEntity", "after");

            } catch (UnsupportedEncodingException e1) {
                Log.v("UnsupportedEncodingException", "");
                e1.printStackTrace();
            }
            //172.16.101.28
            try {  
                Log.v("post", "before");
                HttpResponse httpresponse = httpclient.execute(httppost);
                Log.v("post", "after");
                Log.v("HttpResponse ",httpresponse.getEntity().toString());
            } catch (ClientProtocolException e) {
                Log.v("ClientProtocolException", "ClientProtocolException");
                e.printStackTrace();
            } catch (IOException e) {
                Log.v("IOException", "IOException");

                e.printStackTrace();
            }

            return msg;
        }
        @Override
        protected void onPostExecute(String msg) {
            Log.v("AsyncTask", "onPostExecute");

        }
    }.execute(null, null, null);
}

代码中有一个日志语句 'Log.v("AsyncTask", "doInBackground");',

但它没有出现在记录器中 'Log.v("AsyncTask", "doInBackground");'


1
结果是一样的...你认为这会是一个解决方案吗?在本地,使用'.execute(null,null,null)'非常好用。 - LKM
2
可能还有另一个异步任务正在执行。 - njzk2
1
@brightstar 在我的日志中,'AsyncTask: doInBackground' 被标记了... - LKM
1
@LKM 如果你的logcat中有“doInBackground”,那么你的异步任务执行得很好。 - marcinj
我的异步任务不起作用:只有一个地方出现了异常。然而,当用户滚动到我的ListView中的最后一项时,我想更新屏幕时,也无法使用onScroll监听器。当所有方法都无效时,我使用普通线程执行后台操作,并使用处理程序来更新UI的postExecute。 - Abhinav Saxena
显示剩余5条评论
4个回答

78

你应该使用执行器来执行你的任务。

task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);

因为在较旧版本的Android中,所有AsyncTasks都在单个后台线程上执行。因此,新任务可能会等待,直到其他任务完成。

在较早的Android版本中(实际上是在HONEYCOMB之前),您无法在executor上执行AsyncTask。

更改您的代码为

public void executeAsyncTask()
{
    AsyncTask<Void, Void, String> task = new AsyncTask<Void, Void, String>() {
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            Log.e("AsyncTask", "onPreExecute");
        }

        @Override
        protected String doInBackground(Void... params) {
            Log.v("AsyncTask", "doInBackground");
            String msg = null;
            // some calculation logic of msg variable
            return msg;
        }
        @Override
        protected void onPostExecute(String msg) {
            Log.v("AsyncTask", "onPostExecute");
        }
    };

    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB/*HONEYCOMB = 11*/) {
        task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
    } else {
        task.execute();
    }
}

6

这个方法对你不起作用吗?

task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);

我已经在做这个,但问题仍然存在,问题是我正在使用AsyncTask来运行长时间的后台任务,这些任务会一直运行,因此ThreadPoolExecutor的工作线程已经被占用。
在我的情况下,AsyncTask.THREAD_POOL_EXECUTOR(使用调试器获取执行器属性)具有以下属性:
maximumPoolSize = 3
largetsPoolSize = 2
corePoolSize =2 

禁用其中一个长时间运行的asyncTask使我的doInBackground代码可以运行,但这不是正确的解决方案。

正确的解决方案是将长时间运行的任务移入自定义线程而不是使用AsyncTask


1
或者你可以定义自己的自定义执行器 - 这并不难,只需查看AsyncTask中的操作方式,并使用更多线程在池中完成。 - Haggai

6

我曾经遇到过同样的情况。

  1. 我调用了 AsyncTask.cancel(boolean mayInterruptIfRunning),并传入 true 参数
  2. 然后我假设(这是错误的)这个任务的 doInBackground() 已经被中断了

通过添加日志语句,我发现第一个 asyncTask 仍在运行... 这就阻止了另一个 asyncTask 的执行。它的 doInBackground() 方法正在运行一个无限循环,所以我只需要更改条件来考虑所有可能的“退出”情况...


5

引用Android文档异步任务的内容:

当首次引入AsyncTasks时,它们在单个后台线程上串行执行。从DONUT开始,这已更改为一组线程池,允许多个任务并行操作。从HONEYCOMB开始,任务在单个线程上执行,以避免由并行执行引起的常见应用程序错误。

如果您真正想要并行执行,可以使用executeOnExecutor(java.util.concurrent.Executor,Object [])和THREAD_POOL_EXECUTOR来调用。

使用此代码片段触发AsyncTask:

if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB)
   asyncTaskInstance.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
else
   pdfPageChanger.execute(params);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接