我在 SurfaceView 上做错了什么?
What I'm doing wrong with SurfaceView?
我正在尝试使用 SurfaceView 绘制一些东西,但似乎越来越慢,而不是使用 onDraw 并使 View 无效 Class。
所以我需要知道我是否可以让它更快。
这是我的代码。
public class ViewCentroMesa extends SurfaceView implements Runnable
{
// Bucle pintar
Thread t = null;
SurfaceHolder holder;
boolean isItOk = false;
public ViewCentroMesa(MesaActivity mesaActivity, Mesa mesa)
{
super(mesaActivity.getContext());
setZOrderOnTop(true);
setWillNotDraw(false);
holder = getHolder();
holder.setFormat(PixelFormat.TRANSLUCENT);
isItOk = true;
t = new Thread(this);
t.start();
}
@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
/* Tapete */
try
{
dibujarTapete(canvas);
} catch (Exception e) {}
this.sentido = mesaActivity.getSentidoBitmap();
this.miIcono = mesaActivity.getMiIcono();
this.mazo = mesaActivity.getMazo();
/* Cartas A Robar */
try
{
dibujarCartasARobar(canvas);
} catch (Exception e) {dibujarCartasARobar(canvas);}
/* Sentido */
try
{
dibujarSentido(canvas);
} catch (Exception e) {}
/* Mi icono */
try
{
dibujarMiIcono(canvas);
} catch (Exception e) {}
//if (getMesa().isJuegoAcabado()) return;
boolean cond = mesa.isMiJugadorAcabo();
if (cond) return;
/*Cartas Tiradas */
try
{
dibujarCartasTiradas(canvas);
} catch (Exception e) {e.printStackTrace();}
/*Carta mesa */
try
{
dibujarCartaMesa(canvas);
} catch (Exception e) {}
/* Carta Tirada*/
try
{
dibujarCartaTirada(canvas);
} catch (Exception e) {}
/* Mazo */
try
{
dibujarMazo(canvas);
} catch (Exception e) {}
/* Repartiendo o robando*/
try
{
dibujarAnimacionRobarRepartir(canvas);
} catch (Exception e) {}
}
@SuppressLint("WrongCall")
@Override
public void run()
{
while (true)
{
// Dibujar
if (!holder.getSurface().isValid())continue;
if (!isItOk) continue;
Canvas c = holder.lockCanvas();
synchronized (holder) {
onDraw(c);
}
holder.unlockCanvasAndPost(c);
try {
Thread.sleep(5);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void pause ()
{
//isItOk = false;
}
public void resume ()
{
//isItOk = true;
}
}
如果您想在 SurfaceView 的表面上绘制,请不要覆盖 onDraw()
。
SurfaceView 有两个部分,Surface 和 View。 View 部分的工作方式与在 View class 的任何其他成员中一样,遵循通常的无效/重绘顺序。通常情况下,SurfaceView的View是一个透明孔,布局代码用它来留出空隙让Surface透过。
Surface 是一个完全独立的层,默认情况下位于 View 层的后面,但可以配置为在上面。它会忽略无效/刷新,在您解锁时更新(如果您使用的是 GLES,则交换 EGL 缓冲区)。因为没有与视图的交互 UI,您可以从专用渲染器线程更新表面。
你把两者混在一起了。您已经覆盖了 onDraw()
,就好像您正在创建一个 custom View,但您也在使用相同的功能渲染到 Surafce。
将 onDraw()
重命名为 doDraw()
并取消覆盖。或者,从 SurfaceView 切换到普通的自定义视图,并使用 postInvalidate()
.
驱动您的更新
Canvas 渲染到 SurfaceView Surface 不是硬件加速的,但 Canvas 在自定义 View 上绘制是。根据您的设备和您触摸的像素数量,使用自定义视图可能会更快。
您还可以通过使用较小的 Surface 并让硬件缩放它来加速 Surface 渲染。 (demo, blog post)
我正在尝试使用 SurfaceView 绘制一些东西,但似乎越来越慢,而不是使用 onDraw 并使 View 无效 Class。
所以我需要知道我是否可以让它更快。 这是我的代码。
public class ViewCentroMesa extends SurfaceView implements Runnable
{
// Bucle pintar
Thread t = null;
SurfaceHolder holder;
boolean isItOk = false;
public ViewCentroMesa(MesaActivity mesaActivity, Mesa mesa)
{
super(mesaActivity.getContext());
setZOrderOnTop(true);
setWillNotDraw(false);
holder = getHolder();
holder.setFormat(PixelFormat.TRANSLUCENT);
isItOk = true;
t = new Thread(this);
t.start();
}
@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
/* Tapete */
try
{
dibujarTapete(canvas);
} catch (Exception e) {}
this.sentido = mesaActivity.getSentidoBitmap();
this.miIcono = mesaActivity.getMiIcono();
this.mazo = mesaActivity.getMazo();
/* Cartas A Robar */
try
{
dibujarCartasARobar(canvas);
} catch (Exception e) {dibujarCartasARobar(canvas);}
/* Sentido */
try
{
dibujarSentido(canvas);
} catch (Exception e) {}
/* Mi icono */
try
{
dibujarMiIcono(canvas);
} catch (Exception e) {}
//if (getMesa().isJuegoAcabado()) return;
boolean cond = mesa.isMiJugadorAcabo();
if (cond) return;
/*Cartas Tiradas */
try
{
dibujarCartasTiradas(canvas);
} catch (Exception e) {e.printStackTrace();}
/*Carta mesa */
try
{
dibujarCartaMesa(canvas);
} catch (Exception e) {}
/* Carta Tirada*/
try
{
dibujarCartaTirada(canvas);
} catch (Exception e) {}
/* Mazo */
try
{
dibujarMazo(canvas);
} catch (Exception e) {}
/* Repartiendo o robando*/
try
{
dibujarAnimacionRobarRepartir(canvas);
} catch (Exception e) {}
}
@SuppressLint("WrongCall")
@Override
public void run()
{
while (true)
{
// Dibujar
if (!holder.getSurface().isValid())continue;
if (!isItOk) continue;
Canvas c = holder.lockCanvas();
synchronized (holder) {
onDraw(c);
}
holder.unlockCanvasAndPost(c);
try {
Thread.sleep(5);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void pause ()
{
//isItOk = false;
}
public void resume ()
{
//isItOk = true;
}
}
如果您想在 SurfaceView 的表面上绘制,请不要覆盖 onDraw()
。
SurfaceView 有两个部分,Surface 和 View。 View 部分的工作方式与在 View class 的任何其他成员中一样,遵循通常的无效/重绘顺序。通常情况下,SurfaceView的View是一个透明孔,布局代码用它来留出空隙让Surface透过。
Surface 是一个完全独立的层,默认情况下位于 View 层的后面,但可以配置为在上面。它会忽略无效/刷新,在您解锁时更新(如果您使用的是 GLES,则交换 EGL 缓冲区)。因为没有与视图的交互 UI,您可以从专用渲染器线程更新表面。
你把两者混在一起了。您已经覆盖了 onDraw()
,就好像您正在创建一个 custom View,但您也在使用相同的功能渲染到 Surafce。
将 onDraw()
重命名为 doDraw()
并取消覆盖。或者,从 SurfaceView 切换到普通的自定义视图,并使用 postInvalidate()
.
Canvas 渲染到 SurfaceView Surface 不是硬件加速的,但 Canvas 在自定义 View 上绘制是。根据您的设备和您触摸的像素数量,使用自定义视图可能会更快。
您还可以通过使用较小的 Surface 并让硬件缩放它来加速 Surface 渲染。 (demo, blog post)