Hi Every one will you please help me to fatch data from nested JSON array in recycler view using retrofit from starting to end thankyou
See Overview Of All activity or class or interfaces whichever we need to make & same we will make it below
Here we hide some API data for security purpose & u can remove some Common class data as we set static sound method in it so
we have to set as a Main Image Item or Sub Image Item as per API
API -> https://________.in/childrenart/kidsgames.json
Here We have JSON Format like below - Nested Array
[
{
"id": 1,
"profile_image": "https://________.in/childrenart/profileimages/kg_maze_games.png",
"category_name": "kg_maze_games",
"category_images": [
{
"id": 1,
"image_url": "https://________.in/childrenart/category_images/kg_maze_games/kg_maze_games_01.png"
},
{
"id": 2,
"image_url": "https://________.in/childrenart/category_images/kg_maze_games/kg_maze_games_02.png"
}
]
},
{
"id": 2,
"profile_image": "https://________.in/childrenart/profileimages/kg_match_count.png",
"category_name": "kg_match_count",
"category_images": [
{
"id": 1,
"image_url": "https://________.in/childrenart/category_images/kg_match_count/kg_match_count_01.png"
},
{
"id": 2,
"image_url": "https://________.in/childrenart/category_images/kg_match_count/kg_match_count_02.png"
}
]
}
]
https://www.jsonschema2pojo.org/
Convert this JSON to POJO You will get 2 Ready Model Class
Dont forget to Set Source type: as a JSON & Annotation style: Gson in the below link
Paste your JSON Data & Get model class as a Zip or copy from Preview
https://www.jsonschema2pojo.org/
Now Create new Project in java & Add below Depndencies
in -> build.gradle(Module)
// gson Retrofit
implementation 'com.google.code.gson:gson:2.8.7'
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.okhttp3:logging-interceptor:4.2.1'
// glide
implementation 'com.github.bumptech.glide:glide:4.13.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.13.0'
in -> Gradle.properties
android.nonTransitiveRClass=true
android.enableJetifier=true
Now Lest start to make classes , interfaces , activities as below 14 step wise
To Get Main Iamge From API (profile_image)
Step Type - Name
(01) Model Class - Main Image Item
(02) Model Class - Sub Image Item
(03) Interface(Api) - KidsGameApiCall
(04) Activity(Main) - KidsGameActivity
(05) Activity(MainXML-Layout) - activity_kids_game
(06) Class - Common
(07) Custom Layout - item_main_image
(08) Adapter - KidsGameAdapter
(09) Interface - KidsGamesItemClick
To Get Sub Iamge From Same API (category_name)
Type - Name
(10) Activity(Main) - KidsGameListActivity
(11) Activity(MainXML-Layout) - activity_kids_game_list
(12) Custom Layout - item_sub_image
(13) Adapter - KidsGameListAdapter
(14) Interface - KidsGamesListItemClick
(01) Model Class - Main Image Item
package com.example.childrenartsdrawing.models;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import java.util.ArrayList;
public class MainImageItem {
@SerializedName("id")
@Expose
private Integer id;
@SerializedName("profile_image")
@Expose
private String profileImage;
@SerializedName("category_name")
@Expose
private String categoryName;
@SerializedName("category_images")
@Expose
private ArrayList<SubImageItem> categoryImages = null;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getProfileImage() {
return profileImage;
}
public void setProfileImage(String profileImage) {
this.profileImage = profileImage;
}
public String getCategoryName() {
return categoryName;
}
public void setCategoryName(String categoryName) {
this.categoryName = categoryName;
}
public ArrayList<SubImageItem> getCategoryImages() {
return categoryImages;
}
public void setCategoryImages(ArrayList<SubImageItem> categoryImages) {
this.categoryImages = categoryImages;
}
}
(02) Model Class - Sub Image Item
package com.example.childrenartsdrawing.models;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class SubImageItem {
@SerializedName("id")
@Expose
private Integer id;
@SerializedName("image_url")
@Expose
private String imageUrl;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getImageUrl() {
return imageUrl;
}
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
}
(03) Interface(Api) - KidsGameApiCall
package com.example.childrenartsdrawing.interfaces;
import com.example.childrenartsdrawing.models.MainImageItem;
import java.util.ArrayList;
import retrofit2.Call;
import retrofit2.http.GET;
public interface KidsGamesApiCall {
@GET("kidsgames.json")
Call<ArrayList<MainImageItem>> getMainImageList();
}
(04) Activity(Main) - KidsGameActivity
package com.example.childrenartsdrawing.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.GridLayoutManager;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;
import com.example.childrenartsdrawing.adapter.KidsGameAdapter;
import com.example.childrenartsdrawing.common.Common;
import com.example.childrenartsdrawing.databinding.ActivityKidsGameBinding;
import com.example.childrenartsdrawing.interfaces.KidsGamesApiCall;
import com.example.childrenartsdrawing.interfaces.KidsGamesItemClick;
import com.example.childrenartsdrawing.models.MainImageItem;
import java.util.ArrayList;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class KidsGameActivity extends AppCompatActivity implements KidsGamesItemClick {
ActivityKidsGameBinding binding;
ArrayList<MainImageItem> mainImageItems = new ArrayList<>();
KidsGameAdapter adapter;
Retrofit retrofit;
KidsGamesApiCall services;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
binding = ActivityKidsGameBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
init();
toolBarClick();
}
private void init() {
binding.myToolbar.tvTitle.setText("Kids Game");
binding.myToolbar.icActionSetting.setVisibility(View.INVISIBLE);
callImageAPI();
}
private void toolBarClick() {
binding.myToolbar.icActionBack.setOnClickListener(v -> {
onBackPressed();
Common.myButtonSound(this);
});
}
private void callImageAPI() {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
retrofit = new Retrofit.Builder()
.baseUrl("https://___________.in/childrenart/")
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build();
services = retrofit.create(KidsGamesApiCall.class);
drawingData();
}
private void drawingData() {
Call<ArrayList<MainImageItem>> call = services.getMainImageList();
call.enqueue(new Callback<ArrayList<MainImageItem>>() {
@Override
public void onResponse(@NonNull Call<ArrayList<MainImageItem>> call, @NonNull Response<ArrayList<MainImageItem>> response) {
if (response.isSuccessful()) {
mainImageItems = response.body();
Common.mainListImage = mainImageItems; // save received list in Common
if (Common.mainListImage != null) {
initRecyclerView(); // Here we set adapter
binding.llProgress.setVisibility(View.GONE);
}
}
}
@Override
public void onFailure(@NonNull Call<ArrayList<MainImageItem>> call, @NonNull Throwable t) {
Toast.makeText(KidsGameActivity.this, "Please Check Your Internet Connection", Toast.LENGTH_SHORT).show();
}
});
}
private void initRecyclerView() {
adapter = new KidsGameAdapter(KidsGameActivity.this, mainImageItems, this);
GridLayoutManager layoutManager = new GridLayoutManager(KidsGameActivity.this, 2);
binding.rvDrawingBookList.setLayoutManager(layoutManager);
binding.rvDrawingBookList.setAdapter(adapter);
}
private void passDrawingPosition(int position) {
Intent intent = new Intent(this, KidsGameListActivity.class);
intent.putExtra("KIDS_GAME_POSITION", position);
overridePendingTransition(0, 0);
startActivity(intent);
}
@Override
public void OnKidsGameItemClick(MainImageItem kidsGameItem, int position) {
Common.myBtnCategorySound(this);
passDrawingPosition(position);
}
@Override
protected void onStart() {
super.onStart();
if (Common.homeMusic != null)
Common.homeMusic.start();
}
@Override
protected void onPause() {
super.onPause();
Common.homeMusic.pause();
}
@Override
public void onBackPressed() {
super.onBackPressed();
finish();
}
}
(05) Activity(MainXML-Layout) - activity_kids_game You Can make custom layout for custom_action_bar
<?xml version="1.0" encoding="utf-8"?>
<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="match_parent"
android:background="@drawable/bg_drawing"
android:gravity="center"
android:orientation="vertical"
tools:context=".activities.DrawingBookActivity">
<include
android:id="@+id/my_toolbar"
layout="@layout/custom_action_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
app:layout_constraintBottom_toTopOf="@+id/llDrawingBook"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.083"
tools:layout_editor_absoluteX="10dp" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/llProgress"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.airbnb.lottie.LottieAnimationView
android:layout_width="168dp"
android:layout_height="217dp"
android:layout_gravity="bottom"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:lottie_autoPlay="true"
app:lottie_imageAssetsFolder="images"
app:lottie_loop="true"
app:lottie_rawRes="@raw/progress_2"
tools:ignore="MissingConstraints" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvDrawingBookList"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
(06) Class - Common
package com.example.childrenartsdrawing.common;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.media.MediaPlayer;
import com.example.childrenartsdrawing.R;
import com.example.childrenartsdrawing.models.MainImageItem;
import com.example.childrenartsdrawing.models.MyGalleryItem;
import java.util.ArrayList;
import java.util.Random;
public class Common {
// Here we store MainImageItem in array list
public static ArrayList<MainImageItem> mainListImage;
public static int musicHome, buttonSound, btnCancel,buttonDelete;
public static MediaPlayer homeMusic, buttonClickSound,mpCancel, mpClickSound,mpBtnBig,mpBtnCategory,mpItemSound,deleteSound;
public static Boolean soundOn = true;
public static ArrayList<MyGalleryItem> MY_GALLERY_IMAGES;
public static void myMusicStart(Context mContext) {
musicHome = R.raw.music12bg;
homeMusic = MediaPlayer.create(mContext, musicHome);
homeMusic.start();
}
public static void myButtonSound(Context mContext) {
if (Common.soundOn) {
buttonSound = R.raw.sound_btn_play;
buttonClickSound = MediaPlayer.create(mContext, buttonSound);
buttonClickSound.start();
}
}
public static void onClickSound(Context mContext) {
if (Common.soundOn) {
Random random = new Random();
int[] myMusic = {R.raw.music_01, R.raw.music_02, R.raw.music_03, R.raw.music_04, R.raw.music_05, R.raw.music_06, R.raw.music_07, R.raw.music_08, R.raw.music_09, R.raw.music_10, R.raw.music_11};
int i = random.nextInt(myMusic.length);
mpClickSound = MediaPlayer.create(mContext, myMusic[i]);
mpClickSound.start();
}
}
}
(07) Custom Layout - item_main_image
<?xml version="1.0" encoding="utf-8"?><!-- 2 -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/llCustomDrawAct"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:background="@color/transparent">
<ImageView
android:id="@+id/ivMainItem"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_gravity="center"/>
</LinearLayout>
(08) Adapter - KidsGameAdapter
package com.example.childrenartsdrawing.adapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import com.example.childrenartsdrawing.databinding.ItemMainImageBinding;
import com.example.childrenartsdrawing.interfaces.KidsGamesItemClick;
import com.example.childrenartsdrawing.models.MainImageItem;
import java.util.ArrayList;
public class KidsGameAdapter extends RecyclerView.Adapter<KidsGameAdapter.MyViewHolder> {
ItemMainImageBinding binding;
private Context context;
private ArrayList<MainImageItem> itemList;
// i3 & create constructor also
private KidsGamesItemClick setMainItemClick;
public KidsGameAdapter(Context context, ArrayList<MainImageItem> itemList, KidsGamesItemClick setMainItemClick) {
this.context = context;
this.itemList = itemList;
this.setMainItemClick = setMainItemClick;
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
binding = ItemMainImageBinding.inflate(LayoutInflater.from(context),parent,false);
MyViewHolder holder = new MyViewHolder(binding);
return holder;
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
MainImageItem item = itemList.get(position);
// holder.binding.tvMainItem.setText(item.getCategoryName());
Glide.with(context).load(item.getProfileImage()).into(holder.binding.ivMainItem);
// i4
holder.binding.ivMainItem.setOnClickListener(view -> setMainItemClick.OnKidsGameItemClick(item,position));
}
@Override
public int getItemCount() {
return itemList.size();
}
class MyViewHolder extends RecyclerView.ViewHolder {
ItemMainImageBinding binding;
public MyViewHolder(@NonNull ItemMainImageBinding binding) {
super(binding.getRoot());
this.binding = binding;
}
}
}
(09) Interface - KidsGamesItemClick
package com.example.childrenartsdrawing.interfaces;
import com.example.childrenartsdrawing.models.MainImageItem;
public interface KidsGamesItemClick {
void OnKidsGameItemClick(MainImageItem kidsGameItem, int position);
}
(10) Activity(Main) - KidsGameListActivity
package com.example.childrenartsdrawing.activities;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;
import com.example.childrenartsdrawing.adapter.KidsGameListAdapter;
import com.example.childrenartsdrawing.common.Common;
import com.example.childrenartsdrawing.databinding.ActivityKidsGameListBinding;
import com.example.childrenartsdrawing.interfaces.KidsGamesListItemClick;
import com.example.childrenartsdrawing.models.SubImageItem;
public class KidsGameListActivity extends AppCompatActivity implements KidsGamesListItemClick {
ActivityKidsGameListBinding binding;
int mMainListPos;
KidsGameListAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
binding = ActivityKidsGameListBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
mMainListPos = getIntent().getIntExtra("KIDS_GAME_POSITION", 0);
init();
toolBarClick();
binding.myToolbar.icActionSetting.setVisibility(View.GONE);
}
private void init() {
initRecyclerView();
}
private void initRecyclerView() {
adapter = new KidsGameListAdapter(this, Common.mainListImage.get(mMainListPos).getCategoryImages(), this);
LinearLayoutManager layoutManager = new GridLayoutManager(this, 2, GridLayoutManager.VERTICAL, false);
binding.rvSubList.setLayoutManager(layoutManager);
binding.rvSubList.setAdapter(adapter);
}
@Override
protected void onStart() {
super.onStart();
if (Common.homeMusic != null)
Common.homeMusic.start();
}
@Override
protected void onPause() {
super.onPause();
if (Common.homeMusic != null)
Common.homeMusic.pause();
}
private void toolBarClick() {
binding.myToolbar.icActionBack.setOnClickListener(v -> {
onBackPressed();
Common.myButtonSound(this);
});
}
@Override
public void onBackPressed() {
super.onBackPressed();
finish();
}
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
public void setKidsListSubItemClick(SubImageItem subImageItem, int position) {
String subImageUrl = subImageItem.getImageUrl();
String activityName = KidsGameListActivity.class.getSimpleName();
Intent myIntent = new Intent(this, PaintDrawActivity.class);
Bundle bundle = new Bundle();
bundle.putString("ACTIVITY_NAME",activityName);
bundle.putString("SUB_IMAGE_URL", subImageUrl);
bundle.putInt("SUB_IMAGE_POSITION", position);
bundle.putInt("MAIN_IMAGE_POSITION", mMainListPos);
myIntent.putExtras(bundle);
Common.myBtnItemSound(this);
startActivityForResult(myIntent, 0);
}
}
(11) Activity(MainXML-Layout) - activity_kids_game_list
<?xml version="1.0" encoding="utf-8"?>
<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="match_parent"
android:orientation="vertical"
android:background="@drawable/bg_drawing"
tools:context=".activities.DrawingBookListActivity">
<LinearLayout
android:id="@+id/llLoader"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:visibility="gone"
android:orientation="vertical">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<include
android:id="@+id/my_toolbar"
layout="@layout/custom_action_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
app:layout_constraintBottom_toTopOf="@+id/llDrawingBook"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.083"
tools:layout_editor_absoluteX="10dp" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvSubList"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
(12) Custom Layout - item_sub_image
<?xml version="1.0" encoding="utf-8"?><!-- 2 -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/card_click"
android:layout_width="match_parent"
android:layout_height="160dp"
android:layout_gravity="center"
android:foreground="?android:attr/selectableItemBackground"
android:orientation="horizontal"
android:padding="5dp"
android:layout_margin="10dp">
<LinearLayout
android:background="@drawable/ic_image_background"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/ivSubItem"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="5dp"
android:layout_margin="10dp"/>
</LinearLayout>
</LinearLayout>
(13) Adapter - KidsGameListAdapter
package com.example.childrenartsdrawing.adapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import com.example.childrenartsdrawing.databinding.ItemSubImageBinding;
import com.example.childrenartsdrawing.interfaces.KidsGamesListItemClick;
import com.example.childrenartsdrawing.models.SubImageItem;
import java.util.ArrayList;
public class KidsGameListAdapter extends RecyclerView.Adapter<KidsGameListAdapter.MyViewHolder> {
ItemSubImageBinding binding;
private Context context;
private ArrayList<SubImageItem> itemList;
// i3 & create constructor also
private KidsGamesListItemClick subItemClick;
public KidsGameListAdapter(Context context, ArrayList<SubImageItem> itemList, KidsGamesListItemClick subItemClick) {
this.context = context;
this.itemList = itemList;
this.subItemClick = subItemClick;
}
@NonNull
@Override
public KidsGameListAdapter.MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
binding = ItemSubImageBinding.inflate(LayoutInflater.from(context),parent,false);
KidsGameListAdapter.MyViewHolder holder = new KidsGameListAdapter.MyViewHolder(binding);
return holder;
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
SubImageItem item = itemList.get(position);
Glide.with(context).load(itemList.get(position).getImageUrl()).into(holder.binding.ivSubItem);
holder.binding.cardClick.setOnClickListener(view -> {
subItemClick.setKidsListSubItemClick(item,position);
});
}
@Override
public int getItemCount() {
return itemList.size();
}
class MyViewHolder extends RecyclerView.ViewHolder {
ItemSubImageBinding binding;
public MyViewHolder(@NonNull ItemSubImageBinding binding) {
super(binding.getRoot());
this.binding = binding;
}
}
}
(14) Interface - KidsGamesListItemClick
package com.example.childrenartsdrawing.interfaces;
import com.example.childrenartsdrawing.models.SubImageItem;
public interface KidsGamesListItemClick {
void setKidsListSubItemClick(SubImageItem subImageItem, int position);
}