Загрузка изображения синхронно с Glide

Я хочу написать сопоставитель эспрессо, который проверяет, имеет ли «ImageView» определенный набор растровых изображений. Поскольку приложение загружает изображения через Glide, я подумал, что мне нужно сделать то же самое на тестовой стороне, чтобы учесть обрезку/центрирование, прежде чем я смогу фактически сравнить ожидаемые и фактические растровые изображения.

Вот что я придумал до сих пор:

BitmapRequestBuilder<Uri, Bitmap> bitmapRequest = Glide.with(imageView.getContext())
        .load(Uri.parse("file:///android_asset/" + mPath))
        .asBitmap();

switch (imageView.getScaleType()) {
    case CENTER_CROP:
        bitmapRequest.centerCrop();
        break;
    case FIT_CENTER:
    case FIT_START:
    case FIT_END:
        bitmapRequest.fitCenter();
        break;
    default:
        // no scaling applied to the ImageView under test
}

AtomicReference<Bitmap> bmRef = new AtomicReference<>();
bitmapRequest.into(new SimpleTarget<Bitmap>(
            imageView.getMeasuredWidth(), 
            imageView.getMeasuredHeight()
) {
    @Override
    public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
        bmRef.set(resource);
    }
});

// ???

try {
    Bitmap expected = bmRef.get();
    return expected.sameAs(bitmap);
} catch (Exception e) {
    throw new IllegalStateException("could not load asset " + mPath, e);
}

Теперь проблема здесь, конечно, в том, что у меня тупик. Я нахожусь в основном потоке (сопоставитель выполняется в основном потоке IIRC), и Glide хочет, чтобы внутренний поток загружал растровое изображение, а затем возвращался в основной поток (в «onResourceReady»). Поэтому мне нужно ждать извне результата, который публикуется внутри, сохраняя при этом основной поток.

Я (безуспешно) попытался продвинуть текущий лупер через Looper.loop() в // ???, а также попробовал обычный подход блокировки/ожидания, но ничего не сработало. У меня нет идей...


person Thomas Keller    schedule 25.02.2016    source источник


Ответы (2)


Для таких случаев я использую простой sleep, это не лучший вариант, но мне он подходит.

public static void waitForActivity(long time) {
     try {
         Thread.sleep(time);
     } catch (InterruptedException e) {
         e.printStackTrace();
     }
 }
person Sandro Machado    schedule 28.02.2016
comment
В данном случае это не работает, к сожалению, только что попробовал еще раз. - person Thomas Keller; 01.03.2016

Один из способов сделать это, чтобы сохранить логику сравнения внутри onResourceReady, а затем, если вы используете какую-либо шину событий, затем инициировать событие с результатом и поместить логику пользовательского интерфейса в метод, который подписывается на это событие. Если шина событий не используется, то LocalBroadcastManager для трансляции результата .

Например:

private BroadcastReceiver receiver;

private void doWhateverYouWantWithResult(boolean result) {

}

bitmapRequest.into(new SimpleTarget<Bitmap>(
            imageView.getMeasuredWidth(), 
            imageView.getMeasuredHeight()
) {
    @Override
    public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
        bmRef.set(resource);
        Bitmap expected = resource;
        boolean result = expected.sameAs(bitmap);
        Intent localIntent =
                new Intent(BROADCAST_ACTION)
                        // Puts the status into the Intent
                        .putExtra(MATCH_RESULT, result);
        // Broadcasts the Intent to receivers in this app.
        LocalBroadcastManager.getInstance(this).sendBroadcast(localIntent);
    }
});


    @Override
    public void onResume(){
        super.onResume();
        receiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                boolean result = intent.getBooleanExtra(MATCH_RESULT);
                doWhateverYouWantWithResult(result);
            }
        };
        LocalBroadcastManager.getInstance(getContext())
                .registerReceiver(receiver, new IntentFilter(BROADCAST_ACTION));
    }

    @Override
    public void onPause(){
        super.onPause();
        LocalBroadcastManager.getInstance(getContext()).unregisterReceiver(receiver);
    }
person Praveen Yadav    schedule 11.04.2016