Android возвращает общедоступную функцию Bitmap до окончания задержки

Итак, у меня есть public static Bitmap с задержкой 2000 мил внутри. Моя проблема в том, что я получаю return до выполнения кода, который задерживается.

Чтобы дать вам представление о моей структуре функций:

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;
}

Я установил 2 отладочных сообщения — внутри секции задержки и одно прямо перед return.

Вот что я получаю в logcat:

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

а также сообщения об ошибках, которые я не уверен, актуальны:

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)

person Oleksandr Firsov    schedule 11.08.2017    source источник


Ответы (2)


Когда функция handler.postDelayed вызывается в вашем обработчике, она берет созданный вами экземпляр Runnable и сохраняет его в переменной. После этого выполняется следующая строка в вашей функции.

Просто позже, через 2000 мс, вызывается функция run внутри вашего Runnable.

Поэтому порядок, который вы видите, очень предсказуем и результат, который вы видите.

Основная концепция, которую необходимо понять, заключается в том, что код внутри создаваемого вами анонимного класса Runnable не блокирует текущий поток выполнения. Он запускается в более позднее время.

Теоретически эту функцию можно записать так:

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);
}

Затем каким-то образом реализуйте интерфейс WhenReady в вызывающем коде:

interface WhenReady {
     Bitmap doSomethingWithBitmap(Bitmap bitmap);
}
person Dave Thomas    schedule 11.08.2017
comment
Имеет смысл, большое спасибо. Но существует ли вообще способ полностью заблокировать функцию, как я изначально планировал? - person Oleksandr Firsov; 11.08.2017
comment
Не рекомендуется, особенно если вы находитесь в потоке пользовательского интерфейса. Если вы заблокируете функцию в потоке пользовательского интерфейса, ваше приложение перестанет реагировать на пользовательский ввод. Но простой Thread.sleep(2000) сделает это (я говорю это с юмором, не принимайте меня всерьез). Не совсем уверены, какую конечную цель вы пытаетесь достичь? - person Dave Thomas; 11.08.2017
comment
Я попробовал sleep, но ничего не вышло. Что касается того, что я делаю... Это немного сложно - я пытаюсь сгенерировать bitmap из webview, но из-за некоторых проблем с масштабированием у меня может произойти сбой OOM, если я слишком сильно увеличу масштаб, поэтому я разрабатываю обходной путь. Прямо сейчас это дает функции больше времени, чтобы все обработать. Вот поток с наградой, хотя я думаю, что понял это с этим. - person Oleksandr Firsov; 11.08.2017
comment
Да, вам нужно начать программирование для вашего особого случая. Вот одно из предложений: если можете, сохраните растровое изображение в виде фрагментов. Найдите хороший максимальный размер. Как только вы превысите этот размер, разделите изображение на более мелкие части. Используйте запись на диск, чтобы избежать оперативной памяти. Удачи! - person Dave Thomas; 11.08.2017
comment
Классная задачка кстати =) - person Dave Thomas; 11.08.2017

Моя проблема в том, что я получаю возврат до того, как будет выполнен код, который задерживается.

Как описано в документации, postDelayed() не задерживает метод, в котором вы его вызываете. Он планирует запуск Runnable после назначенного периода задержки. getBitmapFromWebview(), надеюсь, вернется через микросекунды.

person CommonsWare    schedule 11.08.2017