Null pointer Exception in RecyclerViewAdapter [duplicate] - java

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 5 years ago.
The adapter was working just fine until I decided to add Native Ads, for that I made 6 changes in the adapter.
added new ViewType (AD_VIEW_TYPE)
added new ViewHolder (NativeExpressAdViewHolder)
changed getItemViewType (made it return AD_VIEW_TYPE at every 8th position)
added a new case in onCreateViewHolder
switch (viewType){
case AD_VIEW_TYPE:
View nativeExpressLayoutView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.native_express_ad_container, parent, false);
return new NativeExpressAdViewHolder(nativeExpressLayoutView);
Added a new case to onBindViewHolder
switch (viewType){
case AD_VIEW_TYPE:
NativeExpressAdViewHolder nativeExpressHolder = (NativeExpressAdViewHolder)holder;
NativeExpressAdView adView = (NativeExpressAdView)arrayList.get(position);
ViewGroup adCardView = (ViewGroup)nativeExpressHolder.itemView;
adCardView.removeAllViews();
if(adView.getParent() != null){
((ViewGroup)adView.getParent()).removeView(adView);
}
adCardView.addView(adView);
break;
Other than the above changes, I also changed my ArrayList<CardSetterGetter> to ArrayList<Object> in Activity and Adapter too.
Now the problem is that when I run the app, it throws NullPointerException.
the logcat says
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.View.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
at com.company.appname.adapters.RecyclerViewAdapter$RecyclerViewHolder.<init>(RecyclerViewAdapter.java:186)
at com.company.appname.adapters.RecyclerViewAdapter$RecyclerViewHolder.<init>(RecyclerViewAdapter.java:165)
at com.company.appname.adapters.RecyclerViewAdapter$NativeExpressAdViewHolder.<init>(RecyclerViewAdapter.java:150)
at com.company.appname.adapters.RecyclerViewAdapter.onCreateViewHolder(RecyclerViewAdapter.java:84)
at com.company.appname.adapters.RecyclerViewAdapter.onCreateViewHolder(RecyclerViewAdapter.java:48)
These are the part of my code where the logcat is pointing to
/*Line 48*/public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.RecyclerViewHolder> {
public RecyclerViewAdapter(Context context, ArrayList<Object> arrayList, ArrayList<String> favouriteItemList, int totalCount {...}
#Override
public long getItemId(int position){...}
#Override
public RecyclerViewAdapter.RecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType){
case AD_VIEW_TYPE:
View nativeExpressLayoutView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.native_express_ad_container, parent, false);
/*Line 84*/ return new NativeExpressAdViewHolder(nativeExpressLayoutView);
case MENU_ITEM_VIEW_TYPE:
default:
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.cards, parent, false);
return new RecyclerViewHolder(view);
}
}
#Override
public void onBindViewHolder(final RecyclerViewHolder holder, final int position){...}
public class NativeExpressAdViewHolder extends RecyclerViewHolder{
NativeExpressAdViewHolder(View view){
/*Line 150*/ super(view);
}
}
#Override
public int getItemViewType(int position){...}
#Override
public int getItemCount(){...}
/*Line 165*/ public class RecyclerViewHolder extends RecyclerView.ViewHolder {
TextView title;
RelativeLayout relativeLayout;
RelativeLayout cardDescription;
SimpleDraweeView image;
ImageView favourite_button;
CardSetterGetter cardSetterGetter;
ImageView share;
private RecyclerViewHolder(View itemView) {
super(itemView);
title = (TextView) itemView.findViewById(R.id.image_title);
relativeLayout = (RelativeLayout) itemView.findViewById(R.id.activity_dash_board);
cardDescription = (RelativeLayout) itemView.findViewById(R.id.card_details);
image = (SimpleDraweeView) itemView.findViewById(R.id.image);
favourite_button = (ImageView) itemView.findViewById(R.id.favourite_button);
share = (ImageView) itemView.findViewById(R.id.share);
/*Line 186*/ image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Activity activity = (Activity) context;
saveInfo(constants.SERVERIP.concat(cardSetterGetter.getImageurl()), cardSetterGetter.getImageId(), cardSetterGetter.getDescription(), cardSetterGetter.getImagetitle(), cardSetterGetter.getFavourite());
Intent i = new Intent().setClass(context, DetailsImageviewActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
context.startActivity(i);
activity.overridePendingTransition(R.anim.pull_from_right, R.anim.pull_out_to_right);
}
});
}
}
}
I know what a NullPointerException is, I know the solution to those problems, but in this case it's getting hard for me to find the source and the solution of the problem. So if the solution is that simple, instead of marking the question as a duplicate, please consider helping me out with this.

