|
|
1
18
为了将Jonathan Perlow的解决方案推广到他特别指出的bug,我在任何使用AsyncTask的类中都使用了以下内容。looper/handler/post是如何在Android应用程序中的任何地方的UI线程上运行某些东西,而不必将句柄传递给活动或其他上下文。在类中添加此静态初始化块:
我们在试图运行单元测试时遇到了这个问题。我找到了解决办法,但还没有明确指出问题所在。我们只知道尝试在Android JUnit测试中使用AsyncTask<>会导致不调用onPostExecute()。现在我们知道原因了。 本文展示了如何在Android JUnit测试中运行多线程异步代码: Using CountDownLatch in Android AsyncTask-based JUnit tests 为了与非UI单元测试一起使用,我创建了android.test.InstrumentationTestCase的一个简单子类。它有一个“ok”标志和一个倒计时锁。reset()或reset(count)创建一个新的countdownlock({1,count})。good()设置ok=true、count--,并在闩锁上调用.countDown()。bad()设置ok=false,并一直倒计时。等待(秒)等待超时或coundown闩锁为零。然后它调用assertTrue(ok)。 那么测试就像:
由于AsyncTask静态初始化错误,我们必须在传递给runTestOnUiThread()的Runnable中运行实际的测试。对于上述正确的静态初始化,这是不必要的,除非正在测试的调用需要在UI线程上运行。 我现在使用的另一个习惯用法是测试当前线程是否是UI线程,然后在适当的线程上运行所请求的操作。有时,允许调用者请求同步和异步是有意义的,在必要时重写。例如,网络请求应该始终在后台线程上运行。在大多数情况下,异步任务线程池非常适合这样做。只需意识到一次只会运行一个特定的数字,从而阻止其他请求。要测试当前线程是否为UI线程,请执行以下操作:
然后使用AsyncTask的简单子类(只需要doInBackground()和onPostExecute())在非UI线程上运行,或者使用handler.post()或postDelayed()在UI线程上运行。 为调用方提供运行sync或async的选项,如下所示(获取此处未显示的本地有效onUiThread值;如上所述添加本地布尔值):
而且,使用AsyncTask可以变得非常简单和简洁。使用下面RunAsyncTask.java的定义,然后编写如下代码:
或者简单地说:new RunAsyncTask(“”).execute(new Runnable(){public void run(){doSomethingInBackground();}); RunAsyncTask.java:运行异步任务:
|
|
|
2
40
这是由于Android框架中AsyncTask中的一个bug造成的。AsyncTask.java有以下代码:
它希望在主线程上初始化它,但这是不能保证的,因为它将在任何导致类运行其静态初始化器的线程上初始化。我在处理程序引用工作线程时复制了这个问题。 导致这种情况发生的一个常见模式是使用类IntentService。C2DM示例代码就是这样做的。 一个简单的解决方法是将以下代码添加到应用程序的onCreate方法中:
这将强制在主线程中初始化AsyncTask。我在android错误数据库中对此提出了一个错误。见 http://code.google.com/p/android/issues/detail?id=20915 . |
|
|
3
2
我在带有Android 4.0.4和IntentService的设备上遇到了同样的问题,并像sdw对Class.forName(“Android.os.AsyncTask”)所说的那样解决了这个问题。在Android 4.1.2、4.4.4或5.0上,情况并非如此。我想知道谷歌是否从2011年起解决了马丁·韦斯特的问题。 我在应用程序onCreate中添加了这段代码,它起了作用:
很高兴知道Android版本是否需要更改为其他版本。 |
|
|
4
1
|
|
|
5
0
我也有同样的问题,当异步任务在挂起/恢复期间运行时,似乎会发生这种情况。 编辑: 是的,没想到我有但是我用了这个 http://developer.android.com/guide/appendix/faq/commontasks.html#threading 总是在UI线程上启动AsyncTask,问题就解决了。 问题出现在我添加了许可功能sigghhhh之后 谢谢 |
|
|
6
0
尽管这并不能直接回答OP的问题,但我认为这对于人们在运行测试时寻找相同问题的解决方案是有用的。 总的来说, Peter Knego's answer 总结得很好。 我的问题是在一个活动之外的类上运行测试,该活动使用Android的AsyncTask进行API调用。这个类在应用程序中工作,因为它被一个活动使用,但是我想运行一个测试,从测试中发出一个实际的API调用。 当 Jonathan Perlow's answer 工作了,我不喜欢仅仅因为一个测试而对我的应用程序进行更改。
所以,在测试的情况下
但有时,特别是在功能测试中,Jonathan Perlow的答案似乎是唯一有效的。 * Take a look here 查看如何暂停测试以等待结果。 |