# Display latest posts in Parstagram feed
In this guide we will show step-by-step process of displaying last 20 items of your Parstagram feed using a `RecyclerView`. By this time you should be already familiar with `RecyclerView` and we encourage you to try to implement this task independently. You can refer to this guide when you run into issues to unblock yourself.
In the end your app will look something like this:

## 1) Create a FeedActivity
Let's create a new activity to show a RecyclerView of everyone's posts.
Also create a button from your MainActivity to navigate to your FeedActivity.
## 2) Add RecyclerView to FeedActivity
First let's add RecyclerView dependency to your app by modifying `build.gradle` file in the `app` folder:
```groovy=
implementation "androidx.recyclerview:recyclerview:1.1.0"
```
Next, we will be adding `RecyclerView` to our `FeedActivity` layout file. Open `activity_main.xml` and add `androidx.recyclerview.widget.RecyclerView`. Give it a meaningful id, say `rvPosts`. You `activity_main.xml` might look like this:
```xml
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_margin="16dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FeedActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvPosts"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:padding="8dp" />
</RelativeLayout>
```
Now, let's navigate to `FeedActivity` and create a variable for `RecyclerView`:
```java
private RecyclerView rvPosts;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rvPosts = findViewById(R.id.rvPosts);
}
```
## 3) Create layout for list item
Go ahead and create a new layout file `item_post.xml`. This will be our model for every post in the feed. It needs to hold:
* Author's name
* Image
* Description text

