【问题标题】:AsyncTask ; doInbackground() not called after calling method onPreExecute()异步任务;调用方法 onPreExecute() 后未调用 doInbackground()
【发布时间】: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 执行得很好

标签: android android-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】:

    我也遇到过这种情况。

    1. 我打了个电话AsyncTask.cancel(boolean mayInterruptIfRunning)通过了
    2. 然后我假设(我错了)这个任务的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);
      

      【讨论】:

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