Trong Android, nếu bạn muốn làm động một đối tượng và làm cho nó di chuyển một đối tượng từ location1 sang location2, API hoạt hình sẽ tìm ra các vị trí trung gian (tweening) và sau đó xếp hàng vào luồng chính các thao tác di chuyển thích hợp vào thời điểm thích hợp bằng cách sử dụng bộ hẹn giờ . Điều này hoạt động tốt ngoại trừ luồng chính thường được sử dụng cho nhiều thứ khác - vẽ, mở tệp, trả lời đầu vào của người dùng, v.v. Một bộ đếm thời gian xếp hàng thường có thể bị trì hoãn. Các chương trình được viết tốt sẽ luôn cố gắng thực hiện càng nhiều thao tác càng tốt trong các luồng nền (không phải chính) tuy nhiên bạn không thể luôn luôn tránh sử dụng luồng chính. Các hoạt động yêu cầu bạn hoạt động trên một đối tượng UI luôn phải được thực hiện trên luồng chính. Ngoài ra, nhiều API sẽ đưa các hoạt động trở lại luồng chính như một hình thức an toàn của luồng.
Tất cả các khung nhìn được vẽ trên cùng một luồng GUI cũng được sử dụng cho tất cả các tương tác của người dùng.
Vì vậy, nếu bạn cần cập nhật GUI nhanh chóng hoặc nếu việc kết xuất mất quá nhiều thời gian và ảnh hưởng đến trải nghiệm người dùng thì hãy sử dụng SurfaceView.
Ví dụ về hình ảnh xoay:
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);
}
}
}
}
}
Hoạt động:
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));
}
}