Wednesday, September 11, 2024

A Simple Data Binding Example

 Step-1: Enable data binding to android project ADD below line to your app level build.gradle file.

android {

    buildFeatures {

        dataBinding = true

    }


Setp-2: Add all your XML layout design inside this <layout></layout> tag

<?xml version="1.0" encoding="utf-8"?>

<layout

    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">

<androidx.constraintlayout.widget.ConstraintLayout

    android:id="@+id/main"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    tools:context=".MainActivity">


    <TextView

        android:id="@+id/greeting_text_view"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:text="@string/insert_you_name_here"

        android:textSize="30sp"

        android:textStyle="bold"

        android:typeface="sans"

        app:layout_constraintBottom_toBottomOf="parent"

        app:layout_constraintHorizontal_bias="0.532"

        app:layout_constraintLeft_toLeftOf="parent"

        app:layout_constraintRight_toRightOf="parent"

        app:layout_constraintTop_toTopOf="parent"

        app:layout_constraintVertical_bias="0.175" />


    <EditText

        android:id="@+id/name_edit_text"

        android:layout_width="0dp"

        android:layout_height="wrap_content"

        android:layout_margin="20dp"

        android:ems="10"

        android:hint="@string/insert_you_name_here"

        android:inputType="textPersonName"

        android:textSize="30sp"

        app:layout_constraintBottom_toBottomOf="parent"

        app:layout_constraintEnd_toEndOf="parent"

        app:layout_constraintStart_toStartOf="parent"

        app:layout_constraintTop_toBottomOf="@+id/greeting_text_view"

        app:layout_constraintVertical_bias="0.126" />


    <Button

        android:id="@+id/submit_button"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:text="@string/submit"

        android:textSize="30sp"

        app:layout_constraintBottom_toBottomOf="parent"

        app:layout_constraintEnd_toEndOf="parent"

        app:layout_constraintHorizontal_bias="0.498"

        app:layout_constraintStart_toStartOf="parent"

        app:layout_constraintTop_toTopOf="parent"

        app:layout_constraintVertical_bias="0.613" />


</androidx.constraintlayout.widget.ConstraintLayout>

</layout>


Step-3: Bind your XML layout to MainActivity.java


import android.os.Bundle

import android.widget.Button

import android.widget.EditText

import android.widget.TextView

import androidx.activity.enableEdgeToEdge

import androidx.appcompat.app.AppCompatActivity

import androidx.core.view.ViewCompat

import androidx.core.view.WindowInsetsCompat

import androidx.databinding.DataBindingUtil

import com.anushka.bindingdemo1.databinding.ActivityMainBinding


class MainActivity : AppCompatActivity() {

    private lateinit var binding : ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)

        enableEdgeToEdge()

//        setContentView(R.layout.activity_main)

        binding = DataBindingUtil.setContentView(this,R.layout.activity_main)

        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->

            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())

            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)

            insets

        }

//        val button = findViewById<Button>(R.id.submit_button)

//        button.setOnClickListener {

//            displayGreeting()

//        }

        binding.submitButton.setOnClickListener {

            displayGreeting()

        }

    }

    private fun displayGreeting() {

//        val messageView = findViewById<TextView>(R.id.greeting_text_view)

//        val nameText = findViewById<EditText>(R.id.name_edit_text)

//

//        messageView.text = "Hello! "+ nameText.text

        binding.apply {

            greetingTextView.text = "Hello! "+ nameEditText.text

        }

    }


Sunday, June 16, 2024

How to call Post API using Retrofit in Android using Jetpack Compose?

Note: If you are seeking Java code for Jetpack Compose, please note that Jetpack Compose is only available in Kotlin. It uses features such as coroutines, and the handling of @Composable annotations is handled by a Kotlin compiler. There is no method for Java to access these. Therefore, you cannot use Jetpack Compose if your project does not support Kotlin.


Step By Step Implementation

Step 1: Create a New Project in Android Studio

We demonstrated the application in Kotlin, so make sure you select Kotlin as the primary language while creating a New Project.


Step 2: Add the below dependency to your build.gradle File

