Trying to take the JSONs from the API using jsonlint and apply to the recyclerview without success, the application crashes without any warning in the debugger.
Layouts:
dt_product:
<?xml version="1.0" encoding="utf-8"?>
<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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000"
android:orientation="vertical">
<com.google.android.material.button.MaterialButton
android:id="@+id/records_BTN_back"
style="@style/Widget.Material3.Button.TextButton.Icon"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:iconSize="45dp"
app:icon="@drawable/back"
app:iconTint="@null"
/>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#000000"
android:orientation="vertical"
android:padding="32dp">
<ImageView
android:id="@+id/ivImage2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
android:src="@drawable/paris"
android:contentDescription="@string/todo" />
</androidx.appcompat.widget.LinearLayoutCompat>
<com.google.android.material.textview.MaterialTextView
android:id="@+id/descriptionTextView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#000000"
android:gravity="center"
android:text="@string/details"
android:textColor="@color/white"
android:textSize="12sp"
android:textStyle="bold" />
</androidx.appcompat.widget.LinearLayoutCompat>
</RelativeLayout>
activity_rv_prodcts:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvProducts"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
rv_product_item:
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="216dp"
android:layout_margin="2dp"
android:id="@+id/item"
app:cardCornerRadius="12dp"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/ivImage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
android:src="@drawable/paris"
android:contentDescription="@string/todo" />
<TextView
android:id="@+id/tvTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:background="#595959"
android:gravity="center"
android:text="paris"
android:textColor="@color/white"
android:textSize="10sp"
android:textStyle="bold"/>
</RelativeLayout>
</androidx.cardview.widget.CardView>
myapplication-adaptors,networking: ActivityRvProducts:
package com.example.myapplication;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.example.myapplication.adaptors.RVRetrofitAdaptor;
import com.example.myapplication.networking.ProductResult;
import com.example.myapplication.networking.RetrofitClient;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class ActivityRvProducts extends AppCompatActivity implements RVRetrofitAdaptor.OnItemClickListener {
RecyclerView rvProducts;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rv_prodcts);
rvProducts = findViewById(R.id.rvProducts);
getProducts();
}
private void getProducts() {
Call<List<ProductResult>> apiCall = RetrofitClient.getInstance().getApis().getProducts();
apiCall.enqueue(new Callback<List<ProductResult>>() {
@Override
public void onResponse(Call<List<ProductResult>> call, Response<List<ProductResult>> response) {
List<ProductResult> productResult = response.body();
Toast.makeText(ActivityRvProducts.this, "Got Products", Toast.LENGTH_SHORT).show();
setAdapter(productResult);
}
@Override
public void onFailure(Call<List<ProductResult>> call, Throwable t) {
Toast.makeText(ActivityRvProducts.this, "Error", Toast.LENGTH_SHORT).show();
}
});
}
private void setAdapter(List<ProductResult> productResults) {
rvProducts.setLayoutManager(new LinearLayoutManager(this));
RVRetrofitAdaptor rvRetrofitAdaptor = new RVRetrofitAdaptor(this, productResults);
rvRetrofitAdaptor.setOnItemClickListener(this); // Set the click listener
rvProducts.setAdapter(rvRetrofitAdaptor);
}
// Implementing onItemClick method of the OnItemClickListener interface
@Override
public void onItemClick(String productId) {
// Handle item click here, start DetailActivity with necessary data
Intent intent = new Intent(this, DetailActivity.class);
intent.putExtra("productId", productId);
startActivity(intent);
}
}
DetailActivity:
package com.example.myapplication;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.bumptech.glide.Glide;
import com.example.myapplication.networking.RetrofitClient;
public class DetailActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dt_product);
// Retrieve data passed from previous activity
Bundle extras = getIntent().getExtras();
if (extras != null) {
String productId = extras.getString("productId");
// Display the data as needed in your detail layout
ImageView imageView = findViewById(R.id.ivImage2);
TextView descriptionTextView = findViewById(R.id.descriptionTextView);
// Use RetrofitClient to fetch product details
RetrofitClient.getInstance().fetchProductDetails(productId, new RetrofitClient.OnProductDetailsFetchedListener() {
@Override
public void onProductDetailsFetched(String[] productDetails) {
// If product details are fetched successfully
String description = productDetails[0];
String imageUrl = productDetails[1];
// Load image using Glide
Glide.with(DetailActivity.this).load(imageUrl).placeholder(R.drawable.paris).into(imageView);
descriptionTextView.setText(description);
}
@Override
public void onProductDetailsFetchFailed() {
// Handle case when fetching fails
Toast.makeText(DetailActivity.this, "Failed to load product details", Toast.LENGTH_SHORT).show();
}
});
} else {
// Handle case when no data is passed
Toast.makeText(this, "No data available", Toast.LENGTH_SHORT).show();
}
// Find and set click listener for the back button
findViewById(R.id.records_BTN_back).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Finish the current activity to go back to the previous one
finish();
}
});
}
}
MainActivity:
package com.example.myapplication;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageButton;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Find the start button
ImageButton startBtn = findViewById(R.id.startBtn);
// Set OnClickListener for the start button
startBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Start ActivityRvProducts when the button is clicked
Intent intent = new Intent(MainActivity.this, ActivityRvProducts.class);
startActivity(intent);
}
});
}
}
adaptors-RVRetrofitAdaptor:
package com.example.myapplication.adaptors;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import com.example.myapplication.R;
import com.example.myapplication.networking.ProductResult;
import java.util.List;
public class RVRetrofitAdaptor extends RecyclerView.Adapter<RVRetrofitAdaptor.RVHolderRetrofit> {
private Context mContext;
private List<ProductResult> mProductResults;
private OnItemClickListener mListener;
public RVRetrofitAdaptor(Context context, List<ProductResult> productResults) {
this.mContext = context;
this.mProductResults = productResults;
}
public void setOnItemClickListener(OnItemClickListener listener) {
this.mListener = listener;
}
@NonNull
@Override
public RVHolderRetrofit onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.rv_product_item, parent, false);
return new RVHolderRetrofit(view);
}
@Override
public void onBindViewHolder(@NonNull RVHolderRetrofit holder, int position) {
ProductResult product = mProductResults.get(position);
holder.tvTitle.setText(product.getTitle());
Glide.with(mContext)
.load(product.getProductImage())
.placeholder(R.drawable.paris)
.error(R.drawable.paris)
.into(holder.ivImage);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mListener != null) {
mListener.onItemClick(product.getId());
}
}
});
}
@Override
public int getItemCount() {
return mProductResults.size();
}
public static class RVHolderRetrofit extends RecyclerView.ViewHolder {
TextView tvTitle;
ImageView ivImage;
public RVHolderRetrofit(@NonNull View itemView) {
super(itemView);
ivImage = itemView.findViewById(R.id.ivImage);
tvTitle = itemView.findViewById(R.id.tvTitle);
}
}
// Interface for item click
public interface OnItemClickListener {
void onItemClick(String productId);
}
}
networking: APIs:
package com.example.myapplication.networking;
import java.util.List;
import retrofit2.http.GET;
import retrofit2.Call;
public interface APIs {
String BASE_URL = "https://fakestoreapi.com/";
@GET("products")
Call<List<ProductResult>> getProducts();
}
ProductResult:
package com.example.myapplication.networking;
import com.google.gson.annotations.SerializedName;
public class ProductResult {
@SerializedName("id")
String id;
@SerializedName("title")
String title;
@SerializedName("description")
String description;
@SerializedName("image")
String productImage;
public String getId() {
return id;
}
public String getTitle() {
return title;
}
public String getProductImage() {
return productImage;
}
public String getDescription() {
return description;
}
}
RetrofitClient:
package com.example.myapplication.networking;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class RetrofitClient {
private static RetrofitClient instance = null;
private final APIs apis;
private RetrofitClient(){
Retrofit retrofit = new Retrofit.Builder().baseUrl(APIs.BASE_URL).addConverterFactory(GsonConverterFactory.create()).build();
apis = retrofit.create(APIs.class);
}
public static synchronized RetrofitClient getInstance(){
if(instance == null)
instance = new RetrofitClient();
return instance;
}
public APIs getApis(){
return apis;
}
public void fetchProductDetails(String productId, final OnProductDetailsFetchedListener listener) {
Call<List<ProductResult>> call = apis.getProducts();
call.enqueue(new Callback<List<ProductResult>>() {
@Override
public void onResponse(Call<List<ProductResult>> call, Response<List<ProductResult>> response) {
if (response.isSuccessful()) {
List<ProductResult> productList = response.body();
if (productList != null && !productList.isEmpty()) {
for (ProductResult product : productList) {
if (product.getId().equals(productId)) {
String description = product.getDescription();
String imageUrl = product.getProductImage();
String[] productDetails = new String[]{description, imageUrl};
listener.onProductDetailsFetched(productDetails);
return;
}
}
}
}
// If product details are not found or response is not successful
listener.onProductDetailsFetchFailed();
}
@Override
public void onFailure(Call<List<ProductResult>> call, Throwable t) {
// Handle failure case
listener.onProductDetailsFetchFailed();
}
});
}
public interface OnProductDetailsFetchedListener {
void onProductDetailsFetched(String[] productDetails);
void onProductDetailsFetchFailed();
}
}