SurfaceView闪烁/撕裂

Son*_*man 6 android rendering flicker surfaceview tearing

我正试图弄清楚如何解决我的问题.我已经阅读http://groups.google.com/group/android-developers/browse_thread/thread/a2aac88a08cb56c2/b7dff4ba388cd664?lnk=gst&q=SurfaceView#b7dff4ba388cd664这些问题可以解答我的问题,但据我所知,这是一种"艰难的运气"答案.所以这是我的问题:

我正在以正常方式使用SurfaceView(lock/unlockAndPost)在表面改变时绘制我的游戏背景的位图(例如方向等)并且我渲染一系列移动圆(最多30个半径为约25.f).这些圈子的位置的x,y数据来自服务器,并且一切正常.所有圆形对象都存储在列表中,并且它们的位置会更新,以确保同步更新.然而,当我将这些圆圈绘制到屏幕上时(在canvas.lock()期间),大多数时候它们渲染得很好但偶尔(例如每隔几秒一次),一些圆圈似乎会撕裂或闪烁一帧.圆的数量总是不变的,所以这不是问题,并且没有对圆列表的并发修改(正如我所说,它是同步的).我甚至尝试将所有这些圆形绘制到每个渲染循环上的位图并将该位图绘制到主画布.这似乎只会影响性能(~13FPS,而不是直接将圆圈绘制到主画布时的〜30FPS).对不起,如果这些信息有点模糊,(试图让公司高兴:p)但我只是想知道是否有人能给我一个线索?或者我只是运气不好.我应该注意到来自服务器的定位数据是实时数据,渲染反映这些实时位置至关重要.对不起,如果这些信息有点模糊,(试图让公司高兴:p)但我只是想知道是否有人能给我一个线索?或者我只是运气不好.我应该注意到来自服务器的定位数据是实时数据,渲染反映这些实时位置至关重要.对不起,如果这些信息有点模糊,(试图让公司高兴:p)但我只是想知道是否有人能给我一个线索?或者我只是运气不好.我应该注意到来自服务器的定位数据是实时数据,渲染反映这些实时位置至关重要.

谢谢你的帮助!克里斯

编辑:

很公平.这是来自渲染线程的run().

@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);
                }
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

很标准的东西(几乎是月球着陆器的副本: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;
}
Run Code Online (Sandbox Code Playgroud)

非常容易理解,只需重新定位背景位图,如果方向改变并启动渲染线程.

public void onDraw(Canvas canvas) {
    canvas.drawBitmap(mField,0,0,null);
    drawPositionBeans(canvas, this);
}
Run Code Online (Sandbox Code Playgroud)

最后:

    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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

再次感谢你们.克里斯

Hig*_*yer 1

我有这个问题。适合我的解决方案是同步 onDraw 方法和更新变换矩阵的方法。因为在某些帧中矩阵相同(new Matrix() 的初始值),并且在下一帧中它具有正确的值。