Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialEric Perozich
Front End Web Development Techdegree Graduate 23,536 PointsNull pointer exception in ListingAdapter overrides
I have tried every recommendation found in previous questions and still cannot get past this null pointer exception. I even tried to update Picasso to the latest version that replaced the with() method with the get() method which caused another error. Idk what else to say about it. maybe someone else can point me in the right direction. here is all the code I can provide already updated with the fixes suggested in other threads:
Logcat error:
2022-01-23 13:08:39.085 4169-4169/com.example.recommendations E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.recommendations, PID: 4169
java.lang.NullPointerException: Attempt to invoke virtual method 'void com.example.recommendations.MainActivity.showList()' on a null object reference
at com.example.recommendations.ListingAdapter.success(ListingAdapter.java:65)
at com.example.recommendations.ListingAdapter.success(ListingAdapter.java:21)
at retrofit.CallbackRunnable$1.run(CallbackRunnable.java:45)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
ListingAdapter.java where Logcat error was found:
@Override
public void success(ActiveListings activeListings, Response response) {
this.activeListings = activeListings;
notifyDataSetChanged();
this.activity.showList();
// this.activity is causing the null pointer exception.
//which leads me to believe the context "this" is the part that's not functioning correctly
//but I have no idea what to do about it or how to point it to something that returns != null
}
full ListingAdapter class:
package com.example.recommendations;
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.example.recommendations.model.ActiveListings;
import com.example.recommendations.model.Listing;
import com.squareup.picasso.Picasso;
import retrofit.Callback;
import retrofit.RetrofitError;
import retrofit.client.Response;
public class ListingAdapter extends RecyclerView.Adapter<ListingAdapter.ListingHolder>
implements Callback<ActiveListings> {
private MainActivity activity;
private LayoutInflater inflater;
private ActiveListings activeListings;
public ListingAdapter(MainActivity activity) {
inflater = LayoutInflater.from(activity);
}
@NonNull
@Override
public ListingHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
return new ListingHolder(inflater.inflate(R.layout.layout_listing, viewGroup, false));
}
@Override
public int getItemCount() {
if (activeListings == null)
return 0;
if (activeListings.results == null)
return 0;
return activeListings.results.length;
}
@Override
public void onBindViewHolder(@NonNull ListingHolder holder, int i) {
final Listing listing = activeListings.results[i];
holder.titleView.setText(listing.title);
holder.priceView.setText(listing.price);
holder.shopNameView.setText(listing.shop.shop_name);
Picasso.get().load(listing.images[0].url_570xN)
.into(holder.imageView);
// Picasso.get() is the updated method to match Picasso 2.8 it replaced the
//.with() method I have tried both and neither fixes the
//NullPointerException causing the app to crash
}
@Override
public void success(ActiveListings activeListings, Response response) {
this.activeListings = activeListings;
notifyDataSetChanged();
this.activity.showList(); //<--- Logcat error occurs here
}
@Override
public void failure(RetrofitError error) {
this.activity.showError();
}
public ActiveListings getActiveListings() {
return activeListings;
}
public class ListingHolder extends RecyclerView.ViewHolder {
public ImageView imageView;
public TextView titleView;
public TextView shopNameView;
public TextView priceView;
public ListingHolder(@NonNull View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.listing_image);
titleView = itemView.findViewById(R.id.listing_title);
shopNameView = itemView.findViewById(R.id.listing_shop_name);
priceView = itemView.findViewById(R.id.listing_price);
}
}
}
Full Etsy class (renamed etsy.java to ApiKeys.java since I'm storing the google+ Api key in the same file):
package com.example.recommendations.api;
import com.example.recommendations.model.ActiveListings;
import retrofit.Callback;
import retrofit.RequestInterceptor;
import retrofit.RestAdapter;
public class ApiKeys {
public static final String ETSY_API_KEY = "5ysmw6833yd5cnfqy40wzoqu";
// google is no longer using the method described in the videos
// and now generates a normal API key which I have added below
public static final String GOOGLE_API_KEY = "AIzaSyBfJuMQuFaiiapN42kmUUSkEQWXWcnimrs";
private static RequestInterceptor getInterceptor() {
return new RequestInterceptor() {
@Override
public void intercept(RequestFacade request) {
request.addEncodedQueryParam("api_key", ETSY_API_KEY);
}
};
}
private static Api getApi() {
return new RestAdapter.Builder()
.setEndpoint("https://openapi.etsy.com/v2")
.setRequestInterceptor(getInterceptor())
.build()
.create(Api.class);
}
public static void getActiveListings(Callback<ActiveListings> callback) {
getApi().activeListings("Shop,Images", callback);
} // tried the fix where someone suggested changing "Images,Shop" to "Shop,Images" neither works to fix the error.
}
Full Interface class:
package com.example.recommendations.api;
import com.example.recommendations.model.ActiveListings;
import retrofit.Callback;
import retrofit.http.GET;
import retrofit.http.Query;
public interface Api {
@GET("/listings/active")
void activeListings(@Query("includes") String includes,
Callback<ActiveListings> callback);
}
Full Shop class:
package com.example.recommendations.model;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Created by jhuson on 1/22/15.
*/
public class Shop implements Parcelable {
public int shop_id;
public String shop_name;
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(shop_id);
dest.writeString(shop_name);
}
public static final Creator<Shop> CREATOR = new Creator<Shop>() {
@Override
public Shop createFromParcel(Parcel source) {
Shop shop = new Shop();
shop.shop_id = source.readInt();
shop.shop_name = source.readString();
return shop;
}
@Override
public Shop[] newArray(int size) {
return new Shop[size];
}
};
}
Full Listing Class:
package com.example.recommendations.model;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Created by jhuson on 1/22/15.
*/
public class Listing implements Parcelable {
public int listing_id;
public String title;
public String description;
public String price;
public String url;
public Shop shop;
public Image[] images;
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(listing_id);
dest.writeString(title);
dest.writeString(description);
dest.writeString(price);
dest.writeString(url);
dest.writeParcelable(shop, 0);
dest.writeParcelableArray(images, 0);
}
public static final Creator<Listing> CREATOR = new Creator<Listing>() {
@Override
public Listing createFromParcel(Parcel source) {
Listing listing = new Listing();
listing.listing_id = source.readInt();
listing.title = source.readString();
listing.description = source.readString();
listing.price = source.readString();
listing.url = source.readString();
listing.shop = source.readParcelable(Shop.class.getClassLoader());
listing.images = (Image[]) source.readParcelableArray(Image.class.getClassLoader());
return listing;
}
@Override
public Listing[] newArray(int size) {
return new Listing[size];
}
};
}
Full ActiveListings class:
package com.example.recommendations.model;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Created by jhuson on 1/22/15.
*/
public class ActiveListings implements Parcelable {
public int count;
public Listing[] results;
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(count);
dest.writeParcelableArray(results, 0);
}
public static final Creator<ActiveListings> CREATOR = new Creator<ActiveListings>() {
@Override
public ActiveListings createFromParcel(Parcel source) {
ActiveListings activeListings = new ActiveListings();
activeListings.count = source.readInt();
activeListings.results = (Listing[]) source.readParcelableArray(Listing.class.getClassLoader());
return activeListings;
}
@Override
public ActiveListings[] newArray(int size) {
return new ActiveListings[size];
}
};
}
Full Image class:
package com.example.recommendations.model;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Created by jhuson on 1/22/15.
*/
public class Image implements Parcelable {
public int rank;
public int full_height;
public int full_width;
public String hex_code;
public String url_75x75;
public String url_170x135;
public String url_570xN;
public String url_fullxfull;
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(rank);
dest.writeInt(full_height);
dest.writeInt(full_width);
dest.writeString(hex_code);
dest.writeString(url_75x75);
dest.writeString(url_170x135);
dest.writeString(url_570xN);
dest.writeString(url_fullxfull);
}
public static final Creator<Image> CREATOR = new Creator<Image>() {
@Override
public Image createFromParcel(Parcel source) {
Image image = new Image();
image.rank = source.readInt();
image.full_height = source.readInt();
image.full_width = source.readInt();
image.hex_code = source.readString();
image.url_75x75 = source.readString();
image.url_170x135 = source.readString();
image.url_570xN = source.readString();
image.url_fullxfull = source.readString();
return image;
}
@Override
public Image[] newArray(int size) {
return new Image[size];
}
};
}
Full MainActivity class:
package com.example.recommendations;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import com.example.recommendations.api.ApiKeys;
import com.example.recommendations.model.ActiveListings;
import com.google.android.gms.common.api.Api;
public class MainActivity extends AppCompatActivity {
private static final String STATE_ACTIVE_LISTINGS = "StateActiveListings";
private RecyclerView recyclerView;
private View progressBar;
private TextView errorView;
private ListingAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.recyclerView);
progressBar = findViewById(R.id.progressBar);
errorView = findViewById(R.id.error_view);
recyclerView.setLayoutManager(new StaggeredGridLayoutManager(1, StaggeredGridLayoutManager.VERTICAL));
adapter = new ListingAdapter(this);
recyclerView.setAdapter(adapter);
if(savedInstanceState == null) {
showLoading();
ApiKeys.getActiveListings(adapter);
} else {
if(savedInstanceState.containsKey(STATE_ACTIVE_LISTINGS)) {
adapter.success(savedInstanceState.getParcelable(STATE_ACTIVE_LISTINGS), null);
showList();
} else {
showLoading();
ApiKeys.getActiveListings(adapter);
}
}
}
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
ActiveListings activeListings = adapter.getActiveListings();
if(activeListings != null) {
outState.putParcelable(STATE_ACTIVE_LISTINGS, activeListings);
}
}
public void showLoading() {
progressBar.setVisibility(View.VISIBLE);
recyclerView.setVisibility(View.GONE);
errorView.setVisibility(View.GONE);
}
public void showList() {
progressBar.setVisibility(View.GONE);
recyclerView.setVisibility(View.VISIBLE);
errorView.setVisibility(View.GONE);
}
public void showError() {
progressBar.setVisibility(View.GONE);
recyclerView.setVisibility(View.GONE);
errorView.setVisibility(View.VISIBLE);
}
}