Android Retrofit, RecyclerView, SearchView Usage

Hello friends,
Today, I will do an application that describes Retrofit, RecyclerView, SearchView usage together.

What gonna we learn in this post?

  • We will learn the use of rest api with Retrofit.
  • We will list the data from the service in the RecyclerView.
  • Usage the android component SearchView.
  • In RecyclerView, we'll see how we can solve click events with the help of the Interface.
  • We will see how to access the data we want by searching with the getFilter function within the listed data.
  • we will use this method within our Adapter classLet's start building our application now,
    As we always do, let's add the libraries that we will use in our project to build.gradle.
apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "umitkose.codebugfix_retrofit"
        minSdkVersion 21
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    implementation 'com.android.support:cardview-v7:28.0.0'
    implementation 'com.android.support:recyclerview-v7:28.0.0'
    implementation 'com.squareup.retrofit2:retrofit:2.2.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.2.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

In the layout section of our MainActivity class, let's create the RecyclerView structure.

activity_main.xml

 

Then I create my own Model structure based on the data from the rest api.

I have created User and Links model.

json output:

[
  {
    "userId": 1,
    "id": 1,
    "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
    "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
  },
  {
    "userId": 1,
    "id": 2,
    "title": "qui est esse",
    "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
  },
  {
    "userId": 1,
    "id": 3,
    "title": "ea molestias quasi exercitationem repellat qui ipsa sit aut",
    "body": "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut"
  },
  {
    "userId": 1,
    "id": 4,
    "title": "eum et est occaecati",
    "body": "ullam et saepe reiciendis voluptatem adipisci\nsit amet autem assumenda provident rerum culpa\nquis hic commodi nesciunt rem tenetur doloremque ipsam iure\nquis sunt voluptatem rerum illo velit"
  },
  {
    "userId": 1,
    "id": 5,
    "title": "nesciunt quas odio",
    "body": "repudiandae veniam quaerat sunt sed\nalias aut fugiat sit autem sed est\nvoluptatem omnis possimus esse voluptatibus quis\nest aut tenetur dolor neque"
  },
  {
    "userId": 1,
    "id": 6,
    "title": "dolorem eum magni eos aperiam quia",
    "body": "ut aspernatur corporis harum nihil quis provident sequi\nmollitia nobis aliquid molestiae\nperspiciatis et ea nemo ab reprehenderit accusantium quas\nvoluptate dolores velit et doloremque molestiae"
  },
  {
    "userId": 1,
    "id": 7,
    "title": "magnam facilis autem",
    "body": "dolore placeat quibusdam ea quo vitae\nmagni quis enim qui quis quo nemo aut saepe\nquidem repellat excepturi ut quia\nsunt ut sequi eos ea sed quas"
  },
  {
    "userId": 1,
    "id": 8,
    "title": "dolorem dolore est ipsam",
    "body": "dignissimos aperiam dolorem qui eum\nfacilis quibusdam animi sint suscipit qui sint possimus cum\nquaerat magni maiores excepturi\nipsam ut commodi dolor voluptatum modi aut vitae"
  }

 

User.java

package umitkose.codebugfix_retrofit.Model;

import com.google.gson.annotations.SerializedName;

public class User {

    @SerializedName("userId")
    private String userId;

    @SerializedName("id")
    private String id;

    @SerializedName("title")
    private String title;

    @SerializedName("body")
    private String body;

    public String getUserId() {
        return userId;
    }

    public String getId() {
        return id;
    }

    public String getTitle() {
        return title;
    }

    public String getBody() {
        return body;
    }
}

 

In order to access the data, I created a Constant class for the required main url for the rest api.

package umitkose.codebugfix_retrofit;

public class Constant {
    public static String BASE_URL = "https://jsonplaceholder.typicode.com/";
}

Now, in order to use the Retrofit structure, let's create the RetrofitClient class.

package umitkose.codebugfix_retrofit;

import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;


public class RetrofitClient {

    private static Retrofit retrofit = null;

    public static Retrofit getClient() {

        if (retrofit==null) {
            retrofit = new Retrofit.Builder()
                    .baseUrl(Constant.BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        }
        return retrofit;
    }
}

 

Now we have created our interface class and let's examine this code in detail; With the @GET method, we have indicated that we will request a GET and ("users") parameter in addition to this method. Thus, we will draw the data with the GET method as follows:

BASE_URL: https://jsonplaceholder.typicode.com/

URL we will access with the GET method:

https://jsonplaceholder.typicode.com/posts

With the getUsers method, we see that the User type returns a list of data. Retrofit also creates the Call <List <User >> form and the structure of the data from the service with the structure of Call is indicated on the Android part.

RetrofitInterface.java

package umitkose.codebugfix_retrofit;

import java.util.List;

import retrofit2.Call;
import retrofit2.http.GET;
import umitkose.codebugfix_retrofit.Model.User;

public class RetrofitInterface {

    @GET("posts")
    Call<List<User>> getUsers();
}

RecyclerView Click Event

As you know, there is no method like SetOnItemClickListener in RecyclerView as in ListView, so we need to perform some operations to detect this by clicking on each iteration on our list. That's why we're creating an interface called CustomItemClickListener.

CustomItemClickListener.java

package umitkose.codebugfix_retrofit;

import umitkose.codebugfix_retrofit.Model.User;

public interface CustomItemClickListener {
    public void onItemClick(User user, int position);
}

For RecyclerView, we need a adapter structure where we are going to position the data.

CustomAdapter.java

Building into the identity and culture of an agency can also lead to new client work. These projects act as a road map, showing clients exciting new technologies and ideas that will differentiate you from competitors. One of our earliest projects turned our website into a brochure, optimized for the first iPad’s touch interactions. By demonstrating the final product, we went on to win a project to create a similar product for a new client.

package umitkose.codebugfix_retrofit;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.TextView;

import java.util.ArrayList;

import umitkose.codebugfix_retrofit.Model.User;

public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.MyViewHolder> implements Filterable {

    private ArrayList<User> userList;
    private ArrayList<User> filteredUserList;
    private Context context;
    private CustomItemClickListener customItemClickListener;

    public CustomAdapter(Context context,ArrayList<User> userArrayList,CustomItemClickListener customItemClickListener) {
        this.context = context;
        this.userList = userArrayList;
        this.filteredUserList = userArrayList;
        this.customItemClickListener = customItemClickListener;
    }

    @Override
    public CustomAdapter.MyViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_item, viewGroup, false);
        final MyViewHolder myViewHolder = new MyViewHolder(view);
        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // for click item listener
                customItemClickListener.onItemClick(filteredUserList.get(myViewHolder.getAdapterPosition()),myViewHolder.getAdapterPosition());
            }
        });
        return myViewHolder;
    }

    @Override
    public void onBindViewHolder(CustomAdapter.MyViewHolder viewHolder, int position) {

        viewHolder.userId.setText(filteredUserList.get(position).getUserId());
        viewHolder.id.setText(filteredUserList.get(position).getId());
        viewHolder.userTitle.setText(filteredUserList.get(position).getTitle());
        viewHolder.userBody.setText(filteredUserList.get(position).getBody());
    }

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

    @Override
    public Filter getFilter() {

        return new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence charSequence) {

                String searchString = charSequence.toString();

                if (searchString.isEmpty()) {

                    filteredUserList = userList;

                } else {

                    ArrayList<User> tempFilteredList = new ArrayList<>();

                    for (User user : userList) {

                        // search for user title
                        if (user.getTitle().toLowerCase().contains(searchString)) {

                            tempFilteredList.add(user);
                        }
                    }

                    filteredUserList = tempFilteredList;
                }

                FilterResults filterResults = new FilterResults();
                filterResults.values = filteredUserList;
                return filterResults;
            }

            @Override
            protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
                filteredUserList = (ArrayList<User>) filterResults.values;
                notifyDataSetChanged();
            }
        };
    }

    public class MyViewHolder extends RecyclerView.ViewHolder{
        private TextView userId;
        private TextView id;
        private TextView userBody;
        private TextView userTitle;
        public MyViewHolder(View view) {
            super(view);
            userId = (TextView)view.findViewById(R.id.userId);
            id = (TextView)view.findViewById(R.id.id);
            userTitle = (TextView)view.findViewById(R.id.userTitle);
            userBody = (TextView)view.findViewById(R.id.userBody);

        }
    }
}

