Почему во втором классе мы создаем два 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");
}
}
}
В Android сетевые операции обязаны выполняться в фоновом потоке, а операции с UI в главном. Поэтому создаётся два Handler
для обмена данными между потоками: mResponseHandler
в главном, mRequestHandler
в фоновом.
То есть вызывая метод слушателя в Runnablе
заброшенном в mResponseHandler
вы переводите его выполнение из фонового потока в главный.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Сейчас я разрабатываю сервер который должен будет держать коннекты (предположим 1000) и каждые 15 секунд им всем отсылать сообщение с обновленными...
Написал точный пример из книги, но у меня выдает ошибку почему-то