When come to inflate 2 different view type in a recyclerView,we need to create 2 separate ViewHolder class to contain the different element inside of each layout
Try the following:
//make this a separate class,but not inside the onBindViewHolder
private class NativeExpressAdViewHolder extends RecyclerView.ViewHolder{
NativeExpressAdViewHolder(View view){
super(view);
//find the view here
adView = (NativeExpressAdView)view.findViewById(R.id.native_ad);
}
private class RecyclerViewHolder extends RecyclerView.ViewHolder{
//this one as usual..
}
//change your onCreateViewHolder for this as well,
// cause now you have 2 view type,so you just override from universal
//RecyclerView.ViewHolder,not need RecyclerViewAdapter.RecyclerViewHolder
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { }
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
int viewType = getItemViewType(position);
switch (viewType){
case AD_VIEW_TYPE:
final NativeExpressAdViewHolder adHolder (NativeExpressAdViewHolder)holder
//here find your view and load the ad
break;
case MENU_ITEM_VIEW_TYPE:
final RecyclerViewHolder viewHolder = (RecyclerViewHolder)holder
//do your thing here,find view,assign value to the layout
}
And one more thing,please check your XML,your XML should look like this
<com.google.android.gms.ads.NativeExpressAdView
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:id="#+id/native_ad"
android:layout_gravity="center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
ads:adSize="360x132"
ads:adUnitId="#string/your_ads">
</com.google.android.gms.ads.NativeExpressAdView>

Related

How to change only the background alpha of TextView not the whole view?

N.B: This might be a duplicate post. But no previous solution worked for me...
I'm trying to set TextView (only)background opacity from inside a RecyclerView Adapter(not both the textColor & background). Answer of previous question didn't worked for me.
Output of Previous Suggestions
Case 1:
holder.textView.setBackgroundColor(Color.argb(50, 0,255,0)); //this set alpha to whole view(both background + textColor).
Case 2:
holder.textView.setAlpha(50); //this also set alpha to whole view(both background + textColor).
Case 3:
holder.textView.getBackground().setAlpha(alpha); //NullPointerException
Output
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.graphics.drawable.Drawable.setAlpha(int)' on a null object reference
Here is my RecyclerView :
...
#RequiresApi(api = Build.VERSION_CODES.O)
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
TextView textView = new TextView(parent.getContext());
return new ViewHolder(textView);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
holder.textView.setAlpha(50);
}
static class ViewHolder extends RecyclerView.ViewHolder {
private TextView textView;
#RequiresApi(api = Build.VERSION_CODES.O)
public ViewHolder(#NonNull View itemView) {
super(itemView);
this.textView = (TextView) itemView;
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
textView.setLayoutParams(layoutParams);
textView.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
textView.setPadding(4,4,4,4);
textView.setAutoSizeTextTypeUniformWithConfiguration(6,24,1, TypedValue.COMPLEX_UNIT_DIP);
}
}
...
Try this:
....
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
ShapeDrawable drawable = new ShapeDrawable();
drawable.getPaint().setColor(Color.GREEN); //Your color;
drawable.getPaint().setAlpha(75); //BackGround Alpha between 0 to 100;
holder.textView.setBackground(drawable);
}

RecyclerView Adapter highlight clicked or current item

