No Android, se você deseja animar um objeto e fazê-lo mover um objeto de location1 para location2, a API de animação descobre os locais intermediários (interpolação) e enfileira no thread principal as operações de movimentação apropriadas nos horários apropriados, usando um timer . Isso funciona bem, exceto que o encadeamento principal geralmente é usado para muitas outras coisas - pintura, abertura de arquivos, resposta às entradas do usuário etc. Um timer em fila geralmente pode ser atrasado. Programas bem escritos sempre tentarão realizar o maior número possível de operações em threads em segundo plano (não principais), mas nem sempre é possível evitar o uso da thread principal. As operações que exigem que você opere em um objeto de interface do usuário sempre precisam ser realizadas no encadeamento principal. Além disso, muitas APIs direcionarão as operações de volta para o thread principal como uma forma de segurança de thread.
As visualizações são todas desenhadas no mesmo encadeamento da GUI, que também é usado para toda a interação do usuário.
Portanto, se você precisar atualizar a GUI rapidamente ou se a renderização demorar muito e afetar a experiência do usuário, use o SurfaceView.
Exemplo de imagem de rotação:
public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback {
private DrawThread drawThread;
public MySurfaceView(Context context) {
super(context);
getHolder().addCallback(this);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
drawThread = new DrawThread(getHolder(), getResources());
drawThread.setRunning(true);
drawThread.start();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
drawThread.setRunning(false);
while (retry) {
try {
drawThread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
}
class DrawThread extends Thread{
private boolean runFlag = false;
private SurfaceHolder surfaceHolder;
private Bitmap picture;
private Matrix matrix;
private long prevTime;
public DrawThread(SurfaceHolder surfaceHolder, Resources resources){
this.surfaceHolder = surfaceHolder;
picture = BitmapFactory.decodeResource(resources, R.drawable.icon);
matrix = new Matrix();
matrix.postScale(3.0f, 3.0f);
matrix.postTranslate(100.0f, 100.0f);
prevTime = System.currentTimeMillis();
}
public void setRunning(boolean run) {
runFlag = run;
}
@Override
public void run() {
Canvas canvas;
while (runFlag) {
long now = System.currentTimeMillis();
long elapsedTime = now - prevTime;
if (elapsedTime > 30){
prevTime = now;
matrix.preRotate(2.0f, picture.getWidth() / 2, picture.getHeight() / 2);
}
canvas = null;
try {
canvas = surfaceHolder.lockCanvas(null);
synchronized (surfaceHolder) {
canvas.drawColor(Color.BLACK);
canvas.drawBitmap(picture, matrix, null);
}
}
finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
}
}
atividade:
public class SurfaceViewActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new MySurfaceView(this));
}
}