Chapter 25: Challenge 1-2


#1

First, i use this website to convert to POJO (Java Bean) class, all you need to do get json file and paste it and choose the file type (JSON of course) and choose Annotation Style to Gson …
JSON2Pojo

Here is my POJO class GalleryItems:

> package echomachine.android.com.photogallery.model;

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

import java.util.List;

public class GalleryItems {

@SerializedName("photos")
@Expose
private Photos photos;
@SerializedName("stat")
@Expose
private String stat;

public Photos getPhotos() {
    return photos;
}

public void setPhotos(Photos photos) {
    this.photos = photos;
}

public String getStat() {
    return stat;
}

public void setStat(String stat) {
    this.stat = stat;
}

public class Photos {

    @SerializedName("page")
    @Expose
    private Integer page;
    @SerializedName("pages")
    @Expose
    private Integer pages;
    @SerializedName("perpage")
    @Expose
    private Integer perpage;
    @SerializedName("total")
    @Expose
    private Integer total;
    @SerializedName("photo")
    @Expose
    private List<Photo> photo;

    public Integer getPage() {
        return page;
    }

    public void setPage(Integer page) {
        this.page = page;
    }

    public Integer getPages() {
        return pages;
    }

    public void setPages(Integer pages) {
        this.pages = pages;
    }

    public Integer getPerpage() {
        return perpage;
    }

    public void setPerpage(Integer perpage) {
        this.perpage = perpage;
    }

    public Integer getTotal() {
        return total;
    }

    public void setTotal(Integer total) {
        this.total = total;
    }

    public List<Photo> getPhoto() {
        return photo;
    }

    public void setPhoto(List<Photo> photo) {
        this.photo = photo;
    }

    public class Photo {

        @SerializedName("id")
        @Expose
        private String id;

        @SerializedName("title")
        @Expose
        private String title;

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }
    }

}

}

Here i put Photo class inside Photos class with all annotation for gson (you don’t need all these Getter and Setter methods it was for testing something for me)

and here is my

FlickrFitcher Class:

public class FlickrFitcher {

private static final String TAG = "Flickr-Tag";
private static final String API_KEY = "9d7ad75570dadf0177ac26f471f323f1";
public static int maxPages;
public static int mCurrentPage = 0;

public FlickrFitcher() {
    if(mCurrentPage < 1) {
        mCurrentPage = 1;
    } else if(mCurrentPage > maxPages) {
        mCurrentPage = maxPages;
    } else {
        ++mCurrentPage;
    }
}

public byte[] getUrlBytes(String urlSpec) throws IOException {
    URL url = new URL(urlSpec);
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();

    try {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        InputStream in = connection.getInputStream();

        if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
            throw new IOException(connection.getResponseMessage() + ": with " + urlSpec);
        }

        int bytesRead = 0;
        byte[] buffer = new byte[1024];
        while ((bytesRead = in.read(buffer)) > 0) {
            out.write(buffer, 0, bytesRead);
        }
        out.close();
        return out.toByteArray();

    } finally {
        connection.disconnect();
    }
}

public String getUrlString(String urlSpec) throws IOException {
    return new String(getUrlBytes(urlSpec));
}

public List<GalleryItems.Photos.Photo> fetchItemsPages(int page) {
List items = new ArrayList<>();
String pageNum = String.valueOf(page);
try {
String url = Uri.parse(“https://api.flickr.com/services/rest/”)
.buildUpon()
.appendQueryParameter(“method”, “flickr.photos.getRecent”)
.appendQueryParameter(“api_key”, API_KEY)
.appendQueryParameter(“format”, “json”)
.appendQueryParameter(“nojsoncallback”, “1”)
.appendQueryParameter(“page”, pageNum)
.appendQueryParameter(“extras”, “url_s”)
.build().toString();
String urlString = getUrlString(url);
Gson gson = new Gson();
Log.i(TAG, "Fetch Page: " + urlString);
GalleryItems galleryPages = gson.fromJson(urlString, GalleryItems.class);
items = galleryPages.getPhotos().getPhoto();
maxPages = galleryPages.getPhotos().getPages();
Log.i(TAG, " " + maxPages + mCurrentPage);
} catch (IOException e) {
e.printStackTrace();
}
return items;
}
}

Then I Modify some stuff in my Fragment Like this:

PhotoGalleryFragment

public class PhotoGalleryFragment extends Fragment {

private RecyclerView mRecycleView;
private static final String TAG = "PhotoGalleryTask";
private List mItems = new ArrayList<>();
private int lastPosition = 0;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_photo_gallery, container, false);
mRecycleView = view.findViewById(R.id.photo_recycle_view);
mRecycleView.setLayoutManager(new GridLayoutManager(getActivity(), 3));
mRecycleView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            LinearLayoutManager layoutManager = (LinearLayoutManager)recyclerView
                    .getLayoutManager();

            lastPosition = layoutManager.findLastVisibleItemPosition();
            int itemsCount = layoutManager.getItemCount();
            if(lastPosition >= itemsCount - 1 && FlickrFitcher.mCurrentPage < FlickrFitcher.maxPages) {
                new FetchItemsTask().execute();
            }
        }
    });
    setupAdapter();
    return view;
}

private class FetchItemsTask extends AsyncTask<Void, Void, List<GalleryItems.Photos.Photo>> {

    @Override
    protected List doInBackground(Void... voids) {
        return new FlickrFitcher().fetchItemsPages(FlickrFitcher.mCurrentPage);
    }

    @Override
    protected void onPostExecute(List<GalleryItems.Photos.Photo> items) {
            for(GalleryItems.Photos.Photo item: items) {
                mItems.add(item);
            }
            setupAdapter();
        }
    }

private class PhotoHolder extends RecyclerView.ViewHolder{

    private TextView mTextView;

    public PhotoHolder(View itemView) {
        super(itemView);
        mTextView = (TextView) itemView;
    }

    public void bindDrawable(GalleryItems.Photos.Photo galleryItems) {
        mTextView.setText(galleryItems.toString());
    }

}

private class PhotoAdapter extends RecyclerView.Adapter<PhotoHolder> {

    private List<GalleryItems.Photos.Photo> mGalleryItems;

    public PhotoAdapter(List<GalleryItems.Photos.Photo> galleryItems) {
        mGalleryItems = galleryItems;
    }

    @Override
    public PhotoHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        TextView textView = new TextView(getActivity());
        return new PhotoHolder(textView);
    }

    @Override
    public void onBindViewHolder(PhotoHolder holder, int position) {
        GalleryItems.Photos.Photo items = mGalleryItems.get(position);
        holder.bindDrawable(items);
    }

    @Override
    public int getItemCount() {
        return mGalleryItems.size();
    }
}

private void setupAdapter() {
    if(isAdded()) {
        mRecycleView.setAdapter(new PhotoAdapter(mItems));
        mRecycleView.scrollToPosition(lastPosition);
    }
}

}