As I'm new to android, I'm struggling to highlight Recyclerview clicked or current item. I have tried some workarounds but nothing helps. Basically I want to highlight selected item even after it is coming back from respective Fragment. Please check my code and help me to get done. Thanks.
public class ContentaAdapter extends RecyclerView.Adapter<ContentaAdapter.MyViewHolder> {
Context context;
ArrayList<String> ItemTitle;
ArrayList<String> ItemSource;
public ContentaAdapter(Context context, ArrayList<String> ItemTitle, ArrayList<String> ItemSource) {
this.context = context;
this.ItemTitle = ItemTitle;
this.ItemSource = ItemSource;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.home_items_layout, parent, false);
MyViewHolder vh = new MyViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
holder.ItemTitle.setText(ItemTitle.get(position));
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Fragment contentdisplay = new ViewContentFragment();
Bundle bundle=new Bundle();
bundle.putStringArrayList("ItemTitle",ItemTitle);
bundle.putStringArrayList("ItemSource",ItemSource);
bundle.putInt("position",position);
bundle.putInt("ItemCounts",ItemTitle.size());
contentdisplay.setArguments(bundle);
((MainActivity)context).replaceFragment(contentdisplay);
}
});
}
#Override
public int getItemCount() {
return ItemTitle.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView ItemTitle;
public MyViewHolder(View itemView) {
super(itemView);
ItemTitle = (TextView) itemView.findViewById(R.id.item_title);
}
}
}
you need to to add isSelected state in to your list item data model and change it onClick.
And when you know state you can change background in ViewHolder
if (isSelected) {
// set selected background here
} else {
// set not selected background here
}
And instead of keeping two lists in adapter you should create one with model ArrayList<DataModel> similar to this:
class DataModel {
String ItemTitle;
String ItemSource;
Boolean isSelected;
}
also you shouldn't pass both list to other fragment, instead take only what you need, for example yourList.get(position);

Android Studio Firebase Get Data [duplicate]

This question already has an answer here:
I cant see any FirebaseRecyclerAdapter items on my layout
(1 answer)
Closed 3 years ago.
I am trying to use android studio to get firebase data and display it on the screen. I am trying to display anything that is in the database related to it to a RecyclerView. But the data does not return and nothing displays (no error statement). Any ideas why?
private void firebaseLotSearch() {
Toast.makeText(BuyingParking.this,"Started Search",Toast.LENGTH_LONG).show();
Query query = mUserDatabase.startAt(searchText).endAt(searchText+"\uf8ff");
FirebaseRecyclerOptions<Lot_Location> options =
new FirebaseRecyclerOptions.Builder<Lot_Location>()
.setQuery(query, Lot_Location.class)
.build();
// Lot_Location.class,R.layout.list_layout,LotViewHolder.class,mUserDatabase
FirebaseRecyclerAdapter<Lot_Location,LotViewHolder> firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<Lot_Location, LotViewHolder>(options) {
#Override
protected void onBindViewHolder(#NonNull LotViewHolder holder, int position, #NonNull Lot_Location model) {
holder.setDetails(model.getLocation(),model.getAdmin(),model.getPrice());
}
#NonNull
#Override
public LotViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
return null;
}
};
searchParking.setAdapter(firebaseRecyclerAdapter);
}
public class LotViewHolder extends RecyclerView.ViewHolder{
public LotViewHolder(#NonNull View itemView) {
super(itemView);
mView = itemView;
}
public void setDetails(String location,String admin,String price)
{
TextView m_location = (TextView)mView.findViewById(R.id.Lot);
TextView m_admin = (TextView)mView.findViewById(R.id.Admin);
TextView m_price = (TextView)mView.findViewById(R.id.price);
m_location.setText(location);
m_admin.setText(admin);
m_price.setText(price);
}
}
onCreateViewHolder is returning null. You need to return an object of LotViewHolder class.
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View rootView = mInflater.inflate(R.layout.your_item_view, parent, false);
ViewHolder holder = new ViewHolder(rootView);
return holder;
}

Recycler List Adapter is null after initialization