Navigate to the Gradle Scripts > build.gradle(Module:app) and add the below dependency in the dependencies section. 


// below dependency for using the retrofit

implementation ‘com.squareup.retrofit2:retrofit:2.9.0’

implementation ‘com.squareup.retrofit2:converter-gson:2.5.0’


After adding this dependency sync your project and now move towards the AndroidManifest.xml part.  


Step 3: Adding Internet Permissions in the AndroidManifest.xml File

Navigate to the app > AndroidManifest.xml and add the below code to it. 


<!--permissions for INTERNET-->

<uses-permission android:name="android.permission.INTERNET"/>



Step 4: Adding a New Color in the Color.kt File

Navigate to app > java > your app’s package name > ui.theme > Color.kt file and add the below code to it. 


import androidx.compose.ui.graphics.Color


val Purple200 = Color(0xFF0F9D58)

val Purple500 = Color(0xFF0F9D58)

val Purple700 = Color(0xFF3700B3)

val Teal200 = Color(0xFF03DAC5)


// on below line we are adding different colors.

val greenColor = Color(0xFF0F9D58)


Step 5: Creating a Model Class for Storing Our Data  

Navigate to the app > java > your app’s package name > Right-click on it > New > Kotlin class and name it as DataModel and add the below code to it. Comments are added inside the code to understand the code in more detail.


data class DataModel(

// on below line we are creating variables for name and job

var name: String,

var job: String

)



Step 6: Creating an Interface Class for Our API Call

Navigate to the app > java > your app’s package name > Right-click on it > New > Kotlin class select it as Interface and name the file as RetrofitAPI and add below code to it. Comments are added inside the code to understand the code in more detail.


import retrofit2.Call

import retrofit2.http.Body

import retrofit2.http.GET

import retrofit2.http.POST

import retrofit2.http.PUT


interface RetrofitAPI {

// as we are making a post request to post a data

// so we are annotating it with post

// and along with that we are passing a parameter as users

@POST("users")

fun // on below line we are creating a method to post our data.

postData(@Body dataModel: DataModel?): Call<DataModel?>?

}



Step 7: Working with the MainActivity.java file

Go to the MainActivity.kt file and refer to the following code. Below is the code for the MainActivity.kt file. Comments are added inside the code to understand the code in more detail.


import android.app.Activity

import android.content.Context

import android.os.Bundle

import android.widget.Toast

import androidx.activity.ComponentActivity

import androidx.activity.compose.setContent

import androidx.compose.foundation.layout.*

import androidx.compose.material.*

import androidx.compose.runtime.*

import androidx.compose.ui.Alignment

import androidx.compose.ui.Modifier

import androidx.compose.ui.graphics.*

import androidx.compose.ui.platform.LocalContext

import androidx.compose.ui.text.TextStyle

import androidx.compose.ui.text.font.FontFamily

import androidx.compose.ui.text.font.FontWeight

import androidx.compose.ui.text.input.TextFieldValue

import androidx.compose.ui.text.style.TextAlign

import androidx.compose.ui.unit.*

import com.example.newcanaryproject.ui.theme.*

import retrofit2.Call

import retrofit2.Callback

import retrofit2.Response

import retrofit2.Retrofit

import retrofit2.converter.gson.GsonConverterFactory

import java.util.*


class MainActivity : ComponentActivity() {

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContent {

NewCanaryProjectTheme {

// on below line we are specifying background color for our application

Surface(

// on below line we are specifying modifier and color for our app

modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background

) {

// on the below line we are specifying the theme as the scaffold.

Scaffold(

// in scaffold we are specifying top bar.

topBar = {

// inside top bar we are specifying background color.

TopAppBar(backgroundColor = greenColor,

// along with that we are specifying title for our top bar.

title = {

// in the top bar we are specifying tile as a text

Text(

// on below line we are specifying text to display in top app bar.

text = "Retrofit POST Request in Android",

// on below line we are specifying modifier to fill max width.

modifier = Modifier.fillMaxWidth(),

// on below line we are specifying text alignment.

textAlign = TextAlign.Center,

// on below line we are specifying color for our text.

color = Color.White

)

})

}) {

// on the below line we are calling the pop window dialog method to display ui.

postData()

}

}

}

}

}

}