In Android Studio, we create menu structure under res folder. Under the menu structure, we created the xml file which we call menu_item and we define the SearchView component.

menu_item.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:appcompat="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@+id/menu_search"

        android:title="Arama"

        appcompat:actionViewClass="android.support.v7.widget.SearchView"

        appcompat:showAsAction="always"/>
</menu>

Finally our MainActivity will look like that:

We have coded the Retrofit classes that we have created as follows, and if there is no problem when requesting the service, the onResponse method is triggered. Response.body () also returns the list in User type of service. We do not parse the incoming json type structure into the related models. With this structure we have created, Retrofit is doing this process and returning the data we want to us. OnFailure method is triggered if there are any errors. OnCreateOptionsMenu you will see that we define the SearchView component. The setOnQueryTextListener method triggers when there is any input change at the top. OnQueryTextChange is the method that runs when the input value is changed. onQueryTextSubmit is the method that runs when the call key is pressed after the entered value.

OnQueryTextChange also sends the value entered in the filter function found in the getFilter method.

MainActivity.java

public class MainActivity extends AppCompatActivity {

    private ProgressDialog progressDialog;
    private RecyclerView recyclerView;
    private CustomAdapter customAdapter;
    private ArrayList<User> userList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        recyclerView = (RecyclerView)findViewById(R.id.recycler_view);
        RecyclerView.LayoutManager mLayoutManager = new GridLayoutManager(getApplicationContext(), 1);
        recyclerView.setLayoutManager(mLayoutManager);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        getUserListFromRestApi();

    }

    private void getUserListFromRestApi() {

        progressDialog = createProgressDialog(MainActivity.this);

        RetrofitInterface retrofitInterface = RetrofitClient.getClient().create(RetrofitInterface.class);


        Call<List<User>> call = retrofitInterface.getUsers();
        call.enqueue(new Callback<List<User>>() {
            @Override
            public void onResponse(Call<List<User>> call, Response<List<User>> response) {

                progressDialog.dismiss();
                userList = new ArrayList<>(response.body());
                customAdapter = new CustomAdapter(getApplicationContext(), userList, new CustomItemClickListener() {
                    @Override
                    public void onItemClick(User user, int position) {

                        Toast.makeText(getApplicationContext(),""+user.getId(),Toast.LENGTH_SHORT).show();

                    }
                });
                recyclerView.setAdapter(customAdapter);

            }

            @Override
            public void onFailure(Call<List<User>> call, Throwable t) {

                progressDialog.dismiss();
                DialogHelper.getAlertWithMessage("Error",t.getMessage(),MainActivity.this);
            }
        });

    }


    public ProgressDialog createProgressDialog(Context mContext) {
        ProgressDialog dialog = new ProgressDialog(mContext);
        try {
            dialog.show();
        } catch (WindowManager.BadTokenException e) {

        }
        dialog.setCancelable(false);
        dialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
        dialog.setContentView(R.layout.dialog_layout);
        return dialog;
    }



    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater menuInflater = getMenuInflater();
        menuInflater.inflate(R.menu.menu_item, menu);

        MenuItem searchItem = menu.findItem(R.id.menu_search);

        SearchView searchView = null;
        if (searchItem != null) {
            searchView = (SearchView) searchItem.getActionView();
        }
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {

                return false;
            }

            @Override
            public boolean onQueryTextChange(String newText) {
                customAdapter.getFilter().filter(newText);
                return true;
            }
        });

        return super.onCreateOptionsMenu(menu);
    }
}

Finally do not forget to give Internet Permission on AndroidManifest.xml

 <uses-permission android:name="android.permission.INTERNET" />
After running our application, our screen output is as follows:

When we type any input:

In this lesson, we examined RecyclerView, SearchView, Retrofit Usage together. I tried to explain this application from the beginning detailed. I hope it helps everyone.

https://github.com/umitkose1/CodeBugfix/

You can download and review the source code. I'm sure it will be useful. If you have a question you can ask me at any time. Thanks to everyone 🙂

 

Leave a reply:

Your email address will not be published.

Sliding Sidebar

A few words about me

A few words about me

Software engineer who likes weekend more than weekdays. Loves food and cooks good as well. Loves to travel and gym, can never spend a weekend sitting idle at home. Independent, modern man with a traditional heart. My actions speak more than words.

Social Profiles