我正在制作一个简单的2个图像旋转动画,一个在另一个上面(每个都有不同的速度)。我知道已经有一个动画API,但我需要使用这个。
效果很好,但有时,动画停止很短的时间然后继续,使其“跳跃”(在某些帧上保持比其他帧更多)。
为什么会发生?因为GC?我该怎么做才能避免它?我打算做一些后台操作,所以它可能会变得更慢。
我知道使用sleep()并不意味着线程会在给定时间后立即唤醒,但这太过分了,而且非常明显。
有什么技巧可以让它更顺畅吗?也许使用更好的选择?
这是代码(执行它的视图):
public class AnimView extends SurfaceView implements SurfaceHolder.Callback
{
int _angle;
private final Bitmap _bitmap;
private final Paint _paint =new Paint();
private AnimationThread _animationThread;
private Matrix _matrix;
private int _width;
private int _height;
public AnimView(final Context context)
{
super(context);
_bitmap=BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher);
_paint.setAntiAlias(true);
getHolder().addCallback(this);
}
public AnimView(final Context context,final AttributeSet attrs)
{
super(context,attrs);
_bitmap=BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher);
_paint.setAntiAlias(true);
getHolder().addCallback(this);
}
public AnimView(final Context context,final AttributeSet attrs,final int defStyle)
{
super(context,attrs,defStyle);
_bitmap=BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher);
_paint.setAntiAlias(true);
getHolder().addCallback(this);
}
@Override
public void surfaceChanged(final SurfaceHolder holder,final int format,final int width,final int height)
{
_width=width;
_height=height;
}
@Override
public void surfaceCreated(final SurfaceHolder holder)
{
if(isInEditMode())
return;
_matrix=new Matrix();
setWillNotDraw(false);
_animationThread=new AnimationThread();
_animationThread.start();
}
@Override
public void surfaceDestroyed(final SurfaceHolder holder)
{
_animationThread.cancelAnimation();
}
@Override
protected void onDraw(final Canvas canvas)
{
if(isInEditMode())
{
canvas.drawColor(0xffff0000);
return;
}
_paint.setAntiAlias(true);
_matrix.reset();
_matrix.postScale(_width/_bitmap.getWidth(),_height/_bitmap.getHeight());
_matrix.postRotate(_angle,_width/2,_height/2);
canvas.drawBitmap(_bitmap,_matrix,_paint);
_matrix.reset();
_matrix.postScale(_width/_bitmap.getWidth(),_height/_bitmap.getHeight());
_matrix.postRotate(_angle*2,_width/2,_height/2);
canvas.drawBitmap(_bitmap,_matrix,_paint);
}
private class AnimationThread extends Thread
{
private boolean _isRunning =true;
public AnimationThread()
{}
public void cancelAnimation()
{
_isRunning=false;
}
@Override
public void run()
{
while(_isRunning)
{
postInvalidate();
refreshDrawableState();
try
{
sleep(5);
}
catch(final InterruptedException e)
{
e.printStackTrace();
}
_angle=(_angle+1)%360;
}
}
}
}
答案 0 :(得分:0)
尝试这样的事情
@Override
public void run()
{
long last = System.currentTimeMillis();
long currentTime = last;
long frameTime = 40;
while(_isRunning)
{
currentTime = System.currentTimeMillis();
if(currentTime - last > frameTime){
postInvalidate();
refreshDrawableState();
//I FORGOT THIS
last = currentTime;
}
try
{
sleep(5);
}
catch(final InterruptedException e)
{
e.printStackTrace();
}
_angle=(_angle+1)%360;
}
}
}
这样您每40毫秒刷新一次屏幕并每隔5毫秒更新一次您的位置。这只是一个部分,您可以设置矩阵更新和计算也不在绘图部分,这也将提高您的速度。你对实际绘制时间的计算越少,它就越快。
编辑:看看这个
public class AnimView extends SurfaceView implements SurfaceHolder.Callback {
int _angle;
private final Bitmap _bitmap;
private final Paint _paint = new Paint();
private AnimationThread _animationThread;
private Matrix _matrix;
private int _width = 100;
private int _height = 100;
private Bitmap backBitmap;
private Canvas backCanvas;
public AnimView(final Context context) {
super(context);
_bitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.ic_launcher);
_paint.setAntiAlias(true);
getHolder().addCallback(this);
}
public AnimView(final Context context, final AttributeSet attrs) {
super(context, attrs);
_bitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.ic_launcher);
_paint.setAntiAlias(true);
getHolder().addCallback(this);
}
public AnimView(final Context context, final AttributeSet attrs,
final int defStyle) {
super(context, attrs, defStyle);
_bitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.ic_launcher);
_paint.setAntiAlias(true);
getHolder().addCallback(this);
}
@Override
public void surfaceChanged(final SurfaceHolder holder, final int format,
final int width, final int height) {
_width = width;
_height = height;
createImage();
}
@Override
public void surfaceCreated(final SurfaceHolder holder) {
if (isInEditMode())
return;
_matrix = new Matrix();
setWillNotDraw(false);
_animationThread = new AnimationThread();
_animationThread.start();
}
@Override
public void surfaceDestroyed(final SurfaceHolder holder) {
_animationThread.cancelAnimation();
}
@Override
protected void onDraw(final Canvas canvas) {
if (isInEditMode() || backBitmap == null) {
canvas.drawColor(0xffff0000);
return;
}
canvas.drawBitmap(backBitmap, 0, 0, _paint);
}
private class AnimationThread extends Thread {
private boolean _isRunning = true;
public AnimationThread() {
}
public void cancelAnimation() {
_isRunning = false;
}
@Override
public void run() {
long last = System.currentTimeMillis();
long currentTime = last;
long frameTime = 40;
long updateTime = 20;
boolean updated = false;
while (_isRunning) {
currentTime = System.currentTimeMillis();
if (currentTime - last > frameTime) {
postInvalidate();
refreshDrawableState();
last = currentTime;
updated = false;
}
else if(currentTime - last > updateTime){
if(!updated){
drawImage();
updated = true;
}
}
try {
sleep(5);
} catch (final InterruptedException e) {
e.printStackTrace();
}
_angle = (_angle + 1) % 360;
}
}
}
private void createImage(){
backBitmap = Bitmap.createBitmap(_width, _height, Config.ARGB_8888);
backCanvas = new Canvas();
backCanvas.setBitmap(backBitmap);
}
private void drawImage(){
backCanvas.drawRGB(0, 0, 0);
_paint.setAntiAlias(true);
_matrix.reset();
_matrix.postScale(_width / _bitmap.getWidth(),
_height / _bitmap.getHeight());
_matrix.postRotate(_angle, _width / 2, _height / 2);
backCanvas.drawBitmap(_bitmap, _matrix, _paint);
_matrix.reset();
_matrix.postScale(_width / _bitmap.getWidth(),
_height / _bitmap.getHeight());
_matrix.postRotate(_angle * 2, _width / 2, _height / 2);
backCanvas.drawBitmap(_bitmap, _matrix, _paint);
}
}
希望这有助于并享受您的工作