SurfaceView, onDraw and postInvalidate() something

2019-08-05 07:56发布

App behave itself strangely. I have a class extends the SurfaceView and implements SurfaceHolder.Callback .
I tried 3 options of code and only one works like i need (but I'm doubt that it is a right solution) and other have different behavior.
So, my question is why and what is wrong and if "right" solution is wrong, so why it's work...

Right for all:

  1. I tried setWillNotDraw(boolean flag) flag(true/false)
  2. In manifest set android:changeConfiguration="orientation"
  3. In main layout set background with tiling picture defined via xml resources.

Now the "right" implementation: I have thread which call postInvalidate(); with delays and calls between lockCanvas and unlockCanvas:
my onDraw() and draw(Canvas c,int deg) same in all variations:

@Override
public void onDraw(Canvas c) {
    draw(c,lastHeading);
    super.onDraw(c);
}

public synchronized void draw(Canvas c,int degrees) {
    Paint p=new Paint();
    p.setAntiAlias(true);
    c.save();

    rotateLayer(degrees,layer1, cLayers.getDrawable(0),false);
    rotateLayer(lastSideAngle, layer2, sLayers.getDrawable(1),true);
    rotateLayer(lastFrontAngle, layer2, fLayers.getDrawable(1),true);

    c.drawBitmap(layer1,0, 0, p);
    c.drawBitmap(layer2,0, 0, p);
    c.drawBitmap(layer3, 0,0, p);   
    c.restore();
}

Problem code variant A (and "right" ):

@Override
public void run() {
    Canvas c=null;
    try
    {
        c=holder.lockCanvas(null);
        synchronized (holder) {
        postInvalidate();
    }
    finally
    {
        if(c!=null)
        holder.unlockCanvasAndPost(c);
    }
}

why it works without problems however same code without lock/unloc of canvas didn't work corectly?

With next implementation app work nice until phone doesn't change orientation. While changing orientation its take along time to redraw the surface, but in next orientation change it changes fast. but in both variants i call to postInvalidate() and I not understand how lock/unlock Canvas affect on postInvalidate() ?

@Override
public void run() {
    postInvalidate();
}

And in this variant I see on screen a frozen image which never cahnges:

@Override
public void run() {
    Canvas c=null;
    try
    {
        c=holder.lockCanvas(null);
        synchronized (holder) {
        draw(c,deg);
        //OR
        //onDraw(c)
    }
    finally
    {
        if(c!=null)
        holder.unlockCanvasAndPost(c);
    }
}

There is one more variant when app draws the all bitmaps but a background is overlayed its all. So what i do wrong and what i need to do?

1条回答
我欲成王,谁敢阻挡
2楼-- · 2019-08-05 08:07

Here:

@Override
public void run() {
Canvas c=null;
   try
   {
       c=holder.lockCanvas(null);
       synchronized (holder) {
       draw(c,deg);
       //OR
       //onDraw(c)
   }
   finally
   {
       if(c!=null)
       holder.unlockCanvasAndPost(c);
   } 
}

You need to set up a loop, because otherwise you are calling the onDraw() method only once. This would create a continuous redrawing:

while(true) {
   try
   {
       c=holder.lockCanvas(null);
       synchronized (holder) {
       draw(c,deg);
       //OR
       //onDraw(c)
   }
   finally
   {
       if(c!=null)
       holder.unlockCanvasAndPost(c);
   } 
}

Source

查看更多
登录 后发表回答