Почему создается новый Handler?

101
04 апреля 2021, 16:40

Почему во втором классе мы создаем два Handler: mResponseHandler и mRequestHandler? Почему нужно создать mResponseHandler в onCreate и затем передать в конструктор mThumbnailDownloader? Т.е почему в методе hanldeRequest мы вызывает Runnablе и там уже вызываем метод слушателя? Почему это нельзя сделать в mRequestHandler?

Есть такой код:

public class PhotoGalleryFragment extends Fragment {
    private static final String TAG = "PhotoGalleryFragment";
    private RecyclerView mRecyclerView;
    private List<GalleryItem> mItems = new ArrayList<>();
    private ThumbnailDownloader<PhotoHolder> mThumbnailDownloader;
    public static PhotoGalleryFragment newInstance() {
        return new PhotoGalleryFragment();
    }
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
        new FetchItemsTask().execute();
        Handler responseHandler = new Handler();
        mThumbnailDownloader = new ThumbnailDownloader<>(responseHandler);
        mThumbnailDownloader.setThumbnailDownloadListener(new ThumbnailDownloader.ThumbnailDownloadListener<PhotoHolder>() {
            @Override
            public void onThumbnailDownloaded(PhotoHolder target, Bitmap thumbnail) {
                Drawable drawable = new BitmapDrawable(getResources(), thumbnail);
                target.bindDrawable(drawable);
            }
        });
        mThumbnailDownloader.start();
        mThumbnailDownloader.getLooper();
        Log.i(TAG, "Background thread started");
    }
}

И есть второй класс:

public class ThumbnailDownloader<T> extends HandlerThread {
    private static final String TAG = "ThumbnailDownloader";
    private static final int MESSAGE_DOWNLOAD = 0;
    private Handler mRequestHandler;
    private Handler mResponseHandler;
    private ConcurrentMap<T, String> mRequestMap = new ConcurrentHashMap<>();
    private boolean mHasQuit = false;
    private ThumbnailDownloadListener<T> mThumbnailDownloadListener;
    public interface ThumbnailDownloadListener<T>{
        void onThumbnailDownloaded(T target, Bitmap thumbnail);
    }
    public void setThumbnailDownloadListener(ThumbnailDownloadListener<T> listener) {
        mThumbnailDownloadListener = listener;
    }
    public ThumbnailDownloader(Handler responseHandler) {
        super(TAG);
        mResponseHandler = responseHandler;
    }
    @Override
    protected void onLooperPrepared() {
        mRequestHandler = new Handler() {
            @Override
            public void handleMessage(@NonNull Message msg) {
                if(msg.what == MESSAGE_DOWNLOAD){
                    T target = (T)msg.obj;
                    Log.i(TAG, "Got a request for url " + mRequestMap.get(target));
                    handleRequest(target);
                }
            }
        };
    }
    private void handleRequest(final T target) {
        try {
            final String url = mRequestMap.get(target);
            if (url == null)
                return;
            byte[] bitmapBytes = new FlickrFetchr().getUrlBytes(url);
            final Bitmap bitmap = BitmapFactory.decodeByteArray(bitmapBytes, 0, bitmapBytes.length);
            Log.i(TAG, "Bitmap created");
            mResponseHandler.post(new Runnable() {
                @Override
                public void run() {
                    if(mRequestMap.get(target) != url || mHasQuit)
                        return;
                    mRequestMap.remove(target);
                    mThumbnailDownloadListener.onThumbnailDownloaded(target, bitmap);
                }
            });
        } catch (IOException e){
            Log.i(TAG, "Error downloading image");
        }
    }
}
Answer 1

В Android сетевые операции обязаны выполняться в фоновом потоке, а операции с UI в главном. Поэтому создаётся два Handler для обмена данными между потоками: mResponseHandler в главном, mRequestHandler в фоновом.
То есть вызывая метод слушателя в Runnablе заброшенном в mResponseHandler вы переводите его выполнение из фонового потока в главный.

READ ALSO
WebSocket реализация

WebSocket реализация

Сейчас я разрабатываю сервер который должен будет держать коннекты (предположим 1000) и каждые 15 секунд им всем отсылать сообщение с обновленными...

222
Условие If и &ldquo;var1 cannot be resolved to a variable&rdquo; in Java Eclipse, где ошибка?

Условие If и “var1 cannot be resolved to a variable” in Java Eclipse, где ошибка?

Написал точный пример из книги, но у меня выдает ошибку почему-то

88
ExceptionHandler не перехватывает исключения

ExceptionHandler не перехватывает исключения

Итак, у меня есть исключение:

126
Retrofit2 и ошибка SSLHandshakeException SSLProtocolException

Retrofit2 и ошибка SSLHandshakeException SSLProtocolException

Нужно решить проблему с эксепшн

103