在线程中睡眠后Android的surfaceview / canvas闪烁

时间:2012-12-21 21:18:31

标签: android surfaceview

这是我在这里的第一篇文章。对不起,如果做得不好并提前感谢。

有些东西让我发疯。

我尝试绘制一些东西并在屏幕上慢慢显示。为此,我使用Thread.sleep,如代码中所示。但它在每次迭代中都显示了两个不同版本的画布。

有人可以解释什么是错的吗?

我只想画一些东西,几秒后画出别的东西。等等。

这是我的代码:

public class Vista extends SurfaceView implements Callback {
private Hilo hilo;
private SurfaceHolder sf;

class Hilo extends Thread {
    public boolean running;
    private Vista view;
    Canvas c = null;
    Bitmap btm = null;

    public Hilo(SurfaceHolder holder, Vista view) {
        sf = holder;
        btm = Bitmap.createBitmap(480, 800, Config.ARGB_8888);
        c = new Canvas(btm);
    }

    @Override
    public void run() {
        Paint paint = new Paint();
        paint.setStyle(Style.FILL_AND_STROKE);
        paint.setColor(Color.BLUE);

        int k = 0;
        while (running) {
            c = sf.lockCanvas();
            k+= 10;
            c.drawText(String.valueOf(k/10), k, 20, paint);
            sf.unlockCanvasAndPost(c);

          try {
              sleep(1000);
          } catch (InterruptedException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          }
        }
    }
}

public Vista(Context context) {
    super(context);
    SurfaceHolder holder = getHolder();
    holder.addCallback(this);
    hilo = new Hilo(holder, this);
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    // TODO Auto-generated method stub
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
    hilo.running = true;
    hilo.start();
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    boolean retry = true;
    hilo.running = false;
    while (retry) {
        try {
            hilo.join();
            retry = false;
        } catch (InterruptedException e) {
        }
    }
}

}

1 个答案:

答案 0 :(得分:0)

您的代码是sleep()主线程,也称为UI线程。这是你绝对不能做的事情,因为主线程负责处理所有"东西"在Android中:UI渲染,UI事件调度等。您可以阅读Android Developer网站上的Processes and Threads指南以获取更多信息。选择报价:

  

因此,Android的单线程模型只有两个规则:

     
      
  1. 不要阻止UI线程

  2.   
  3. 不要从UI线程外部访问Android UI工具包

  4.   

然后问题变成了,如何在不睡眠主线程的情况下为视图设置动画?诀窍是告诉Android去做其他事情并在一段时间后回到你身边(重绘你)。每次绘制时,都会计算推进动画的程度。

执行此操作的一种(粗略)方法是使用postInvalidateDelayed(long),它完全相同:在给定的毫秒数后重绘您的视图。这不是一个精确的延迟,它会稍微波动,所以你不能假设确切地说有多少时间过去了。一种方法是将System.nanoTime()存储在实例字段中,以便下次绘制时,您可以将差值调整为nanoTime()的新读数。这个差异是经过了多少时间,因此告诉您应该更新动画状态的程度。如果您的动画总共应该持续1秒,并且自上次绘制场景以来已经过了100毫秒,则必须将所有内容提前10%。

Android提供a lot of utilities以简化此操作。