Android surfaceview冻结

时间:2014-12-29 14:01:51

标签: java android surfaceview

我想在surfaceview上创建动画。 这是一个表面视图:

public class AnimationSurfaceView extends SurfaceView implements SurfaceHolder.Callback{

private AnimationWorker animationWorker;
private GestureDetectorCompat mGestureDetector;
private OverScroller mScroller;
private Cursor mCursor;
private int pIndexA, pIndexB;
private int dir;

private float posX=0;

public AnimationSurfaceView(Context context, Cursor cursor) {
    super(context);
    getHolder().addCallback(this);
    mCursor = cursor;
    mGestureDetector = new GestureDetectorCompat(context, mGestureListener);
    mScroller = new OverScroller(context);
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
    animationWorker = new AnimationWorker(getHolder(), getContext(), null);
    animationWorker.setRunning(true);
    animationWorker.run();
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    boolean retry = true;
    animationWorker.setRunning(false);
    animationWorker.postTask(null);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    Log.e("sfsfsfdf", "Работает1!!!!!!!!!!!!!!!!!!!");
    boolean retVal = mGestureDetector.onTouchEvent(event);
    return retVal || super.onTouchEvent(event);

}

@Override
public void computeScroll() {
    super.computeScroll();
    if(mCursor != null){
        int i1 = Math.max(0,Math.min(mCursor.getCount()-1, (int)Math.floor(posX/720f)));
        int i2 = Math.max(0,Math.min(mCursor.getCount()-1, (int)Math.ceil(posX/720f)));
        if(i1 != pIndexA){
            dir = i1-pIndexA;
            pIndexA = i1;
            pIndexB = i2;
        }
    }
}

private void updateWorker(){
    animationWorker.postTask(new AnimationTask(posX, dir));
    AnimationWorker.syncObj.notifyAll();
}

private final GestureDetector.SimpleOnGestureListener mGestureListener
        = new GestureDetector.SimpleOnGestureListener() {


    @Override
    public boolean onDown(MotionEvent e) {
        mScroller.forceFinished(true);
        animationWorker.cancelTaskQueue();
        return true;
    }

    @Override
    public boolean onDoubleTap(MotionEvent e) {
        return true;
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2,
                            float distanceX, float distanceY) {
        posX += -distanceX;
        updateWorker();
        return true;
    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                           float velocityY) {
        velocityX = - velocityX;
        fling(velocityX);
        return true;
    }

    private void fling(float velocity){
        mScroller.forceFinished(true);
        mScroller.fling((int) posX, 0, (int) -velocity, 0, 0, 720 * (mCursor != null ? mCursor.getCount() : 1), 0, 0);
        updateWorker();
    }
};

这是一名工人:

public class AnimationWorker extends Thread {

private static final String LOG_TAG = AnimationWorker.class.getSimpleName();
public static final Object syncObj = new Object();

private boolean runFlag = false;
private SurfaceHolder surfaceHolder;
private Context context;
private BlockingQueue<AnimationTask> queue;
private Cursor mCursor;
private AnimationImageCacheHelper animationImageCacheHelper;
private final String ASSET_SUFFIX = "assets://";
private final String FILE_SUFFIX = "file://";

Rect clipRect;
Rect bitmapRect;
Paint paint;
Pair<Bitmap, Bitmap> bitmaps;
int mLeftIndex;
int mRightIndex;

private final Float TRACK_LENTH = 720f;
private final Float MAX_ALPHA = 255f;

public AnimationWorker(
        SurfaceHolder surfaceHolder,
        Context context,
        Cursor cursor){
    super();
    this.surfaceHolder = surfaceHolder;
    this.animationImageCacheHelper = new AnimationImageCacheHelper();
    bitmapRect = new Rect();
    paint = new Paint();
    clipRect = new Rect();
    queue = new LinkedBlockingDeque<AnimationTask>();
}

public void setRunning(boolean run){
    runFlag = run;
}

public void postTask(AnimationTask task){
    try {
        queue.put(task);
    }catch (Exception e){
        //do nothing
    }
}

public void cancelTaskQueue(){
    queue.clear();
}

@Override
public void run() {

    while(runFlag){
        Log.e(LOG_TAG, "running");
        try {
            AnimationTask task = queue.remove();
            if(task != null) {
                processTask(task);
            }
        }catch(Exception e){
            try {
                synchronized (syncObj) {
                    syncObj.wait();
                }
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
            Log.e(LOG_TAG, "exception");
            e.printStackTrace();
        }
    }
}

private void processTask(AnimationTask task){
    int leftIndex = Math.max(0,Math.min(mCursor.getCount()-1, (int)Math.floor(task.currentPosition/TRACK_LENTH.intValue())));
    int rightIndex = Math.max(0,Math.min(mCursor.getCount()-1, (int)Math.ceil(task.currentPosition/TRACK_LENTH.intValue())));
    if(mLeftIndex != leftIndex || mRightIndex != rightIndex){
        bitmaps = getBitmaps(leftIndex, rightIndex, task.direction);
    }
    float alpha = (MAX_ALPHA / TRACK_LENTH * task.currentPosition) % MAX_ALPHA;
    draw(bitmaps.first, bitmaps.second, alpha);
}

private Pair<Bitmap, Bitmap> getBitmaps(int leftIndex, int rightIndex, int direction){
    final Bitmap foregroundBitmap;
    final Bitmap backgroundBitmap;
    final Pair<Bitmap, Bitmap> result;
    if(direction == 1) {
        //right on top
        if(mCursor.moveToPosition(leftIndex)){
            String backgroundImageUrl = mCursor.getString(mCursor.getColumnIndex(PhotoContract.PhotoEntry.COLUMN_PHOTO_URL));
            backgroundBitmap = loadImage(backgroundImageUrl);
        }else{
            backgroundBitmap = null;
        }
        if (mCursor.moveToPosition(rightIndex)){
            String foregroundImageUrl = mCursor.getString(mCursor.getColumnIndex(PhotoContract.PhotoEntry.COLUMN_PHOTO_URL));
            foregroundBitmap = loadImage(foregroundImageUrl);
        }else{
            foregroundBitmap = null;
        }
    } else {
        //left on top
        if(mCursor.moveToPosition(rightIndex)){
            String backgroundImageUrl = mCursor.getString(mCursor.getColumnIndex(PhotoContract.PhotoEntry.COLUMN_PHOTO_URL));
            backgroundBitmap = loadImage(backgroundImageUrl);
        }else{
            backgroundBitmap = null;
        }
        if (mCursor.moveToPosition(leftIndex)){
            String foregroundImageUrl = mCursor.getString(mCursor.getColumnIndex(PhotoContract.PhotoEntry.COLUMN_PHOTO_URL));
            foregroundBitmap = loadImage(foregroundImageUrl);
        }else{
            foregroundBitmap = null;
        }
    }
    result = new Pair<Bitmap, Bitmap>(foregroundBitmap, backgroundBitmap);
    return result;
}

private Bitmap loadImage(String uri){
    if(animationImageCacheHelper.isImageContains(uri)){
        return animationImageCacheHelper.getBitmap(uri);
    }
    if (uri.startsWith(ASSET_SUFFIX)) {
        Bitmap bitmap = ImageLoader.getInstance().loadImageSync(uri);
        animationImageCacheHelper.put(uri, bitmap);
        return bitmap;
    } else {
        Bitmap bitmap = ImageLoader.getInstance().loadImageSync("file://" + uri);
        animationImageCacheHelper.put(uri, bitmap);
        return bitmap;
    }
}

private void draw(Bitmap foreground, Bitmap background, float alpha){
    Canvas canvas;
    canvas = null;
    try {
        canvas = surfaceHolder.lockCanvas(null);
        canvas.getClipBounds(clipRect);
        synchronized (surfaceHolder) {
            //draw background
            paint.setAlpha(255);
            bitmapRect.set(0, 0, background.getWidth(), background.getHeight());
            canvas.drawBitmap(background, bitmapRect, clipRect, paint);

            //draw foreground
            paint.setAlpha((int)alpha);
            bitmapRect.set(0, 0, foreground.getWidth(), foreground.getHeight());
            canvas.drawBitmap(foreground, bitmapRect, clipRect, paint);
        }
    }finally {
        if (canvas != null) {
            surfaceHolder.unlockCanvasAndPost(canvas);
        }
    }
}

}

我正在收听 onTouch 事件,并为工作人员添加任务(当前位置和方向)。工作人员必须从队列中获取任务并绘制当前状态。 在我的版本中没有任何反应Surfaceview会冻结,我需要从我的设备中取出电池来解锁它。

*注意:我尝试使用queue.take() - 但我得到的结果相同

0 个答案:

没有答案