异步任务;调用方法 onPreExecute() 后未调用 doInbackground()

Posted

技术标签:

【中文标题】异步任务;调用方法 onPreExecute() 后未调用 doInbackground()【英文标题】:AsyncTask ; doInbackground() not called after calling method onPreExecute() 【发布时间】:2015-01-09 12:29:20 【问题描述】:

我确实在我的项目中添加了异步库并且已经检查过了,我不知道为什么代码流没有进入异步任务

代码

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");'

【问题讨论】:

尝试 .execute() 而不是 .execute(null, null, null); 结果是一样的...为什么你认为这是一个解决方案?在本地,它与 '.execute(null,null,null)' 配合得很好 可能另一个异步任务仍在执行 @brightstar 在我的日志 cat 中,'AsyncTask : doInBackground' 被标记... @LKM 好吧,如果你的 logcat 中有“doInBackground”,那么你的 asynctask 执行得很好 【参考方案1】:

你应该用executor来执行你的任务

task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);

因为在较低版本的 android 中,所有 AsyncTask 都在单个后台线程中执行。因此,新任务可能正在等待,直到其他任务工作为止。

在 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();
    

【讨论】:

【参考方案2】:

这样做不适合你吗?

task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);

我已经这样做了,但问题仍然存在,问题是我使用 AsyncTask 运行长期后台任务,因此ThreadPoolExecutor 的工作线程已经被占用。

在我的情况下,AsyncTask.THREAD_POOL_EXECUTOR(使用调试器获取您的执行程序属性)具有 ff 属性:

maximumPoolSize = 3
largetsPoolSize = 2
corePoolSize =2 

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

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

【讨论】:

或者你可以定义你自己的自定义执行器——这并不难,只需看看它是如何在 AsyncTask 中完成的,并在池中使用更多线程【参考方案3】:

我也遇到过这种情况。

    我打了个电话AsyncTask.cancel(boolean mayInterruptIfRunning)通过了 然后我假设(我错了)这个任务的doInBackground() 现在被中断了

通过添加日志语句,我意识到第一个 asyncTask 仍在运行......因此阻止了另一个 asyncTask 执行。 doInBackground() 方法正在运行一个无限循环,所以我只需要更改条件以考虑所有可能的“中断”情况......

【讨论】:

【参考方案4】:

引用Async Task的Android文档

在首次引入时,AsyncTask 是在单个 后台线程。从 DONUT 开始,这变成了一个池 允许多个任务并行运行的线程。从...开始 HONEYCOMB,任务在单线程上执行,避免常见 并行执行导致的应用程序错误。

如果你真的想要并行执行,你可以调用 executeOnExecutor(java.util.concurrent.Executor, Object[]) 与 THREAD_POOL_EXECUTOR。

使用这个 sn-p 来触发 AsyncTask:

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

【讨论】:

以上是关于异步任务;调用方法 onPreExecute() 后未调用 doInbackground()的主要内容,如果未能解决你的问题,请参考以下文章

Android AsyncTask异步任务的使用

AsyncTask介绍

自定义异步任务的实现不起作用

AsyncTask Android方法的技术差异

从片段调用 Android AsyncTask 没有调用其成员 - doInbackground、onpreexecute、onpostexecute

在 onPreExecute() 内部调用时 TextView.setText() 的 NullPointerException