2011-04-14 89 views
3

这是我经常使用Asyntask时遇到的一个问题。联系UI线程的方法是调用publishProgress()&此方法接受只有一个参数类型的数组如何让Asynctask以不同的方式更新UI

在后台运行,这样做复杂的计算可能需要更新使用不同类型对象在不同的​​点UI线程。

让我说明一个例子:

...do some processing... 
// Send UI thread the integer values of the width & height of the image 
...do some more processing... 
// Send UI thread a String with custom message. 
...do some more processing... 
// Send UI thread an instance of MyObject so it can extract & display certain values 
...do some cleanup job & finish... 

然而,onProgressUpdate()接受仅一种类型的阵列。

那么,我做出一个包罗万象的对象类型?我怎么知道如何下调它,因为这个方法可以从第1,2或3行调用,所以这是什么时间?

当然必须有一个很好的方法来实现这一目标?

编辑:我真的很想看看,如果在Android中是可能的,将是界定publishProgress1(用户定义args1)publishProgress2(用户定义args2)publishProgress3的一些方法(用户定义的args3) ...

+0

我相信,你所要求的类似的变体结构http://en.wikipedia.org/wiki/Variant_type – JAL 2011-04-15 01:52:50

+0

@JAL:感谢您分享有趣的链接。使用运行时类型确定的Variant_type通过运行时向下转换提醒了我非常多的Java对象类型。我真的很希望看到,如果它可能在Android中,将会是定义* publishProgress1(用户定义的args1)*,* publishProgress2(用户定义的args2)*,* publishProgress3(用户定义的args3) * ... – OceanBlue 2011-04-15 14:27:14

+0

@OceanBlue VisualBasisVARIANT是一个旧的解决方案,但我宁愿看到更安全的解决方案,可能会解决使用消息和单个处理程序来启动三个顺序线程的问题。因此,启动返回类型A的线程返回消息(0),处理程序中的陷阱消息,启动带消息的线程(1)返回类型B,带消息(2)的陷阱和启动线程等。 – JAL 2011-04-16 00:25:35

回答

4

在你的第三个情况......

//发送UI线程的MyObject的

实例......有说你会在onPostExecute()虽然说这样做的说法取决于你的插图意味着什么。

你可以很容易地按照你的建议传递一个包罗万象的对象。该对象可以有各种字段(整数,字符串,对象)加上一个'动作'来描述哪些字段是有效的并且需要被处理。

你可以简单地传递一个int枚举如PROCESS_INT_WIDTH_AND_HEIGHTPROCESS_STRING_MESSAGEPROCESS_OBJECT等,有什么能阻止你这样做......

private static class MyAsyncTask extends AsyncTask<String, int, Void> { 
    private int width; 
    private int height; 
    private String customMessage; 
    private MyObject myObject; 

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

     width = 10; 
     height = 10; 
     publishProgress(PROCESS_INT_WIDTH_AND_HEIGHT); 
    } 

    protected void onProgressUpdate(int... progress) { 
     if (progress == PROCESS_INT_WIDTH_AND_HEIGHT) 
      // Process width and height 
    } 
} 

换句话说,在onProgressUpdate()方法只是简单地回应到'命令'并相应地处理相关的专用字段。

+0

这里的一个危险是'publishProgress()'在onProgressUpdate()'拍摄之前可能会被调用多次。如果您修改方法以使publishProgress()采用Object,并且第一个参数是您的Integer命令ID,其他参数是其余数据,则可以避免此问题。 – CommonsWare 2011-04-14 21:17:42

+0

@CommonsWare:有效的点 - 根据涉及的任务的复杂性,它可能会导致问题。我的偏好实际上是OP所隐含的'包罗万象'的对象,其中要执行的动作/命令被嵌入(如你所说)。从某种意义上说,这模拟了Intents可以使用的方式 - 可以在不同情况下提供相同的数据参数,但“行动”最终决定结果。 – Squonk 2011-04-14 22:02:55

+0

谢谢,我想这可能是最好的方式去解决它,在限制之下。请参阅编辑。 – OceanBlue 2011-04-15 14:41:23

0

我不认为有任何其他方式做到这一点。使用getType方法创建基类,然后将其用作适当投射的类型。

0

在这种情况下泛型类型能工作吗?您可以根据需要键入值。例如AsyncTask原型:

new AsyncTask<String, Object, List<?>>(){ 
... 

我还记得读取AsyncTask是最适合,只能短距离的任务。考虑复杂和长时间运行的其他线程模型。

+0

服务并不是长时间运行的任务,而只是一种在后台运行某些东西的方式。对于长时间运行的任务,即使在服务中也应该使用线程。 – advantej 2011-04-14 21:09:11

+0

不是很长时间。几秒钟。但是对于一个注视着固定屏幕的用户来说,这些看起来似乎很漫长。沿着你想要做的几件事说...显示一条消息,然后进行一些处理,更新整数值等等。希望我的问题有道理! – OceanBlue 2011-04-14 21:11:04

+0

@OceanBlue您仍然可以考虑将您的任务分解为较小的部分或使用较低级别的模型。 'AsyncTask'似乎不适合所有情况。也可以考虑使用所需行为的泛型类型。 – 2011-04-14 21:37:44

0

如果你有回国在AsyncTask处理过程的相应状态值,您可以创建AsyncTask为每个数据/类型,你需要内部的私有成员,然后分配一个整数每个国家和onProgressUpdate(Integer...)switch(state)基于int状态的作业从publishProgress(state)获得。

如果你想坚持AsyncTask(这可能不是最清晰的答案我给)

2

,另一种选择是使用不同的类在不同的时间,和测试用的instanceof类型。

然而,这听起来像一个相对复杂的任务,所以我建议考虑使用Handler并从一个普通Thread张贴[Runnable接口] S 2,或使用runOnUiThread

你也可能需要阅读Painless Threading

希望这有助于

菲尔Lello

+0

为链接+1。这些都是很好的链接,我以前阅读过它们。我认为AsnycTask基本上是为了避免处理程序和线程的复杂性(和潜在的缺陷)而创建的,所以我想尽可能地坚持下去。 – OceanBlue 2011-04-15 14:36:58