Java Android surfaceview冻结
我想在surfaceview上创建动画。 下面是一个表面视图:Java Android surfaceview冻结,java,android,surfaceview,Java,Android,Surfaceview,我想在surfaceview上创建动画。 下面是一个表面视图: public class AnimationSurfaceView extends SurfaceView implements SurfaceHolder.Callback{ private AnimationWorker animationWorker; private GestureDetectorCompat mGestureDetector; private OverScroller mScroller; private
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);
}
}
}
public类AnimationWorker扩展线程{
私有静态最终字符串LOG_TAG=AnimationWorker.class.getSimpleName();
公共静态最终对象syncObj=新对象();
私有布尔runFlag=false;
私人地勤人员地勤人员;
私人语境;
私有阻塞队列;
私有游标mCursor;
私有AnimationImageCacheHelper AnimationImageCacheHelper;
私有最终字符串ASSET_SUFFIX=“assets://”;
私有最终字符串FILE_SUFFIX=“FILE://”;
直截了当;
Rect-bitmapRect;
油漆;
成对位图;
int mLeftIndex;
int-mRightIndex;
专用最终浮动轨道长度=720f;
私人最终浮动最大值α=255f;
公共动画工作者(
浮雕浮雕浮雕,
语境,
光标(光标){
超级();
this.surfaceHolder=surfaceHolder;
this.animationImageCacheHelper=新的animationImageCacheHelper();
bitmapRect=new Rect();
油漆=新油漆();
clipRect=new Rect();
队列=新的LinkedBlockingDeque();
}
公共void setRunning(布尔运行){
runFlag=run;
}
public void postTask(AnimationTask任务){
试一试{
queue.put(任务);
}捕获(例外e){
//无所事事
}
}
public void cancelTaskQueue(){
queue.clear();
}
@凌驾
公开募捐{
while(runFlag){
Log.e(Log_标签,“running”);
试一试{
AnimationTask=queue.remove();
如果(任务!=null){
processTask(任务);
}
}捕获(例外e){
试一试{
已同步(syncObj){
syncObj.wait();
}
}捕捉(中断异常e1){
e1.printStackTrace();
}
Log.e(Log_标签,“异常”);
e、 printStackTrace();
}
}
}
私有void处理任务(AnimationTask任务){
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());
如果(mLeftIndex!=左索引| | mRightIndex!=右索引){
位图=获取位图(leftIndex、rightIndex、task.direction);
}
float alpha=(MAX_alpha/TRACK_LENTH*task.currentPosition)%MAX_alpha;
绘制(位图。第一,位图。第二,alpha);
}
私有对GetBitmap(int-leftIndex、int-rightIndex、int-direction){
最终位图前景位图;
最终位图背景位图;
最终配对结果;
如果(方向==1){
//正上方
if(mCursor.moveToPosition(leftIndex)){
String backgroundImageUrl=mCursor.getString(mCursor.getColumnIndex(PhotoContract.PhotoEntry.COLUMN_PHOTO_URL));
backgroundBitmap=loadImage(backgroundImageUrl);
}否则{
背景位图=空;
}
if(mCursor.moveToPosition(右索引)){
String foregroundImageUrl=mCursor.getString(mCursor.getColumnIndex(PhotoContract.PhotoEntry.COLUMN_PHOTO_URL));
foregroundBitmap=loadImage(foregroundImageUrl);
}否则{
foregroundBitmap=null;
}
}否则{
//左上角
if(mCursor.moveToPosition(右索引)){
String backgroundImageUrl=mCursor.getString(mCursor.getColumnIndex(PhotoContract.PhotoEntry.COLUMN_PHOTO_URL));
backgroundBitmap=loadImage(backgroundImageUrl);
}否则{
背景位图=空;
}
if(mCursor.moveToPosition(leftIndex)){
String foregroundImageUrl=mCursor.getString(mCursor.getColumnIndex(PhotoContract.PhotoEntry.COLUMN_PHOTO_URL));
foregroundBitmap=loadImage(foregroundImageUrl);
}否则{
foregroundBitmap=null;
}
}
结果=新的一对(前景位图、背景位图);
返回结果;
}
私有位图加载图像(字符串uri){
if(animationImageCacheHelper.isImageContains(uri)){
返回animationImageCacheHelper.getBitmap(uri);
}
if(uri.startsWith(资产后缀)){
位图位图=ImageLoader.getInstance().loadImageSync(uri);
animationImageCacheHelper.put(uri,位图);
返回位图;
}否则{
位图位图=ImageLoader.getInstance().loadImageSync(“文件:/”+uri);
animationImageCacheHelper.put(uri,位图);
返回位图;
}
}
专用空心绘制(位图前景、位图背景、浮点alpha){
帆布;
canvas=null;
试一试{
canvas=surfaceHolder.lockCanvas(null);
canvas.getClipBounds(clipRect);
已同步(surfaceHolder){
//画背景
油漆。setAlpha(255);
bitmapRect.set(0,0,background.getWidth(),background.getHeight());
画布.drawBitmap(背景、bitmapRect、clipRect、绘画);
//画前景
paint.setAlpha((int)alpha);
bitmapRect.set(0,0,前台.getWidth(),前台.getHeight());
画布.drawBitmap(前景、位图矩形、clipRect、绘制);
}
}最后{
if(canvas!=null){
surfaceHolder.unlockCanvasAndPost(画布);
}
}
}
}
我正在收听“接触”事件,并为员工添加任务(当前位置和方向)。工作者必须从队列中获取任务并绘制当前状态。
在我的版本中,什么都没有发生。Surfaceview freeezes,我需要从我的设备中拔出电池来解锁它
*注意:我尝试使用
队列。take()
-但我得到了相同的结果如果您必须从设备中取出电池,您的问题不会浮出水面查看。“主页”按钮应始终有效。你使用的是什么设备,什么版本的Android?(另一方面,为什么要在surfaceHolder上同步…?)@