Android View实现了Runnable - 没关系,还是Handler是必须的?

时间:2011-03-05 08:33:34

标签: android multithreading view

我想问一个关于android View绘制游戏或动画循环的问题。

我之前已经完成了j2me的一些游戏开发,我尝试在android中实现相同的绘图逻辑,只是为了衡量性能并试验框架。我的第一次尝试是使用View和onDraw()。稍后我将尝试使用SurfaceView。

所以这是我的问题:我扩展了View并使View实现了Runnable,因此它可以启动一个线程使循环不在UI线程上。代码工作正常。

困扰我的是,在android documentation中,它写道,如果不使用Handler,就无法从另一个线程调用View的方法。文档说我应该使用一个处理程序,但是我的代码在没有它的情况下工作。

引用:

  

注意:整个视图树是单一的   螺纹。您必须始终在UI上   调用任何方法时的线程   视图。如果你正在做其他工作   线程并想要更新状态   你应该从那个线程看一个视图   使用处理程序。

以下是View的代码。有理由我更喜欢使用Handler而不是下面的代码吗?

非常感谢。

public class DrawView extends View implements Runnable
{
    private Context mContext = null;    
    private Thread drawThread = null;
    private Drawable mIcon = null;

    public DrawView(Context context)
    {
        super(context);
        mContext = context;
        mIcon = context.getResources().getDrawable(R.drawable.icon);
    }

    protected void onDraw(Canvas canvas)
    {
        mIcon.draw(canvas);
    }

    public void start()
    {
        if(drawThread == null) drawThread = new Thread(this);
        drawThread.start();
    }

    public void run()
    {
        while(true)
        {
            // updateGameState(); // move the objects (icon) to new position
            postInvalidate(); // request for drawing objects
        }
    }
}

----编辑----

当通过postInvalidate更新视图时,使用上面的代码而不使用Handler似乎是合理的。

  

导致指定的无效   在随后的循环中发生的区域   通过事件循环。用它来   从非UI中使视图无效   线程。

所以在我看来Android文档中关于View的注释应该得到纠正,因为当你想从另一个线程更新View时,Handler不是唯一的选择。

3 个答案:

答案 0 :(得分:2)

处理程序不是必须的,您可以随时使用runOnUiThread()

但是我不确定这是否符合您的意图。澄清一下:您的视图必须(据我所知)在UI线程Looper上生成并处理。 View公开的大多数功能都会检查非法的跨线程调用,因为View不能同时被多个线程访问。

如果扩展View,您总是可以从任何线程调用自己的方法,但是如果不向UI线程的消息队列发布内容,则无法访问继承的功能。如果您使用HandlerrunOnUiThread()或使用其他一些线程安全方法(现在不能想到任何方法),则取决于您。

在您的情况下,run()在其自己的线程上运行,但postInvalidate()将导致从UI线程重绘。

答案 1 :(得分:1)

运动更平滑,可以运行,因为我得到60fps或150,如果我想要比较30使用处理程序,虽然我没有超过10个对象同时移动,我想这可能是设备依赖,也许是android os版本依赖。 Motorola flipout使用2.1。无论如何使用runnable方法来自j2me游戏,所以它应该工作正常,你只需要最小化你的线程睡眠不要运行太快。使用处理程序可能会为您做到这一点

答案 2 :(得分:0)

做了一些xperimenting,如果你想达到超过30fps,例如匹配iphone标准60fps,你将需要使用runnable,如你的例子中没有处理程序,当我使用一个处理程序时它永远不会超过30fps。有人说它足够了,但是当你与60相比时它就不一样了,特别是对于快节奏的游戏,但它可能会更快地耗尽电池