我想问一个关于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不是唯一的选择。
答案 0 :(得分:2)
处理程序不是必须的,您可以随时使用runOnUiThread()
。
但是我不确定这是否符合您的意图。澄清一下:您的视图必须(据我所知)在UI线程Looper
上生成并处理。 View公开的大多数功能都会检查非法的跨线程调用,因为View
不能同时被多个线程访问。
如果扩展View,您总是可以从任何线程调用自己的方法,但是如果不向UI线程的消息队列发布内容,则无法访问继承的功能。如果您使用Handler
,runOnUiThread()
或使用其他一些线程安全方法(现在不能想到任何方法),则取决于您。
在您的情况下,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相比时它就不一样了,特别是对于快节奏的游戏,但它可能会更快地耗尽电池