我在遵循典型的Android图形流时遇到了一些小麻烦。有很多例子,但我的似乎不起作用。在我的主要活动中,我这样做:
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
在我的资源文件中,我有3个覆盖SurfaceView的自定义类。在这些表面视图的构造函数中,我有这样的东西:
super(context, attrs);
getHolder().addCallback(this);
this.thread = new MyThread(getHolder(),this);
在我的线程运行方法中,我这样做(从我看到的许多例子中借鉴):
Canvas c;
try {
c = surfaceHolder.lockCanvas(null);
synchronized (surfaceHolder) {
panel.onDraw(c);
}
} finally {
if (c != null) {
surfaceHolder.unlockCanvasAndPost(c);
}
这个线程是在我的SurfaceView的"surfaceCreated"事件中启动的。在onDraw中我这样做:
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
<some drawing stuff here using canvas>
}
当我运行时,线程确实运行了,我可以看到onDraw被调用了(我在那里放了日志打印命令),但我的图形并没有像预期的那样更新。然而,如果我调用这个.invalidate(),图形会像我预期的那样更新几次,直到我崩溃:
E/AndroidRuntime(748): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
我意识到,根据我看到的例子,我不应该在OnDraw中调用invalid,但我这样做只是为了验证我的OnDraw中的代码是有效的。因此,在我看来,如果没有invalidate(),onDraw事件就会被调用,我的代码应该会正确地更新图形,但屏幕永远不会更新。在主"活动"实际决定需要重新绘制其子对象的过程中,我遗漏了一些内容。
任何想法都将不胜感激。我花了一段时间试图从一些工作演示中复制一些东西,但我似乎被卡住了。感谢
在run()中所做的事情会做你所做的任何事情-一次。您需要重复绘图过程。
一种方法是将所有内容放入while
环路
while(true){
try {
c = surfaceHolder.lockCanvas(null);
synchronized (surfaceHolder) {
panel.onDraw(c);
}
} finally {
if (c != null) {
surfaceHolder.unlockCanvasAndPost(c);
}
}
我已经遇到了同样的问题。由于找不到任何解决方案,我做了一种变通方法:创建一个Bitmap
作为缓冲区,并绘制到该位图。绘制后,将完整的位图绘制到视图本身。在View类中声明这些变量:
Canvas bmpCanvas;
Bitmap bmp;
并在onDraw()方法中使用它,如图所示:
@Override
protected void onDraw(Canvas canvas) {
if(bmp == null || bmpCanvas == null) {
bmp = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
bmpCanvas = new Canvas(bmp);
}
//do drawing-stuff here
canvas.drawBitmap(bmp, 0, 0, p); //where p is a Paint-Object.
}
现在,要更新视图/调用此方法,请使用视图的invalidate
或postInvalidate()
invalidate
,具体取决于您是在同一线程中还是在其他线程中调用该方法。