0

我正在使用 asynctask 进行蓝牙套接字通信。它在galaxy s ii(android 2.3.3)上运行良好,但有时不适用于galaxy s iii(android 4.0.4)。

class MyTask extends AsyncTask<Void, long[], Void> {
     long[] d = new long[40];

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        Log.e("BTtest", "MyTask preexecute");
    }

    @Override
    protected Void doInBackground(Void... v) {
        int count = 0;
        Log.e("BTtest", "Mytask background start " );
            *******creting socket and streams*******
                    *********logic*******
                    publishProgress(d);
            }


    @Override
    protected void onPostExecute(Void result) {
        super.onPostExecute(result);
        **logic**           
    }

    @Override
    protected void onProgressUpdate(long[]... data) {
        super.onProgressUpdate(data);
                    *******logic***
        }

}

来自 onCreate 按钮功能:

mt = new MyTask();
mt.execute( );

有时在galaxy s iii 上调用onPreExecute 方法而doInBackground 方法未启动。但其他时候调用后台方法。它看起来像随机的。

有任何想法吗?

wildhemp 建议只在一个线程中执行哪些异步任务。我在一个活动中编写了这 3 个异步任务的测试应用程序:

public class MainActivity extends Activity {

 MyTask mt1, mt2, mt3;
  TextView tvInfo;

  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    tvInfo = (TextView) findViewById(R.id.tvInfo);
  }

  public void onclick(View v) {
        mt1 = new MyTask();
        mt1.execute("file_path_1", "file_path_2", "file_path_3", "file_path_4");
        mt2 = new MyTask();
        mt2.execute("file_path_1", "file_path_2", "file_path_3", "file_path_4");
        mt3 = new MyTask();
        mt3.execute("file_path_1", "file_path_2", "file_path_3", "file_path_4");
  }

  class MyTask extends AsyncTask<String, Integer, Void> {

    @Override
    protected void onPreExecute() {
      super.onPreExecute();
      tvInfo.append("Begin \n");
    }

    @Override
    protected Void doInBackground(String... urls) {
      try {
        int cnt = 0;
        for (String url : urls) {
          downloadFile(url);
          publishProgress(++cnt);
        }

      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      return null;
    }


    @Override
    protected void onProgressUpdate(Integer... values) {
      super.onProgressUpdate(values);
      tvInfo.append("Downloaded " + values[0] + " files \n");
    }

    @Override
    protected void onPostExecute(Void result) {
      super.onPostExecute(result);
      tvInfo.append("End\n");
    }


    private void downloadFile(String url) throws InterruptedException {
      int i=0;
      while (i<100000000){
          i+=1;
      }
    }
  }
} 

它在 sgs2、sgs3 和模拟器上运行良好。应用程序在 sgs3 上以 75%(4 个内核上的 3 个线程)加载 cpu。sgs2 加载 100%(2 个内核上的 3 个线程)。这意味着每个异步任务在单独的线程中执行。

问题解决了。谢谢。我已经更改了项目目标构建版本。现在执行代码:

                    mt = new MyTask();

                    if (Build.VERSION.SDK_INT >= 11){
                        mt.executeOnExecutor( AsyncTask.THREAD_POOL_EXECUTOR); //work on sgs3 android 4.0.4
                    }
                    else {
                        mt.execute(); // work on sgs2 android 2.3
                    }
4

1 回答 1

0

这可能会发生,因为 4.0.4 上的 doInBackground 默认使用 1 个线程来运行所有异步任务,所以如果另一个 doInBackground 仍在工作,它将阻止执行,我认为在这种情况下会调用 onPreExecute,因为它是在主线程上运行。在 2.3.3 中,asynctask 使用更多线程(AFAIK 为每个任务一个新线程)。

更新:这是android文档所说的:

首次引入时,AsyncTask 在单个后台线程上串行执行。从 DONUT 开始,这被更改为允许多个任务并行运行的线程池。从 HONEYCOMB 开始,任务在单个线程上执行,以避免并行执行导致的常见应用程序错误。

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

于 2013-01-01T19:59:18.897 回答