Android Getting public Bitmap function return before Delay ended
Asked Answered
A

2

0

So, I have a public static Bitmap with a delay of 2000 mils inside of it. My problem is that I get return before code that is getting delayed is executed.

To give you the idea of my function structure:

public static Bitmap getBitmapFromWebview(WebView webView){
    *******************some code here
    Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            ********************declaring bm bitmap
            Log.i("DelayD", "Delay");
        }
    }, 2000);


    Log.i("DelayD", "Return");
    return bm;
}

I've set up 2 debug messages - inside the delayed section, and one right before the return.

Here's what I get in the logcat:

08-11 20:45:13.520 I/DelayD: Return
08-11 20:45:16.173 I/DelayD: Delay

as well as an Error messages, which I'm not sure are relevant:

08-11 20:44:45.170 E/Sensors: new setDelay handle(0),ns(66667000)m, error(0), index(2)
08-11 20:44:48.082 E/Sensors: new setDelay handle(0),ns(66667000)m, error(0), index(2)
Accomplice answered 11/8, 2017 at 19:2 Comment(0)
B
2

When the function handler.postDelayed is called on your handler it takes the Runnable instance you created and stores it in a variable. After that concludes then the next line in your function executes.

Simply, at a later time after 2000ms, the function run inside your Runnable is called.

Therefore the order you are seeing is very predictable and the result you are seeing.

The core concept to grasp is the fact that the code inside the anonymous Runnable class you create does not block the current thread of execution. It is run at a later time.

This function theoretically could be written:

public static void getBitmapFromWebview(WebView webView, final WhenReady callback){

    Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {

            callback.doSomethingWithBitmap(bitmap);
        }
    }, 2000);
}

Then implement the WhenReady interface some how in your calling code:

interface WhenReady {
     Bitmap doSomethingWithBitmap(Bitmap bitmap);
}
Bairam answered 11/8, 2017 at 19:13 Comment(5)
Makes sense, thanks a bunch. But is there even exists a way to block a function completely like I intended at first?Accomplice
Not recommended, especially if you are on your UI thread. If you block a function on the UI thread your application will stop responding to user input. But a simple Thread.sleep(2000), would do it ( I say that with humor don't take me seriously on that one ). Not entirely sure what your overall end goal is you are trying to accomplish?Bairam
I tried sleep, but it didn't work out well. As of what I'm doing... It's a bit complicated - I'm trying to generate a bitmap from webview, but due to some scaling issues I can get OOM crash if I zoom in too much, so I'm developing a workaround. Right now it's "give function more time to process everything". Here's the thread with a bounty, although I think I have figured it out with this.Accomplice
Yup, you need to start programming for your special case there. Here is one suggestion save the bitmap in slices if you can. Find a nice maximum size. As soon as you go over that size divide your image into smaller quarters. Use writing to disk to help you keep out of ram. Good luck!Bairam
Cool problem by the way =)Bairam
P
2

My problem is that I get return before code that is getting delayed is executed.

As is covered in the documentation, postDelayed() does not delay the method in which you call it. It schedules a Runnable to run after the designated delay period. getBitmapFromWebview() will return in microseconds, hopefully.

Plenteous answered 11/8, 2017 at 19:8 Comment(0)
B
2

When the function handler.postDelayed is called on your handler it takes the Runnable instance you created and stores it in a variable. After that concludes then the next line in your function executes.

Simply, at a later time after 2000ms, the function run inside your Runnable is called.

Therefore the order you are seeing is very predictable and the result you are seeing.

The core concept to grasp is the fact that the code inside the anonymous Runnable class you create does not block the current thread of execution. It is run at a later time.

This function theoretically could be written:

public static void getBitmapFromWebview(WebView webView, final WhenReady callback){

    Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {

            callback.doSomethingWithBitmap(bitmap);
        }
    }, 2000);
}

Then implement the WhenReady interface some how in your calling code:

interface WhenReady {
     Bitmap doSomethingWithBitmap(Bitmap bitmap);
}
Bairam answered 11/8, 2017 at 19:13 Comment(5)
Makes sense, thanks a bunch. But is there even exists a way to block a function completely like I intended at first?Accomplice
Not recommended, especially if you are on your UI thread. If you block a function on the UI thread your application will stop responding to user input. But a simple Thread.sleep(2000), would do it ( I say that with humor don't take me seriously on that one ). Not entirely sure what your overall end goal is you are trying to accomplish?Bairam
I tried sleep, but it didn't work out well. As of what I'm doing... It's a bit complicated - I'm trying to generate a bitmap from webview, but due to some scaling issues I can get OOM crash if I zoom in too much, so I'm developing a workaround. Right now it's "give function more time to process everything". Here's the thread with a bounty, although I think I have figured it out with this.Accomplice
Yup, you need to start programming for your special case there. Here is one suggestion save the bitmap in slices if you can. Find a nice maximum size. As soon as you go over that size divide your image into smaller quarters. Use writing to disk to help you keep out of ram. Good luck!Bairam
Cool problem by the way =)Bairam

© 2022 - 2024 — McMap. All rights reserved.