I am trying to figure out how to get around my problem. I read the http://groups.google.com/group/android-developers/browse_thread/thread/a2aac88a08cb56c2/b7dff4ba388cd664?lnk=gst&q=SurfaceView#b7dff4ba388cd664 that answers my question, but as far as I can tell, this is kind of an answer "good luck." So here is my problem:
I use SurfaceView in the usual way (lock / unlockAndPost) to draw a bitmap of my game background whenever the surface changes (for example, orientation, etc.), and I represent a series of moving circles (up to 30 with a radius of about 25.f ) The x, y data for the positions of these circles comes from the server and everything works fine. All environment objects are stored in the list, and their position is updated to ensure synchronization of this update. However, when I draw these circles on the screen (during canvas.lock ()), most of the time they render fine, but sometimes (for example, once every few seconds) some of the circles seem to blush or flicker for the frame. The number of circles is always constant, so there is no problem and there are no parallel changes in the list of circles (as I said, it is synchronized). I even tried to draw all these circles in Bitmap in each rendering cycle and draw this bitmap on the main canvas. This seems to affect performance even more (~ 13FPS as opposed to ~ 30FPS when drawing circles directly on the main canvas). Sorry if the information is a bit vague (I try to keep the company happy: p), but I'm just wondering if anyone can give me a clue? Or I'm just out of luck. I should note that the positioning data coming from the server is real-time data, and it is vital that the rendering reflect these positions in real time.
Thanks for any help! Chris
EDIT:
Fair enough. Here is the run () from the render stream.
@Override public void run() { Canvas c; while (mRun) { c = null; try { c = mSurfaceHolder.lockCanvas(null); synchronized (mSurfaceHolder) { panel.onDraw(c); } } finally { if (c != null) { mSurfaceHolder.unlockCanvasAndPost(c); } } } }
Pretty standard stuff (almost a copy of the lunar lander: p)
@Override public void surfaceCreated(SurfaceHolder holder) { mBackground= Bitmap.createBitmap(this.getWidth(), this.getHeight(), Bitmap.Config.RGB_565); screenOrientation = getResources().getConfiguration().orientation; if(thread.getState()== Thread.State.TERMINATED){ thread = new RenderThread(holder, this); thread.setRunning(true); thread.start(); }else { thread.setRunning(true); thread.start(); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Canvas c = new Canvas(mField); c.drawARGB(255,0,144,0); backgroundDetails.renderOnPanel(c, this); screenOrientation = getResources().getConfiguration().orientation; }
It's pretty easy to follow, just redraw the background bitmap if the orientation changes and start the rendering stream.
public void onDraw(Canvas canvas) { canvas.drawBitmap(mField,0,0,null); drawPositionBeans(canvas, this); }
And finally:
public void onDraw(Canvas canvas, RadarView radarView) { float beanX=0, beanY=0; float radius = 25.0f; final List<PositionBean> copyOfList = Collections.synchronizedList(positionBeans.getPositionBeans()); synchronized(copyOfList){ try { for (final PositionBean pb : copyOfList) { if (panel.getOrientation() == Configuration.ORIENTATION_PORTRAIT) { beanX = (float)pb.getY()*(-1); beanY = (float)pb.getX(); } else { beanX = (float)pb.getY()*(-1); beanY = (float)pb.getX()*(-1); } mPaint.setARGB(255,pb.getRgbColor().getR(), pb.getRgbColor().getG(), pb.getRgbColor().getB()); panel.drawSpot(canvas, beanX, beanY, radius, mPaint); mPaint.setStyle(Paint.Style.STROKE); mPaint.setARGB(255,255,222,1); for (int j = 0; j < selectedBean.size(); ++j) { if(pb.getTrack()==selectedBean.get(j)) { panel.drawSpot(canvas, beanX, beanY, radius+1, mPaint); } } mPaint.setStyle(Paint.Style.FILL); } } catch(Exception e) { Log.e("render", "Exception Drawing Beans: " + e); } } }
Thanks again to the guys. Chris