My app has a tab bar with three fragments. During the onCreate Method I call a function called initPlantList. This function initializes my RecyclerListAdapter.
private void initPlantList(){
RecyclerView rV = findViewById(R.id.plantsRecycler);
PlantListAdapter pLA = new PlantListAdapter(this);
Log.d("PLA", pLA.hasContext());
rV.setAdapter(pLA);
rV.setLayoutManager(new LinearLayoutManager(this));
}
I get this error java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.widget.RecyclerView.setAdapter(android.support.v7.widget.RecyclerView$Adapter)' on a null object reference when I attempt to call rV.setAdapter(pLA);
Here is my Adapter Class
public class PlantListAdapter extends
RecyclerView.Adapter<PlantListAdapter.ViewHolder>{
private static final String TAG = "PlantListAdapter";
private Context mContext;
public PlantListAdapter(Context c){
this.mContext = c;
}
public String hasContext(){
if(this.mContext != null){
return mContext.getPackageResourcePath();
}
return "false";
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layoutplantlist, parent, false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
Log.d(TAG, "onBindViewHolder: called.");
holder.image.setImageDrawable(MyApplication.myPlantList.get(position).getImage());
holder.plantName.setText(MyApplication.myPlantList.get(position).getName());
}
#Override
public int getItemCount() {
return MyApplication.myPlantList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
CircleImageView image;
TextView plantName;
RelativeLayout plantListItem;
public ViewHolder(View itemView) {
super(itemView);
image = itemView.findViewById(R.id.plantImage);
plantName = itemView.findViewById(R.id.plantName);
plantListItem = itemView.findViewById(R.id.plantListItem);
}
}
}
Any thoughts on why it is reffering to pLA as a null object reference?
It is not your adapter that is null. Its is your Recyclerview. You are using a fragment therefore you can’t use (findViewById).
You have to find it using the view you inflated.
Try this:
private void initPlantList(View v){
RecyclerView rV = v.findViewById(R.id.plantsRecycler);
PlantListAdapter pLA = new PlantListAdapter(this);
Log.d("PLA", pLA.hasContext());
rV.setAdapter(pLA);
rV.setLayoutManager(new LinearLayoutManager(this));
}
And when you call that method in your fragment onCrrateView() just pass the view as a parameter.
Hope it helps you

Calling activity from ViewHolder in RecyclerView?

I've got a RecyclerView which is loading the content of my String arrays which works fine, however I want to open a new activity depending on which view they have pressed.
What I have done is created an array called classes like so:
<array name="classes">
<item>ClassOne</item>
<item>ClassTwo</item>
<item>ClassThree</item>
<item>ClassFour</item>
</array>
These are stored in an array, and passed to my MainActivityList adapter below:
String[] classes = resource.getStringArray(R.array.classes);
MainActivityList adapter = new MainActivityList(titles,content, images, classes);
recyclerView.setAdapter(adapter);
I've managed to add the OnClickListener to the ViewHolder and output what class is assigned to each view to the log, however I cannot figure out or get working, how to launch another activity.
The class name would be something like ClassOne.class for example
public class MainActivityList extends RecyclerView.Adapter<MainActivityList.ViewHolder> {
private String[] mTitles;
private String[] mContent;
private String[] mClasses;
private TypedArray mImages;
private Context context;
public MainActivityList(String[] titles, String[] content, TypedArray images, String[] classes) {
this.mTitles = titles;
this.mContent = content;
this.mImages = images;
this.mClasses = classes;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup,int i) {
final View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.activity_main_card, viewGroup, false);
ViewHolder vh = new ViewHolder(v);
v.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
ViewHolder vh = (ViewHolder)v.getTag();
Log.v("DEBUG", "Clicked" + vh.classes);
}
});
return vh;
}
public void onBindViewHolder(ViewHolder holder, int position) {
holder.titleView.setText(mTitles[position]);
holder.contentView.setText(mContent[position]);
holder.imageView.setImageDrawable(mImages.getDrawable(position));
holder.classes = mClasses[position];
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView titleView;
public TextView contentView;
public ImageView imageView;
public String classes;
public ViewHolder(View v) {
super(v);
titleView = (TextView) v.findViewById(R.id.card_title);
contentView = (TextView) v.findViewById(R.id.card_content);
imageView = (ImageView)v.findViewById(R.id.card_image);
v.setTag(this);
}
}
#Override
public int getItemCount() {
return mTitles.length;
}
}
Intent intent = new Intent(viewObject.getContext(),ActivityName.class);
viewObject.getContext().startActivity(intent);
I was also looking for a solution, and I found this post:
http://venomvendor.blogspot.sg/2014/07/setting-onitemclicklistener-for-recycler-view.html
By using the OnItemClickListener interface, you should be able to call startActivity in your activity.
adapter.SetOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(View v , int position) {
// This is in an Activity so should be able to start new activity, etc.
}
});
Update: I have tested, the method mentioned in the blog worked for me.

Categories