public class ThumbnailDownloader extends HandlerThread {
private static final String TAG=“ThumbnailDownloader”;
private boolean mHasQuit=false;
private static final int MESSAGE_DOWNLOAD=0;
private Handler mRequestHandler;
private ConcurrentMap<T,String> mRequestMap = new ConcurrentHashMap<>();
private Handler mResponseHandler;
private ThumbnailDownloaderListener mThumbnailDownloaderListener;
public interface ThumbnailDownloaderListener<T>
{
void onThumbnailDownloaded(T target, Bitmap thumbnail);
}
public void setThumbnailDownloaderListener(ThumbnailDownloaderListener listener)
{
mThumbnailDownloaderListener=listener;
}
public ThumbnailDownloader(Handler responseHandler){
super(TAG);
mResponseHandler=responseHandler;
}
@Override
protected void onLooperPrepared() {
mRequestHandler=new Handler(){
@Override
public void handleMessage(Message msg) {
if (msg.what==MESSAGE_DOWNLOAD)
{
T target=(T) msg.obj;
Log.i(TAG, "Got a request fpr URL "+ mRequestMap.get(target));
handleRequest(target);
}
}
};
}
@Override
public boolean quit()
{
mHasQuit=true;
return super.quit();
}
public void queueThumbnail(T target, String url)
{
Log.i(TAG,"Got a URL: " + url);
if (url==null)
{
mRequestMap.remove(target);
}
else
{
mRequestMap.put(target, url);
mRequestHandler.obtainMessage(MESSAGE_DOWNLOAD, target).sendToTarget();
}
}
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);
mThumbnailDownloaderListener.onThumbnailDownloaded(target, bitmap);
}
});
}catch (IOException ioe)
{
Log.e(TAG, "Error downloading image", ioe);
}
}
public void clearQueue()
{
mResponseHandler.removeMessages(MESSAGE_DOWNLOAD);
mRequestMap.clear();
}
}
public class PhotoGalleryFragment extends Fragment {
private RecyclerView mPhotoRecyclerView;
private static final String TAG = "PhotoGalleryFragment";
private List<GalleryItem> mItems = new ArrayList<>();
private int mPosition = 1;
private int mCurrentPage=1;
private int mNewSize;
private boolean mDataUpload=false;
private int mOldPosition;
private ImageView mTitleImageView;
private ThumbnailDownloader<PhotoHolder> mThumbnailDownloader;
public static PhotoGalleryFragment newInstance() {
return new PhotoGalleryFragment();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
new FetchItemsTask().execute(mCurrentPage);
Handler responseHandler= new Handler();
mThumbnailDownloader=new ThumbnailDownloader<>(responseHandler);
mThumbnailDownloader.setThumbnailDownloaderListener(
new ThumbnailDownloader.ThumbnailDownloaderListener<PhotoHolder>() {
@Override
public void onThumbnailDownloaded(PhotoHolder photoHolder, Bitmap bitmap) {
Drawable drawable=new BitmapDrawable(getResources(), bitmap);
photoHolder.bindDrawble(drawable);
}
}
);
mThumbnailDownloader.start();
mThumbnailDownloader.getLooper();
Log.i(TAG,"Background thread started!");
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_photo_gallery, container, false);
mPhotoRecyclerView = (RecyclerView) v.findViewById(R.id.photo_recycle_view);
mPhotoRecyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 3));
mPhotoRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
mOldPosition+=dy;
if (mPosition==mPhotoRecyclerView.getAdapter().getItemCount()-1 && !mDataUpload) {
mCurrentPage +=1;
mDataUpload=true;
new FetchItemsTask().execute(mCurrentPage);
}
}
});
setupAdapter();
return v;
}
@Override
public void onDestroyView() {
super.onDestroyView();
mThumbnailDownloader.clearQueue();
}
@Override
public void onDestroy() {
super.onDestroy();
mThumbnailDownloader.quit();
Log.i(TAG, "Background thread destroyed");
}
private void setupAdapter() {
if (isAdded()) {
mPhotoRecyclerView.setAdapter(new PhotoAdapter(mItems));
}
}
private class FetchItemsTask extends AsyncTask<Integer, Void, List<GalleryItem>> {
@Override
protected List<GalleryItem> doInBackground(Integer... params) {
int state = 0;
for (int parametr : params) {
state = parametr;
}
return new FlickrFetchr().fetchItems(state);
}
@Override
protected void onPostExecute(List<GalleryItem> items) {
mNewSize=items.size();
mItems.addAll(items);
if (mDataUpload)
{mPhotoRecyclerView.getAdapter().notifyItemRangeInserted(mPosition+1,mNewSize );
mDataUpload=false;}
else {
setupAdapter();
}
}
}
private class PhotoHolder extends RecyclerView.ViewHolder {
private TextView mTitleTextView;
public PhotoHolder(View itemView) {
super(itemView);
mTitleImageView = (ImageView) itemView.findViewById(R.id.item_image_view);
}
public void bindDrawble(Drawable drawable) {
mTitleImageView.setImageDrawable(drawable);
}
}
private class PhotoAdapter extends RecyclerView.Adapter<PhotoHolder> {
private List<GalleryItem> mGalleryItems;
public PhotoAdapter(List<GalleryItem> galleryItems) {
mGalleryItems = galleryItems;
}
@Override
public PhotoHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater=LayoutInflater.from(getActivity());
View view=inflater.inflate(R.layout.gallery_item, parent, false);
return new PhotoHolder(view);
}
@Override
public void onBindViewHolder(PhotoHolder holder, int position) {
GalleryItem galleryItem = mGalleryItems.get(position);
mPosition=position;
Drawable placeHolder=getResources().getDrawable(android.R.drawable.ic_menu_upload);
holder.bindDrawble(placeHolder);
mThumbnailDownloader.queueThumbnail(holder, galleryItem.getUrl());
}
@Override
public int getItemCount() {
return mGalleryItems.size();
}
}
}