@Composable

fun postData() {

val ctx = LocalContext.current


val userName = remember {

mutableStateOf(TextFieldValue())

}

val job = remember {

mutableStateOf(TextFieldValue())

}

val response = remember {

mutableStateOf("")

}

// on below line we are creating a column.

Column(

// on below line we are adding a modifier to it

// and setting max size, max height and max width

modifier = Modifier

.fillMaxSize()

.fillMaxHeight()

.fillMaxWidth(),

// on below line we are adding vertical

// arrangement and horizontal alignment.

verticalArrangement = Arrangement.Center,

horizontalAlignment = Alignment.CenterHorizontally

) {

// on below line we are creating a text

Text(

// on below line we are specifying text as

// Session Management in Android.

text = "Retrofit POST Request in Android",

// on below line we are specifying text color.

color = greenColor,

fontSize = 20.sp,

// on below line we are specifying font family

fontFamily = FontFamily.Default,

// on below line we are adding font weight

// and alignment for our text

fontWeight = FontWeight.Bold, textAlign = TextAlign.Center

)

//on below line we are adding spacer

Spacer(modifier = Modifier.height(5.dp))

// on below line we are creating a text field for our email.

TextField(

// on below line we are specifying value for our email text field.

value = userName.value,

// on below line we are adding on value change for text field.

onValueChange = { userName.value = it },

// on below line we are adding place holder as text as "Enter your email"

placeholder = { Text(text = "Enter your name") },

// on below line we are adding modifier to it

// and adding padding to it and filling max width

modifier = Modifier

.padding(16.dp)

.fillMaxWidth(),

// on below line we are adding text style

// specifying color and font size to it.

textStyle = TextStyle(color = Color.Black, fontSize = 15.sp),

// on below line we are adding single line to it.

singleLine = true,

)

// on below line we are adding spacer

Spacer(modifier = Modifier.height(5.dp))

// on below line we are creating a text field for our email.

TextField(

// on below line we are specifying value for our email text field.

value = job.value,

// on below line we are adding on value change for text field.

onValueChange = { job.value = it },

// on below line we are adding place holder as text as "Enter your email"

placeholder = { Text(text = "Enter your job") },

// on below line we are adding modifier to it

// and adding padding to it and filling max width

modifier = Modifier

.padding(16.dp)

.fillMaxWidth(),

// on below line we are adding text style

// specifying color and font size to it.

textStyle = TextStyle(color = Color.Black, fontSize = 15.sp),

// on below line we ar adding single line to it.

singleLine = true,

)

// on below line we are adding spacer

Spacer(modifier = Modifier.height(10.dp))

// on below line we are creating a button

Button(

onClick = {

// on below line we are calling make payment method to update data.

postDataUsingRetrofit(

ctx, userName, job, response

)

},

// on below line we are adding modifier to our button.

modifier = Modifier

.fillMaxWidth()

.padding(16.dp)

) {

// on below line we are adding text for our button

Text(text = "Post Data", modifier = Modifier.padding(8.dp))

}

// on below line we are adding a spacer.

Spacer(modifier = Modifier.height(20.dp))

// on below line we are creating a text for displaying a response.

Text(

text = response.value,

color = Color.Black,

fontSize = 20.sp,

fontWeight = FontWeight.Bold, modifier = Modifier

.padding(10.dp)

.fillMaxWidth(),

textAlign = TextAlign.Center

)

}

}


