Android平板电脑中,Asynctask DoInBackground()方法未被调用

6
在 Android 应用中,我使用了 Asynctask 类。在我的运行 Android 2.3.5 的设备上测试时,它能正常工作。但是我遇到的问题是,在我的平板电脑 4.0.4 上无法正常工作。
在测试过程中,我发现 prexecute() 被调用了,但 doInbackground() 没有被调用,然而在设备(2.3.5)上 doInbackground() 被调用。
我认为问题的一个原因可能是平板电脑的处理器比设备的处理器快得多,所以可能会出现一些线程问题。为了解决这个问题,我使用了一些标志,并在 do while 循环中使用 Thread.sleep(),以便在条件为 true 时它可以工作,但没有成功,我陷入了循环中。以下是我的代码:
MyAsyncTask object = new MyAsyncTask (MainActivity.this);
runOnUiThread(new Runnable() {
    public void run() {         

        try {
            if (object.isReady() || !object.isStarting()) {
                return;
            }

            object.execute();

            do {
                Thread.sleep(1000);             
            } while (!object.isReady() && object.isStarting());

            if(!object.isReady()) { 
                return;
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }           
});

异步任务类:

public class MyAsyncTask extends AsyncTask<Void, Void, Boolean>{

    private ProgressDialog dialog;
    private Context context;
    private boolean isStarting = false;
    private boolean isReady = false;


    public AsyncUpdatesofJquery(Context context) {
        this.context = context;
        isStarting = true;
        isReady = false;
    }

    public boolean isStarting() {
        return isStarting;
    }

    public boolean isReady() {
        return isReady;
    }

    @Override
    protected void onPreExecute() {

        isStarting = true;
        isReady = false;
        dialog = new ProgressDialog(context); 
        dialog.setMessage("Downloading Files, Please wait...");
        dialog.show();
    }

    @Override
    protected Boolean doInBackground(Void... params) {

        isReady = true;
        isStarting = false;
        downloadFiles(context); // my background task

        return true;
    }

    @Override
    protected void onPostExecute(Boolean result) {
        super.onPostExecute(result);
        context.startActivity(new Intent(context, NewActivity.class));
        dialog.dismiss();
        isReady = false;
        isStarting = false;

    }
}

在UI线程上运行AsyncTask有什么意义? - Egor
2
首先,当您从不同的线程中使用布尔值isStartingisReady时,它们应该是易失性的或更好地使用AtomicBoolean - olshevski
1
@Egor AsyncTask 应该只从 UI 线程启动。我假设在这种情况下代码不在 UI 线程中。否则,我看不到 runOnUiThread() 调用的任何目的。 - olshevski
你确定 doInBackground 没有被执行吗?你调试过它的调用了吗?我非常确定你只是因为 while 循环的错误条件而陷入了无限循环。 - olshevski
1
@dave21,像您之前使用的布尔标志一样是不安全的线程,因为线程可能会缓存变量值。 因此,如果一个线程修改了一个变量,则该更改未必对任何其他线程可用。 要么修复代码使其线程安全,要么只是使用一些日志记录。 - dave.c
显示剩余6条评论
1个回答

17

多线程模型在2.3.5和4.0.4之间发生了改变。现在,AsyncTask默认情况下将所有子类放在一个应用程序中使用同一个线程(即一次只能运行一个AsyncTask!)。这在这里有解释:

初次引入时,AsyncTasks在单个后台线程上串行执行。从DONUT开始,它被改为线程池,允许多个任务并行操作。从HONEYCOMB开始,任务在单个线程上执行,以避免由并行执行造成的常见应用程序错误。

如果您真的希望并行执行,则可以使用THREAD_POOL_EXECUTOR调用executeOnExecutor(java.util.concurrent.Executor,Object [])。

考虑到这一点,可能是应用程序中正在运行另一个AsyncTask,从而阻止启动此任务。这就解释了为什么它在您的2.3.5设备上运行良好,但在4.0.4平板电脑上不行。


嘿兄弟,你是对的,实际上还有一个AsyncTask正在运行。但我无法实现executeOnExecutor(),有示例代码吗? - dave21
进一步研究后,我有更多坏消息。executeOnExecutor 直到 Android 3.0 才可用。如果您想要在 2.3.5 和 4.0.4 上实现完全兼容,我认为您需要放弃 AsyncTask 并转而使用 Runnable。这就是我最终采取的方法。好消息是你不需要改变太多的代码。你将不得不自己进入 UI 线程,可能使用 Handler - Todd Sjolander
没错,我不得不放弃Asynctask并使用Runnable,现在工作正常。 - dave21
@ToddSjolander 感谢您详细的回答,点赞。您是否有关于实现时需要进行的更改或集中注意的清单?我们能否找到为此目的分组的文档,以便我们可以专注于这些,而不是面对奇怪的问题并浪费时间在这些问题上。希望您能理解我的问题。 - Dinash
他们不一定会以我认为你要找的形式呈现它:“这是您需要更新以保持与最新Android版本的功能兼容的内容...”但是,文档中有一个diff报告:http://developer.android.com/sdk/api_diff/17/changes.html。那是4.2版的,但您可以调整URL以获取其他版本。当您遇到兼容性问题时,查看它是值得的,但它并没有以易于阅读的格式呈现。 - Todd Sjolander
留给谷歌来搞兼容性问题吧。这只是他们在Android上做的一系列愚蠢之举中的又一个,也是我告诉大多数人购买iPhone的另一个原因。 - Johann

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