Wenn Sie in Android ein Objekt animieren und von Objekt1 zu Standort2 verschieben möchten, ermittelt die Animations-API die Zwischenpositionen (Tweening) und stellt die entsprechenden Verschiebungsvorgänge zu den entsprechenden Zeiten mithilfe eines Timers in den Hauptthread . Dies funktioniert einwandfrei, außer dass der Haupt-Thread normalerweise für viele andere Dinge verwendet wird - Malen, Öffnen von Dateien, Reagieren auf Benutzereingaben usw. Ein Timer in der Warteschlange kann häufig verzögert werden. Gut geschriebene Programme versuchen immer, so viele Operationen wie möglich in Hintergrundthreads (nicht Hauptthreads) auszuführen. Sie können jedoch nicht immer vermeiden, den Hauptthread zu verwenden. Vorgänge, bei denen Sie ein UI-Objekt bearbeiten müssen, müssen immer im Hauptthread ausgeführt werden. Außerdem leiten viele APIs Operationen als eine Form der Thread-Sicherheit zurück zum Haupt-Thread.
Alle Ansichten werden auf demselben GUI-Thread gezeichnet, der auch für alle Benutzerinteraktionen verwendet wird.
Wenn Sie also die GUI schnell aktualisieren müssen oder wenn das Rendern zu lange dauert und die Benutzererfahrung beeinträchtigt, verwenden Sie SurfaceView.
Beispiel für ein Rotationsbild:
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);
}
}
}
}
}
Aktivität:
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));
}
}