private fun postDataUsingRetrofit(

ctx: Context,

userName: MutableState<TextFieldValue>,

job: MutableState<TextFieldValue>,

result: MutableState<String>

) {

var url = "https://reqres.in/api/"

// on below line we are creating a retrofit

// builder and passing our base url

val retrofit = Retrofit.Builder()

.baseUrl(url)

// as we are sending data in json format so

// we have to add Gson converter factory

.addConverterFactory(GsonConverterFactory.create())

// at last we are building our retrofit builder.

.build()

// below the line is to create an instance for our retrofit api class.

val retrofitAPI = retrofit.create(RetrofitAPI::class.java)

// passing data from our text fields to our model class.

val dataModel = DataModel(userName.value.text, job.value.text)

// calling a method to create an update and passing our model class.

val call: Call<DataModel?>? = retrofitAPI.postData(dataModel)

// on below line we are executing our method.

call!!.enqueue(object : Callback<DataModel?> {

override fun onResponse(call: Call<DataModel?>?, response: Response<DataModel?>) {

// this method is called when we get response from our api.

Toast.makeText(ctx, "Data posted to API", Toast.LENGTH_SHORT).show()

// we are getting a response from our body and

// passing it to our model class.

val model: DataModel? = response.body()

// on below line we are getting our data from model class

// and adding it to our string.

val resp =

"Response Code : " + response.code() + "\n" + "User Name : " + model!!.name + "\n" + "Job : " + model!!.job

// below line we are setting our string to our response.

result.value = resp

}


override fun onFailure(call: Call<DataModel?>?, t: Throwable) {

// we get error response from API.

result.value = "Error found is : " + t.message

}

})

}


Summary

In this tutorial you've learned how to post data to API using Retrofit in Android using Jetpack Compose.


Do you have further questions on this topic or about Retrofit in general? Let us leave a comment below.


Enjoy coding & make it rock!

How to call Post type API using Retrofit in Android?

Step by Step Implementation

Step 1: Create a New Project


Step 2: Add the below dependency in your build.gradle file


Navigate to the Gradle Scripts > build.gradle(Module:app) and add the below dependency in the dependencies section. 


// below dependency for using the retrofit

implementation ‘com.squareup.retrofit2:retrofit:2.9.0’

implementation ‘com.squareup.retrofit2:converter-gson:2.5.0’



After adding this dependency sync your project and now move towards the AndroidManifest.xml part.  


Step 3: Adding permissions to the internet in the AndroidManifest.xml file


Navigate to the app > AndroidManifest.xml and add the below code to it. 


<!--permissions for INTERNET-->

<uses-permission android:name="android.permission.INTERNET"/>


Step 4: Working with the activity_main.xml file


Navigate to the app > res > layout > activity_main.xml and add the below code to that file. Below is the code for the activity_main.xml file. 


<?xml version="1.0" encoding="utf-8"?> 

<LinearLayout

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

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical"

tools:context=".MainActivity"> 


<!--edit text field for adding name-->

<EditText

android:id="@+id/idEdtName"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_margin="10dp"

android:layout_marginTop="40dp"

android:hint="Enter your name" /> 


<!--edit text for adding job-->

<EditText

android:id="@+id/idEdtJob"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_margin="10dp"

android:hint="Enter your job" /> 


<!--button for adding data-->

<Button

android:id="@+id/idBtnPost"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_margin="20dp"

android:text="Send Data to API"

android:textAllCaps="false" /> 


<!--text view for displaying our API response-->

<TextView

android:id="@+id/idTVResponse"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_margin="10dp"

android:gravity="center_horizontal"

android:text="Response"

android:textAlignment="center"

android:textSize="15sp" /> 


<!--progress bar for loading -->

<ProgressBar

android:id="@+id/idLoadingPB"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_gravity="center"

android:visibility="gone" /> 


</LinearLayout>


Step 5: Creating a modal class for storing our data  


Navigate to the app > java > your app’s package name > Right-click on it > New > Java class and name it as DataModal and add the below code to it. Comments are added inside the code to understand the code in more detail.