Let's use `LinearLayout` with **vertical** orientation. We will add `TextView` for author's name, `ImageView` for the image, and another `TextView` for description. The image should take whole width of the layout. In the end your layout xml might look like this:
```xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:orientation="vertical">
<TextView
android:id="@+id/tvUsername"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextView"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
tools:text="rahul" />
<ImageView
android:id="@+id/ivImage"
android:layout_width="match_parent"
android:layout_height="300dp"
android:scaleType="centerCrop"
tools:srcCompat="@tools:sample/avatars" />
<TextView
android:id="@+id/tvDescription"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
tools:text="trying to look hipster" />
</LinearLayout>
```
Notice that we modify `android:textApperance` attribute for author's name to make it stand out. Also, we use `android:scaleType="centerCrop"` to imitate Parstagram crop and make sure the image aspect ratio is not affected when stretching image to match parent width.
## 4) Create RecyclerView Adapter
As you might remember from previous assignments, Adapter connects `RecyclerView` to the data we want to display by providing `ViewHolder` and binding methods. Let's start by creating a new class `PostsAdapter` with and empty `ViewHolder`:
```java
public class PostsAdapter extends RecyclerView.Adapter<PostsAdapter.ViewHolder> {
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return null;
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
}
@Override
public int getItemCount() {
return 0;
}
class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(@NonNull View itemView) {
super(itemView);
}
}
}
```
Similar to our previous implementations we want to pass the `Context` and feed data into adapter. Create constructor and pass the parameters to store in member variables:
```java
public class PostsAdapter extends RecyclerView.Adapter<PostsAdapter.ViewHolder> {
private Context context;
private List<Post> posts;
public PostsAdapter(Context context, List<Post> posts) {
this.context = context;
this.posts = posts;
}
@Override
public int getItemCount() {
return posts.size();
}
}
```
Next we will implement Adapter methods. For every visible item on the screen we want to inflate (create) a view. We use `LayoutInflater` and pass it a "blueprint" of the view (reference to XML layout file). Remember, that we want to wrap a view in a `ViewHolder` for easy access:
```java
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.item_post, parent, false);
return new ViewHolder(view);
}
```
Whenever `RecyclerView` has to show an item to a user it will call `onBindViewHolder` with this item's position and `ViewHolder`. Here we should first get the post at this position. Then we can delegate binding to `ViewHolder`.
```java
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
Post post = posts.get(position);
holder.bind(post);
}
```
For ViewHolder we first need to find views and store references to them, so we can later access those views easily when binding data. In our case we have 2 `TextView`s and one `ImageView`:
```java
class ViewHolder extends RecyclerView.ViewHolder {
private TextView tvUsername;
private ImageView ivImage;
private TextView tvDescription;
public ViewHolder(@NonNull View itemView) {
super(itemView);
tvUsername = itemView.findViewById(R.id.tvUsername);
ivImage = itemView.findViewById(R.id.ivImage);
tvDescription = itemView.findViewById(R.id.tvDescription);
}
}
```
Lastly we need to implement the `bind()` method that will update views to display a given post. We will load images using Glide library (refer to [this guide](https://guides.codepath.com/android/Displaying-Images-with-the-Glide-Library) if you need a refresher on using Glide):
```java
public void bind(Post post) {
// Bind the post data to the view elements
tvDescription.setText(post.getDescription());
tvUsername.setText(post.getUser().getUsername());
ParseFile image = post.getImage();
if (image != null) {
Glide.with(context).load(image.getUrl()).into(ivImage);
}
}
```
Now you should have a working `PostsAdapter` and `ViewHolder`.
Let's switch back to `FeedActivity` and connect adapter to the Activity code:
```java
public class FeedActivity extends AppCompatActivity {
protected PostsAdapter adapter;
protected List<Post> allPosts;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rvPosts = findViewById(R.id.rvPosts);
// initialize the array that will hold posts and create a PostsAdapter
allPosts = new ArrayList<>();
adapter = new PostsAdapter(this, allPosts);
}
}
```
Next we need to get data to display by querying posts from your Parstagram feed.
## 5) Query Posts
You should already have `Post` class from previous stories. Now, we want to query the Parstagram backend (our Parse server) to retrieve a list of the latest 20 posts in our feed. In your `FeedActivity` add `queryPosts()` method like this:
```java
private void queryPosts() {
// specify what type of data we want to query - Post.class
ParseQuery<Post> query = ParseQuery.getQuery(Post.class);
// include data referred by user key
query.include(Post.KEY_USER);
// limit query to latest 20 items
query.setLimit(20);
// order posts by creation date (newest first)
query.addDescendingOrder("createdAt");
// start an asynchronous call for posts
query.findInBackground(new FindCallback<Post>() {
@Override
public void done(List<Post> posts, ParseException e) {
// check for errors
if (e != null) {
Log.e(TAG, "Issue with getting posts", e);
return;
}
// for debugging purposes let's print every post description to logcat
for (Post post : posts) {
Log.i(TAG, "Post: " + post.getDescription() + ", username: " + post.getUser().getUsername());
}
// save received posts to list and notify adapter of new data
allPosts.addAll(posts);
adapter.notifyDataSetChanged();
}
});
}
```
In the snippet above we form request and set options such as order, max number of posts and additional data to include. Notice how we store received posts in the array we prepared before - `allPosts.addAll(posts);`. We also make a call to notify the Adapter of new data. It will force to invalidate existing items and re-bind data to `ViewHolder`s.
## 6) Putting it all together
In your `FeedActivity` modify `onCreate()` method to set adapter for `RecyclerView`, add `LayoutManager` and finally query posts from Parstagram feed:
```java
public class FeedActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rvPosts = findViewById(R.id.rvPosts);
allPosts = new ArrayList<>();
adapter = new PostsAdapter(this, allPosts);
// set the adapter on the recycler view
rvPosts.setAdapter(adapter);
// set the layout manager on the recycler view
rvPosts.setLayoutManager(new LinearLayoutManager(this));
// query posts from Parstagram
queryPosts();
}
}
```
Compile and run your application. You should see the list of the latests posts.
## Troubleshooting
If you see no posts:
- Make sure that your Parstagram account has Posts.
- Check Logcat output for Exceptions or Errors. Verify that the posts are printed in logcat.
- Open XML layout files and check that `RecyclerView` and `item_layout` has properly set `width` and `height` attributes.
- See if `PostsAdapter` returns correct size of the items.
- Ensure that you pass `allPosts` into adapter and not changing its reference later.