0

I want to draw many bitmaps on canvas but the android show: "The application may be doing too much work on its main thread" and the app doesn't run. [ cloud_number is over 50 ]

Here my code:

 fun draw_beautiful(canvas: Canvas){

    val mPaint: Paint = Paint()
    mPaint.style = Paint.Style.FILL
    mPaint.isAntiAlias = true
    mPaint.color= Color.BLACK

    var vt = 0; var x1 =0f; var y1 =0f;var style =0;

    for (i in 1..cloud_number){
        vt = i*4-3
        style = mt_cloud[vt]
        x1  = mt_cloud[vt+2].toFloat()
        y1 = mt_cloud[vt+3].toFloat()

        
        var ob= canvas_cloud1
        if (style==0) ob= canvas_cloud1
        else if (style==1) ob= canvas_cloud2
        else if (style==2) ob= canvas_cloud3

        canvas.drawBitmap(ob, x1,y1 , mPaint)

    }

}
aminography
  • 21,986
  • 13
  • 70
  • 74
Dang Hoang
  • 161
  • 11

1 Answers1

0

From the code you posted, majority of the operation in the function does not involve a view. The only part that interacts with a view is the canvas drawing operation. So as has been pointed out in the comments, you should run all the calculations in a worker thread, then call a runOnUIThread with a runnable to do the final drawing on the canvas. The runOnUIThread call will prevent android from throwing an error that occurs when you modify a view from a worker thread not tied to the UI.

The options you have here are obviously AsyncTask and the threading classes. In my example below, I am using an AyncTask.

void draw_beautiful(Canvas canvas) {
        MyDrawingWorkerTask myDrawingWorkerTask = new MyDrawingWorkerTask(this);
        myDrawingWorkerTask.execute(canvas);
    }


/**
 * A class for doing a lot of the work in a background
 */
private static class MyDrawingWorkerTask extends AsyncTask<Canvas, Void, Void> {

    private final Activity activity;

    public MyDrawingWorkerTask(Activity activity) {// add more parameters to use to set other variables like cloud_number, etc
        this.activity = activity;
    }

    // This is where the work is being done
    @Override
    protected Void doInBackground(Canvas... canvases) {
        final Canvas canvas = canvases[0];
        final Paint mPaint = new Paint();
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setAntiAlias(true);
        mPaint.setColor(Color.BLACK);

        int vt = 0;
        float x1 = 0f;
        float y1 = 0f;
        int style = 0;

        for (int i = 0; i < cloud_number; i++) {
            vt = i * 4 - 3;
            style = mt_cloud[vt];
            x1 = mt_cloud[vt + 2].toFloat();
            y1 = mt_cloud[vt + 3].toFloat();


            Bitmap ob = canvas_cloud1;
            if (style == 0) ob = canvas_cloud1;
            else if (style == 1) ob = canvas_cloud2;
            else if (style == 2) ob = canvas_cloud3;

            Bitmap finalOb = ob;
            float finalX = x1;
            float finalY = y1;

            // note that this is what interacts with the view
            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    canvas.drawBitmap(finalOb, finalX, finalY, mPaint);
                }
            });
        }
        return null;
    }
}
  • I'm also new to Kotlin, I hardly write Kotlin in work environment when I have deadlines. – Clement Osei Tano Sep 25 '19 at 10:26
  • I transfer to kotlin and it show this error: Could not complete scheduled request to refresh entries. ClientErrorCode: 3 – Dang Hoang Sep 26 '19 at 10:04
  • I know little Kotlin so check [here](https://stackoverflow.com/questions/50324189/could-not-complete-scheduled-request-to-refresh-entries-clienterrorcode-3-andr#50483744) for a possible solution. – Clement Osei Tano Sep 26 '19 at 13:47