0
我需要加載保存在drawable中的汽車的不同圖像,以便模擬360度旋轉,當用戶拖動視圖時我已經設置了拖動距離,加載下一幀。我正在使用曲面視圖並在畫布上繪製圖像。由於圖像太大,我無法一次將所有圖像加載到內存中,因此我通過僅將當前圖像保留在內存中來實時加載圖像。但是這種方法太慢了。任何人都可以指出我做錯了什麼嗎?或任何其他更好的方式來實現相同。謝謝你的幫助。在SurfaceView中加載圖像時發生的問題
這是我的代碼
/** * @author rajeshcp *類充當在視圖中頂視圖 *層次爲CarDetailsActivity * @Since 2013年2月13日 */
public class VirtualView extends SurfaceView implements SurfaceHolder.Callback, OnTouchListener, TweenListener {
private final int frame_width = 1024;
private final int frame_height = 462;
private InteractionListener mInteractionListener;
private final int mSnapVelocity = 1000;
private VelocityTracker mVelocityTracker;
protected int mTouchSlop;
private int mMaxVelocity;
private Rect mViewArea;
private IQTweener mValueanimator;
private ColorVariationVO mColorVariationVO;
/**************Indicates the current frame*********************/
private int mCurrentFrameIndex;
/**********Initial touch x coordinate**************/
private int mInitialTouchX;
/***********The drag distance for frame change***********/
private int mDragInterWell = 10;
private final int mTotalFrames = 36;
protected final int mMaxFrameSkip = 3;
/**************Identity matrix**********************/
private Matrix mIdentityMatrix;
private Paint mPaint;
/*********The bitmap to be drawn over the canvas*********/
private Bitmap mCurrentFrame;
private ViewUpdater mViewUpdater;
/*++++++++++++++++++++++++++++++++++++++++++++++*/
/*+++++++++++++Getters and Setters++++++++++++++*/
/*++++++++++++++++++++++++++++++++++++++++++++++*/
/**
* @param of type null
* @return mColorVariationVO of type ColorVariationVO
* getter function for mColorVariationVO
* @since Feb 13, 2013
* @author rajeshcp
*/
public ColorVariationVO getmColorVariationVO() {
return mColorVariationVO;
}
/**
* @param mColorVariationVO of type ColorVariationVO
* @return of type null
* setter function for mColorVariationVO
* @since Feb 13, 2013
* @author rajeshcp
*/
public void setmColorVariationVO(ColorVariationVO mColorVariationVO) {
this.mColorVariationVO = mColorVariationVO;
loadNextFrame();
}
/**
* @param context of type Context
* @return of type VirtualView
* Constructor function
* @since Feb 13, 2013
* @author rajeshcp
*/
public VirtualView(Context context) {
super(context);
init();
}
/**
* @param context of type Context
* @param attrs of type AttributeSet
* @return of type VirtualView
* Constructor function
* @since Feb 13, 2013
* @author rajeshcp
*/
public VirtualView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
/**
* @param context of type Context
* @param attrs of type AttributeSet
* @param defStyle of type int
* @return of type VirtualView
* Constructor function
* @since Feb 13, 2013
* @author rajeshcp
*/
public VirtualView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
/**
* @param of type null
* @return of type null
* function which will initialize the values for the view
* @since 13 Feb 2013
*/
private void init()
{
setZOrderOnTop(true);
getHolder().setFormat(PixelFormat.TRANSPARENT);
mPaint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG | Paint.ANTI_ALIAS_FLAG);
mIdentityMatrix = new Matrix();
mCurrentFrameIndex = 0;
mViewUpdater = new ViewUpdater();
mInteractionListener = new InteractionListener();
final ViewConfiguration configuration = ViewConfiguration.get(getContext());
mTouchSlop = configuration.getScaledTouchSlop();
mMaxVelocity = configuration.getScaledMaximumFlingVelocity();
getHolder().addCallback(this);
setOnTouchListener(this);
setLayerType(View.LAYER_TYPE_HARDWARE, mPaint);
}
/**
* @param direction of type int
* @return of type null
* function which will change the current frame index
* @since Feb 13, 2013
* @author rajeshcp
*/
private void initiateFrameChange(final int direction)
{
mCurrentFrameIndex += Math.max(-mMaxFrameSkip, Math.min(mMaxFrameSkip, direction));
if(mCurrentFrameIndex > (mTotalFrames - 1))
{
mCurrentFrameIndex = (mCurrentFrameIndex % (mTotalFrames - 1));
}else if(mCurrentFrameIndex < 0)
{
mCurrentFrameIndex = (mTotalFrames - 1) + (mCurrentFrameIndex % (mTotalFrames - 1));
}
loadNextFrame();
}
/**
* @param index of type int
* @return of type Bitmap
* function which will create the bitmap form the
* resources
* @since Feb 13, 2013
* @author rajeshcp
*/
@SuppressLint("UseSparseArrays")
private Bitmap getFrame(final int index)
{
Bitmap bitmap = null;
if(mColorVariationVO != null)
{
final int drawableId = getResourceId(index);
try
{
bitmap = BitmapFactory.decodeResource(getResources(), drawableId);
}catch (Exception e) {
Log.d(getClass().getName(), e.getLocalizedMessage());
}
}
return bitmap;
}
/**
* @param index of type int
* @return of type int
* function which create the resource id
* from index
* @since Feb 18, 2013
* @author rajeshcp
*/
private int getResourceId(final int index)
{
final String frameName = mColorVariationVO.getmCarAssetPath() + "_" + index;
int drawableId = 0;
try {
@SuppressWarnings("rawtypes")
Class res = R.drawable.class;
Field field = res.getField(frameName);
drawableId = field.getInt(null);
}
catch (Exception e) {
Log.e(getClass().getName(), "Failure to get drawable id.", e);
}
return drawableId;
}
/* (non-Javadoc)
* @see android.view.View#onDraw(android.graphics.Canvas)
* @since Feb 13, 2013
* @author rajeshcp
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(mCurrentFrame != null && canvas != null)
{
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
mIdentityMatrix.reset();
// mPaint.setStyle(Paint.Style.STROKE);
// mPaint.setStrokeWidth(1);
// mPaint.setColor(Color.MAGENTA);
// mPaint.setTextSize(100);
//
// canvas.drawText(String.valueOf(mCurrentFrameIndex), (getWidth()/(mTotalFrames - 1)) * mCurrentFrameIndex, (getHeight() - 100)/2, mPaint);
mIdentityMatrix.postTranslate(getWidth() - frame_width, (getHeight() - frame_height)/2);
canvas.drawBitmap(mCurrentFrame, mIdentityMatrix, mPaint);
}
}
/* (non-Javadoc)
* @see android.view.SurfaceHolder.Callback#surfaceChanged(android.view.SurfaceHolder, int, int, int)
* @since Feb 13, 2013
* @author rajeshcp
*/
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
/* (non-Javadoc)
* @see android.view.SurfaceHolder.Callback#surfaceCreated(android.view.SurfaceHolder)
* @since Feb 13, 2013
* @author rajeshcp
*/
@Override
public void surfaceCreated(SurfaceHolder holder) {
if(mViewArea == null)
{
int top = (getHeight() - frame_height)/2;
int left = getWidth() - frame_width;
mViewArea = new Rect(left, top, frame_width + left, frame_height + top);
}
mDragInterWell = (int)(mViewArea.width()/(2 * mTotalFrames));
if(mViewUpdater == null)
{
init();
}
mViewUpdater.start();
mInteractionListener.start();
}
/* (non-Javadoc)
* @see android.view.SurfaceHolder.Callback#surfaceDestroyed(android.view.SurfaceHolder)
* @since Feb 13, 2013
* @author rajeshcp
*/
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if(mViewUpdater != null)
{
mViewUpdater.setRun(false);
mViewUpdater = null;
mInteractionListener.mIsRunning = false;
mInteractionListener = null;
}
}
private boolean isScrolled = false;
/* (non-Javadoc)
* @see android.view.View.OnTouchListener#onTouch(android.view.View, android.view.MotionEvent)
* @since Feb 13, 2013
* @author rajeshcp
*/
@Override
public boolean onTouch(View v, MotionEvent event) {
mInteractionListener.queueEvent(event);
return true;
}
/**
* @param velocity of type int
* @return of type null
* function which will initiate the
* fling animation
* @since Feb 15, 2013
* @author rajeshcp
*/
private void initiateFling(int velocity)
{
return;
// int maxDuration = mMaxFrameSkip * mSnapVelocity;
// velocity = Math.max(-maxDuration, Math.min(maxDuration, velocity));
// int end = ((int)(velocity/mSnapVelocity)) * mTotalFrames;
//
// if(mValueanimator == null)
// {
// mValueanimator = new IQTweener(mCurrentFrameIndex, mTotalFrames - 1);
// mValueanimator.setmListener(this);
// }
// mValueanimator.setMduration(2000);
// mValueanimator.setmStart(mCurrentFrameIndex);
// mValueanimator.setmEnd(end);
// mValueanimator.start();
}
/**
* @param of type null
* @return of type null
* function which will clear
* the touch values
* @since Feb 15, 2013
* @author rajeshcp
*/
private void onTouchEnd()
{
isScrolled = false;
mVelocityTracker.clear();
mVelocityTracker.recycle();
mVelocityTracker = null;
mInitialTouchX = 0;
}
/* (non-Javadoc)
* @see com.inkoniq.iqpromomultitouch.animations.IQTweener.TweenListener#onUpdate(java.lang.Object)
* @since Feb 15, 2013
* @author rajeshcp
*/
@Override
public void onUpdate(float mCurrent) {
final int mIndex = (int) mCurrent;
if(mIndex > (mTotalFrames - 1))
{
mCurrentFrameIndex = (mIndex % (mTotalFrames - 1));
}else if(mIndex < 0)
{
mCurrentFrameIndex = (mTotalFrames - 1) + (mIndex % (mTotalFrames - 1));
}
}
/**
* @param of type null
* @return of type null
* function which will load the next frame from local storage
* @since Feb 13, 2013
* @author rajeshcp
*/
private void loadNextFrame()
{
final Bitmap frame = getFrame(mCurrentFrameIndex);
if(mCurrentFrame != null)
{
Bitmap temp = mCurrentFrame;
mCurrentFrame = frame;
temp.recycle();
temp = null;
}else
{
mCurrentFrame = frame;
}
}
/**
* @author rajeshcp
* class which will take care of updating the view
* @since 13 Feb 2013
*/
private class ViewUpdater extends Thread
{
private SurfaceHolder surface;
private boolean run = true;
/**
* @param run of type boolean
* @return of type null
* setter function for run
* @since 13 Feb 2013
*/
public void setRun(boolean run) {
this.run = run;
}
/**
* @param surface of type SurfaceHolder
* @param gameView of type GameView
* Constructor function
* @since 13 Feb 2013
*/
public ViewUpdater()
{
}
/*
* (non-Javadoc)
* @see java.lang.Thread#run()
* @since Feb 13, 2013
* @author rajeshcp
*/
@Override
public void run() {
Canvas canvas;
while (run) {
canvas = null;
try {
surface = getHolder();
canvas = surface.lockCanvas(null);
synchronized (surface) {
onDraw(canvas);
}
} finally {
if (canvas != null) {
surface.unlockCanvasAndPost(canvas);
}
}
}
}
}
/**
* @author rajeshcp
* Class which will handle the touch
* events
* @since 19 Feb 2013
*/
private class InteractionListener extends Thread
{
ArrayList<MotionEvent> mEventQueue;
boolean mIsRunning = false;
/**
* @param of type null
* @return of type InteractionListener
* Constructor function
* @since Feb 19, 2013
* @author rajeshcp
*/
public InteractionListener()
{
init();
}
/**
* @param of type null
* @return of type null
* @since Feb 19, 2013
* @author rajeshcp
*/
private void init()
{
mIsRunning = true;
mEventQueue = new ArrayList<MotionEvent>();
}
/**
* @param event of type MotionEvent
* @return of type null
* function which will add the event to
* the mEventQueue
* @since Feb 19, 2013
* @author rajeshcp
*/
private void queueEvent(MotionEvent event)
{
mEventQueue.add(event);
}
/**
* @param event of type MotionEvent
* @return of type null
* function which will process the touch event
* @since Feb 19, 2013
* @author rajeshcp
*/
private void onTouch(MotionEvent event) {
if(event == null)
return;
if(mVelocityTracker == null)
{
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(event);
if(!mViewArea.contains((int)event.getX(), (int)event.getY()))
{
return;
}
switch(event.getAction())
{
case MotionEvent.ACTION_DOWN :
{
if(mValueanimator != null)
{
mValueanimator.cancel();
}
isScrolled = false;
mInitialTouchX = (int)event.getX();
break;
}
case MotionEvent.ACTION_MOVE :
{
final int currentX = (int)event.getX();
final int draggedDistance = (currentX - mInitialTouchX);
if(draggedDistance != 0 && draggedDistance % mDragInterWell == 0)
{
isScrolled = true;
initiateFrameChange(draggedDistance/mDragInterWell);
Log.d(getClass().getName(), "frameIndex = " + mCurrentFrameIndex);
mInitialTouchX = currentX;
}
break;
}
case MotionEvent.ACTION_UP :
{
if(isScrolled)
{
final VelocityTracker velocityTracker = mVelocityTracker;
velocityTracker.computeCurrentVelocity(1000, mMaxVelocity);
int velocityX = (int) velocityTracker.getXVelocity();
if((velocityX > mSnapVelocity) || (velocityX < -mSnapVelocity))
{
initiateFling(velocityX);
}
}
onTouchEnd();
break;
}
case MotionEvent.ACTION_CANCEL :
{
onTouchEnd();
break;
}
default :
{
break;
}
}
}
/* (non-Javadoc)
* @see java.lang.Thread#run()
* @since Feb 19, 2013
* @author rajeshcp
*/
@Override
public void run() {
while (mIsRunning) {
while (mEventQueue.size() > 0) {
onTouch(mEventQueue.remove(0));
try
{
Thread.sleep(16);
}catch (Exception e) {
}
}
}
}
}
}
你能指出我做錯了什麼嗎?或者什麼是渲染滯後的主要原因。我嘗試了所有可能從本地資源加載圖像的事情,這可能是造成這種滯後的原因,那麼我該如何擺脫這種滯後? – Triode 2013-02-19 18:48:15
Itsa對SurfaceView的限制,認爲你在處理過程中對Bitmap做了很多工作,只是這樣做會花費很多時間。因爲位圖的工作與它必須處理的像素數(分辨率)成正比。它並不是說你做錯了什麼,但是你使用了錯誤的方法。 – JoxTraex 2013-02-19 18:52:44
http://stackoverflow.com/questions/1039393/iphone-app-png-sequence-animation-how-to-use-opengle-optimally-without-crashin但這是iPhone的情況,雖然 – Triode 2013-02-19 18:56:13