Synchronous Creation of Android Surfaceview

Asked

Viewed 200 times

2

I created a subclass of Surfaceview to abstract canvas operations, such as drawBitmap (among others), as shown below:

public class MyView extends SurfaceView {

    public MyView(Context c) {
       super(c);
       this.canvasHolder = this.getHolder();
       this.canvasHolder.addCallback(surfaceHolderCallback);
    }

    public void drawBitmap(Bitmap bitmap, float width, float height, Paint p) {
        canvas.drawBitmap(bitmap, width, height, p);
    }

    private SurfaceHolder.Callback surfaceHolderCallback = new SurfaceHolder.Callback() {
       @Override
       public void surfaceCreated(SurfaceHolder holder) {
           canvas = holder.lockCanvas();
       }

       @Override
       public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}

       @Override
       public void surfaceDestroyed(SurfaceHolder holder) {}
    };

    public void flush() {
       this.canvasHolder.unlockCanvasAndPost(this.canvas);
       this.canvas = this.canvasHolder.lockCanvas();
    }

The full startup of Surfaceview depends on the callback, in which I can access the canvas I will need to manipulate. Otherwise, I get a Nullpointerexception on the first call to drawBitmap.

The problem is that I want to allow the use of the class very directly, as shown below. To do this, I need to abstract this entire boot mechanism with callback and ensure that drawBitmap has access to a valid canvas (not null).

Any idea how to do that?

    MyView view = new MyView(getBaseContext());
    String source = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/abc.png";
    view.drawBitmap(BitmapFactory.decodeFile(source).copy(Bitmap.Config.ARGB_8888, true), 0, 0, null);
    view.flush();

1 answer

0

If the "valid state" of a class instance Myview depends on a call to a callback it is as if the "creation of the instance was asynchronous"

I do not see how it is possible to ensure that the instance is not used before having the "valid status".

However, it is possible to provide you with a place where you can use it with this warranty.

One way would be to pass one callback in the builder and call him after the canvas be valid.

It would be something like that:

public class MyView extends SurfaceView {

    //Iterface que o callback tem de implemantar
    public interface onCreatedCallback {
        void onCreated(MyView myView);
    }

    private final SurfaceHolder canvasHolder;
    private Canvas canvas;
    private onCreatedCallback onCreatedCallback;

    public MyView(Context c, onCreatedCallback callback) {
        super(c);
        //Guarda o callback
        onCreatedCallback = callback;
        this.canvasHolder = this.getHolder();
        this.canvasHolder.addCallback(surfaceHolderCallback);
    }

    public void drawBitmap(Bitmap bitmap, float width, float height, Paint p) {
        canvas.drawBitmap(bitmap, width, height, p);
    }

    private SurfaceHolder.Callback surfaceHolderCallback = new SurfaceHolder.Callback() {
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            canvas = holder.lockCanvas();

            //Nesta altura o canvas é valido
            if(onCreatedCallback != null){
                //Chama o callback
                onCreatedCallback.onCreated(MyView.this);
            }
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {}
    };

    public void flush() {
        this.canvasHolder.unlockCanvasAndPost(this.canvas);
        this.canvas = this.canvasHolder.lockCanvas();
    }
}  

The use would be thus:

final String source = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/abc.png";
new MyView(getBaseContext(), new MyView.onCreatedCallback() {
    @Override
    public void onCreated(MyView myView) {
        myView.drawBitmap(BitmapFactory.decodeFile(source).copy(Bitmap.Config.ARGB_8888, true), 0, 0, null);
        myView.flush();
    }
});
  • Thank you for your reply. In fact, I am aware of the possibility of adding the Ner, but I cannot do it, because both the creation of the object and the call to functions are made via reflection, in code coming from another language, synchronously. A very specific context. . =(

Browser other questions tagged

You are not signed in. Login or sign up in order to post.