public class DataModal { 

// string variables for our name and job 

private String name; 

private String job; 


public DataModal(String name, String job) { 

this.name = name; 

this.job = job; 


public String getName() { 

return name; 


public void setName(String name) { 

this.name = name; 


public String getJob() { 

return job; 


public void setJob(String job) { 

this.job = job; 

}


Step 6: Creating an Interface class for our API Call


Navigate to the app > java > your app’s package name > Right-click on it > New > Java class select it as Interface and name the file as RetrofitAPI and add below code to it. Comments are added inside the code to understand the code in more detail.


import retrofit2.Call; 

import retrofit2.http.Body; 

import retrofit2.http.POST; 


public interface RetrofitAPI { 

// as we are making a post request to post a data 

// so we are annotating it with post 

// and along with that we are passing a parameter as users 

@POST("users") 

//on below line we are creating a method to post our data. 

Call<DataModal> createPost(@Body DataModal dataModal); 

}


Step 7: Working with the MainActivity.java file


Go to the MainActivity.java file and refer to the following code. Below is the code for the MainActivity.java file. Comments are added inside the code to understand the code in more detail.


import android.os.Bundle; 

import android.view.View; 

import android.widget.Button; 

import android.widget.EditText; 

import android.widget.ProgressBar; 

import android.widget.TextView; 

import android.widget.Toast; 


import androidx.appcompat.app.AppCompatActivity; 


import retrofit2.Call; 

import retrofit2.Callback; 

import retrofit2.Response; 

import retrofit2.Retrofit; 

import retrofit2.converter.gson.GsonConverterFactory; 


public class MainActivity extends AppCompatActivity { 


// creating variables for our edittext, 

// button, textview and progressbar. 

private EditText nameEdt, jobEdt; 

private Button postDataBtn; 

private TextView responseTV; 

private ProgressBar loadingPB; 


@Override

protected void onCreate(Bundle savedInstanceState) { 

super.onCreate(savedInstanceState); 

setContentView(R.layout.activity_main); 

// initializing our views 

nameEdt = findViewById(R.id.idEdtName); 

jobEdt = findViewById(R.id.idEdtJob); 

postDataBtn = findViewById(R.id.idBtnPost); 

responseTV = findViewById(R.id.idTVResponse); 

loadingPB = findViewById(R.id.idLoadingPB); 

// adding on click listener to our button. 

postDataBtn.setOnClickListener(new View.OnClickListener() { 

@Override

public void onClick(View v) { 

// validating if the text field is empty or not. 

if (nameEdt.getText().toString().isEmpty() && jobEdt.getText().toString().isEmpty()) { 

Toast.makeText(MainActivity.this, "Please enter both the values", Toast.LENGTH_SHORT).show(); 

return; 

// calling a method to post the data and passing our name and job. 

postData(nameEdt.getText().toString(), jobEdt.getText().toString()); 

}); 


private void postData(String name, String job) { 

// below line is for displaying our progress bar. 

loadingPB.setVisibility(View.VISIBLE); 

// on below line we are creating a retrofit 

// builder and passing our base url 

Retrofit retrofit = new Retrofit.Builder() 

.baseUrl("https://reqres.in/api/") 

// as we are sending data in json format so 

// we have to add Gson converter factory 

.addConverterFactory(GsonConverterFactory.create()) 

// at last we are building our retrofit builder. 

.build(); 

// below line is to create an instance for our retrofit api class. 

RetrofitAPI retrofitAPI = retrofit.create(RetrofitAPI.class); 

// passing data from our text fields to our modal class. 

DataModal modal = new DataModal(name, job); 

// calling a method to create a post and passing our modal class. 

Call<DataModal> call = retrofitAPI.createPost(modal); 

// on below line we are executing our method. 

call.enqueue(new Callback<DataModal>() { 

@Override

public void onResponse(Call<DataModal> call, Response<DataModal> response) { 

// this method is called when we get response from our api. 

Toast.makeText(MainActivity.this, "Data added to API", Toast.LENGTH_SHORT).show(); 

// below line is for hiding our progress bar. 

loadingPB.setVisibility(View.GONE); 

// on below line we are setting empty text 

// to our both edit text. 

jobEdt.setText(""); 

nameEdt.setText(""); 

// we are getting response from our body 

// and passing it to our modal class. 

DataModal responseFromAPI = response.body(); 

// on below line we are getting our data from modal class and adding it to our string. 

String responseString = "Response Code : " + response.code() + "\nName : " + responseFromAPI.getName() + "\n" + "Job : " + responseFromAPI.getJob(); 

// below line we are setting our 

// string to our text view. 

responseTV.setText(responseString); 


@Override

public void onFailure(Call<DataModal> call, Throwable t) { 

// setting text to our text view when 

// we get error response from API. 

responseTV.setText("Error found is : " + t.getMessage()); 

}); 

}

Friday, June 14, 2024

Retrofit 2 — Receive Plain-String Responses

Android apps usually interact with REST APIs, which often use JSON as a data format. We've focused almost all of our tutorials on sending JSON or XML requests, and converting JSON or XML responses.


Scalars Converter for Plain Strings

To receive plain-text or plain-string responses you can utilize the scalars converter. You can integrate the converter by adding it as a dependency to your app's build.gradle:


dependencies {  

    implementation 'com.squareup.retrofit2:retrofit:2.9.0'

    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'

    implementation 'com.squareup.retrofit2:converter-scalars:2.5.0'//You need to add this

    implementation 'com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.2'

}


Next, you need to describe the endpoint you want to interact with. In this demo case, you'll use a GET request with the dynamic URL feature to pass any URL to the method, and set the response type as String.


@GET()

Call<String> getStringResponse(@Url String url);


You've finished the preparations. Next, you can use Retrofit to execute requests with the scalars converter and the created endpoint. You'll create a Retrofit object with the Retrofit builder and configure it to use the scalars converter:


Retrofit retrofit = new Retrofit.Builder()  

        .addConverterFactory(ScalarsConverterFactory.create())//You need to add this

        .addConverterFactory(GsonConverterFactory.create())

        .baseUrl("https://your.base.url/")

        .build();

The final step is to use the Retrofit object to execute a request:


ScalarService scalarService = retrofit.create(ScalarService.class);  

Call<String> stringCall = scalarService.getStringResponse("https://futurestud.io");  

stringCall.enqueue(new Callback<String>() {  

    @Override

    public void onResponse(Call<String> call, Response<String> response) {

        if (response.isSuccessful()) {

            String responseString = response.body();

            // todo: do something with the response string

        }


    }


    @Override

    public void onFailure(Call<String> call, Throwable t) {


    }

});


In the code snippet above, you're executing a GET request for our homepage futurestud.io. Consequently, you'll receive a long string back (which is actually the website's HTML source). You can also use the above approach to receive plain strings from your API.


Summary

In this tutorial you've learned how you can set up Retrofit to access plain-string responses from requests. This could be a regular API call, where the server returns a string. But this could also be the HTML source of a website.

Do you have further questions on this topic or about Retrofit in general? Let us leave a comment below.


Enjoy coding & make it rock!

Thursday, September 23, 2021

Offline Load More Data with RecyclerView in android.

Step 1. Create a project step by step

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<include layout="@layout/layout_toolbar" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycleView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="8dp" />
</LinearLayout> 

 layout_toolbar.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
android:layout_height="?android:attr/actionBarSize"
android:background="@color/purple_200"/>
</LinearLayout>


MainActivity.Java
public class MainActivity extends AppCompatActivity {
private Toolbar mToolbar;
private RecyclerView mRecyclerView;
private List<UserModel> mUsers = new ArrayList<>();
private UserAdapter mUserAdapter;

public static OnLoadMoreListener mOnLoadMoreListener;

public static boolean isLoading;

private int visibleThreshold = 5;

private int lastVisibleItem, totalItemCount;

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

mToolbar = (Toolbar) findViewById(R.id.toolbar);
mToolbar.setTitle("LoadMoreRecycleView");
for (int i = 0; i < 10; i++) {
UserModel user = new UserModel();
user.setName("Name " + i);
user.setEmail("vimalku" + i + "@gmail.com");
mUsers.add(user);
}
mRecyclerView = (RecyclerView) findViewById(R.id.recycleView);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mUserAdapter = new UserAdapter(this, mUsers);
mRecyclerView.setAdapter(mUserAdapter);
final LinearLayoutManager linearLayoutManager = (LinearLayoutManager) mRecyclerView.getLayoutManager();
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
totalItemCount = linearLayoutManager.getItemCount();
lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
if (!isLoading && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
if (mOnLoadMoreListener != null) {
mOnLoadMoreListener.onLoadMore();
}
isLoading = true;
}
}
});
mUserAdapter.setOnLoadMoreListener(new OnLoadMoreListener() {
@Override public void onLoadMore() {
Log.e("haint", "Load More");
mUsers.add(null);
mUserAdapter.notifyItemInserted(mUsers.size() - 1);
//Load more data for reyclerview
new Handler().postDelayed(new Runnable() {
@Override public void run() {
Log.e("haint", "Load More 2");
//Remove loading item
mUsers.remove(mUsers.size() - 1);
mUserAdapter.notifyItemRemoved(mUsers.size());
//Load data
int index = mUsers.size();
int end = index + 10;
for (int i = index; i < end; i++) {
UserModel user = new UserModel();
user.setName("Name " + i);
user.setEmail("vimalku" + i + "@gmail.com");
mUsers.add(user);
}
mUserAdapter.notifyDataSetChanged();
mUserAdapter.setLoaded();
}
}, 5000);
}
});
}
static class LoadingViewHolder extends RecyclerView.ViewHolder {
public ProgressBar progressBar;
public LoadingViewHolder(View itemView) {
super(itemView);
progressBar = (ProgressBar) itemView.findViewById(R.id.progressBar1);
}
}

}
layout_user_item.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
card_view:cardCornerRadius="5dp"
card_view:cardUseCompatPadding="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:selectableItemBackground">
<TextView android:id="@+id/tvName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:text="Name"
android:textColor="@android:color/black"
android:textSize="18sp" />
<TextView android:id="@+id/tvEmailId"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/tvName"
android:layout_margin="5dp"
android:text="Email Id"
android:textColor="@android:color/black"
android:textSize="12sp" />
</RelativeLayout>
</androidx.cardview.widget.CardView>
  
layout_loading_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ProgressBar android:id="@+id/progressBar1"
android:layout_width="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_height="wrap_content" />
</LinearLayout>


 
 
UserAdapter.Java:
class UserAdapter extends RecyclerView.Adapter <RecyclerView.ViewHolder > {
private Context context;
private List<UserModel> mUsers;

private final int VIEW_TYPE_ITEM = 0;

private final int VIEW_TYPE_LOADING = 1;

public UserAdapter(Context context, List<UserModel> mUsers) {
this.context = context;
this.mUsers = mUsers;
}

public void setOnLoadMoreListener(OnLoadMoreListener mOnLoadMoreListener) {
MainActivity.mOnLoadMoreListener = mOnLoadMoreListener;
}
@Override public int getItemViewType(int position) {
return mUsers.get(position) == null ? VIEW_TYPE_LOADING : VIEW_TYPE_ITEM;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == VIEW_TYPE_ITEM) {
View view = LayoutInflater.from(context).inflate(R.layout.layout_user_item, parent, false);
return new UserViewHolder(view);
} else if (viewType == VIEW_TYPE_LOADING) {
View view = LayoutInflater.from(context).inflate(R.layout.layout_loading_item, parent, false);
return new MainActivity.LoadingViewHolder(view);
}
return null;
}
@Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof UserViewHolder) {
UserModel user = mUsers.get(position);
UserViewHolder userViewHolder = (UserViewHolder) holder;
userViewHolder.tvName.setText(user.getName());
userViewHolder.tvEmailId.setText(user.getEmail());
} else if (holder instanceof MainActivity.LoadingViewHolder) {
MainActivity.LoadingViewHolder loadingViewHolder = (MainActivity.LoadingViewHolder) holder;
loadingViewHolder.progressBar.setIndeterminate(true);
}
}
@Override
public int getItemCount() {
return mUsers == null ? 0 : mUsers.size();
}

static class UserViewHolder extends RecyclerView.ViewHolder {
public TextView tvName;
public TextView tvEmailId;
public UserViewHolder(View itemView) {
super(itemView);
tvName = (TextView) itemView.findViewById(R.id.tvName);
tvEmailId = (TextView) itemView.findViewById(R.id.tvEmailId);
}
}
public void setLoaded() {
MainActivity.isLoading = false;
}
}
UserModel.Java:
public class UserModel {
private String name;
private String email;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
OnLoadMoreListener interface:
public interface OnLoadMoreListener {
void onLoadMore();

 

A Simple Data Binding Example

  Step-1: Enable data binding to android project ADD below line to your app level build.gradle file. android {     buildFeatures {        ...