RecyclerView Adapter methods not called - java

I have this weird issue with my adapter that no methods are called.. The constructor works, it stops there if I have a breakpoint but from there, nothing.. onCreateViewHolder doesn't get called and neither onBindViewHolder and not even getItemCount.. I tried everything I could find online but nothing seems to be working so I don't know what to do. Any suggestions? Here's my code:
Fragment:
public class FragmentPackageDetails extends Fragment {
//other vars
RecyclerView rvPackageDetails;
DatabaseHandler database;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Bundle args = getArguments();
String temp = args.getString(KEY_TRACKER_CODE);
View v = inflater.inflate(R.layout.fragment_package_details_new, container, false);
return v;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
rvPackageDetails = (RecyclerView) view.findViewById(R.id.rvPackageDetails);
rvPackageDetails.setLayoutManager(new LinearLayoutManager(getActivity()));
database = new DatabaseHandler(getActivity());
selectedPackage = database.getPackage(trackerCode);
RecyclerView.Adapter adapter = new MyAdapter(selectedPackage.getRecords());
rvPackageDetails.setAdapter(adapter);
}
//other methods in class
}
MyAdapter
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private ArrayList<TrackingRecordCheckedOut> mDataset;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public class ViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public TextView tvPackageDetailsRowDayOfWeek, tvPackageDetailsRowDayOfMonth, tvPackageDetailsRowNameOfMonth,
tvPackageDetailsRowDetailsTitle, tvPackageDetailsRowDetailsDescription, tvPackageDetailsRowDetialsTime;
public ViewHolder(View v) {
super(v);
tvPackageDetailsRowDayOfWeek = (TextView) v.findViewById(R.id.tvPackageDetailsRowDayOfWeek);
tvPackageDetailsRowDayOfMonth = (TextView) v.findViewById(R.id.tvPackageDetailsRowDayOfMonth);
tvPackageDetailsRowNameOfMonth = (TextView) v.findViewById(R.id.tvPackageDetailsRowNameOfMonth);
tvPackageDetailsRowDetailsTitle = (TextView) v.findViewById(R.id.tvPackageDetailsRowDetialsTime);
tvPackageDetailsRowDetailsDescription = (TextView) v.findViewById(R.id.tvPackageDetailsRowDetailsDescription);
tvPackageDetailsRowDetialsTime = (TextView) v.findViewById(R.id.tvPackageDetailsRowDetialsTime);
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(ArrayList<TrackingRecordCheckedOut> myDataset) {
mDataset = myDataset;
}
// Create new views (invoked by the layout manager)
#Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_list_item, parent, false);
// set the view's size, margins, paddings and layout parameters
ViewHolder vh = new ViewHolder(v);
return vh;
}
// Replace the contents of a view (invoked by the layout manager)
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
TrackingRecordCheckedOut tr = mDataset.get(position);
holder.tvPackageDetailsRowDayOfWeek.setText(tr.getDayOfWeek());
holder.tvPackageDetailsRowDayOfMonth.setText(tr.getDayOfWeek());
holder.tvPackageDetailsRowNameOfMonth.setText(tr.getMonthOfYear());
holder.tvPackageDetailsRowDetailsTitle.setText(tr.getTitle());
holder.tvPackageDetailsRowDetailsDescription.setText(tr.getDetails());
holder.tvPackageDetailsRowDetialsTime.setText(tr.getTimeOfDay());
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return mDataset.size();
}
}
Fragment Layout:
<?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">
<android.support.v7.widget.RecyclerView
android:id="#+id/rvPackageDetails"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
RecyclerView Row Layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/llPackageDetailsRecyclerViewRow"
android:layout_width="match_parent"
android:layout_height="96dip"
android:orientation="horizontal"
android:weightSum="100">
<LinearLayout
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="20"
android:orientation="vertical"
android:weightSum="10">
<TextView
android:id="#+id/tvPackageDetailsRowDayOfWeek"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="3"/>
<TextView
android:id="#+id/tvPackageDetailsRowDayOfMonth"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="4"/>
<TextView
android:id="#+id/tvPackageDetailsRowNameOfMonth"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="3"/>
</LinearLayout>
<LinearLayout
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="80"
android:orientation="vertical">
<TextView
android:id="#+id/tvPackageDetailsRowDetailsTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="3"/>
<TextView
android:id="#+id/tvPackageDetailsRowDetailsDescription"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="4"/>
<TextView
android:id="#+id/tvPackageDetailsRowDetialsTime"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="3"/>
</LinearLayout>
</LinearLayout>

I had this same issue where neither onCreateViewHolder or onBindViewHolder were being called. Saving a reference to Context in the constructor of your Adapter, and then changing your onCreateViewHolder method to use the saved reference to Context instead of doing parent.getContext() should fix it:
private Context mContext;
public MyAdapter(Context context, ArrayList<TrackingRecordCheckedOut> myDataset) {
mDataset = myDataset;
mContext = context;
}
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// create a new view using saved reference to Context (mContext)
View v = LayoutInflater.from(mContext).inflate(R.layout.recyclerview_list_item, parent, false);
// set the view's size, margins, paddings and layout parameters
ViewHolder vh = new ViewHolder(v);
return vh;
}

I looked at your code don't really see an issue unfortunately. One thing that might be problematic is that in you ViewHolder constructor you call super(v). You might need to call super((LinearLayout)v). That might not make a difference though.
Good luck!

Related

java.lang.NullPointerException: while try accessing textview from viewholder

I have a custom RecycleView and I am able to display the data in the RecycleViewsuccessfully. Now, I want to access the text view from the custom layout in order to make the change in later part of my code. I have provided the layout, RecycleViewadapter and the method I have tried to access the TextView. But I am getting NullPointerException with the view is null. How can I access the textview((R.id.zb) from Mylayout.xml in my main activity to modify RecycleView items?
My layout:
<android.support.v7.widget.CardView android:id="#+id/card_view1"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardBackgroundColor="#color/cardview_light_background"
card_view:cardCornerRadius="5dp"
card_view:cardUseCompatPadding="true"
xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="3"
android:orientation="horizontal"
android:id="#+id/z">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Z "
style="#style/Base.TextAppearance.AppCompat.Large.Inverse"
android:layout_weight="1"
android:textColor="#color/colorPrimary"
android:gravity="center"
android:id="#+id/zn"/>
<TextView
android:id="#+id/zb"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="buy"
android:textColor="#333"
style="#style/Base.TextAppearance.AppCompat.Medium.Inverse"/>
<TextView
android:id="#+id/zs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="Sell"
android:textColor="#333"
style="#style/Base.TextAppearance.AppCompat.Medium.Inverse"/>
</LinearLayout>
</android.support.v7.widget.CardView>
RecycleView Adapter:
public class Adapter extends RecyclerView.Adapter<Adapter.Viewholder> {
private List<dispitems> m;
#NonNull
#Override
public Adapter.Viewholder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list1, parent, false);
return new Viewholder(itemView);
}
#Override
public void onBindViewHolder(#NonNull Adapter.Viewholder holder, int position) {
dispitems d = m.get(position);
holder.zb.setText(d.getZb());
holder.zs.setText(d.getZs());
holder.zn.setText(d.getZn());
}
#Override
public int getItemCount() {
return m.size();
}
Adapter(List<dispitems> m) {
this.m = m;
}
public class Viewholder extends RecyclerView.ViewHolder {
public TextView zb,zs,zn;
Viewholder(View itemView) {
super(itemView);
zn = (TextView) itemView.findViewById(R.id.zn);
zb = (TextView) itemView.findViewById(R.id.zb);
zs = (TextView) itemView.findViewById(R.id.zs);
}
}
}
I've tried the below options but it is showing the null pointer exception
Adapter.Viewholder row = (Adapter.Viewholder) recyclerView.findViewHolderForAdapterPosition(getCategoryPos(device));
row.zs.setTextColor(ContextCompat.getColor(this, R.color.colorAccent));
I have received the following exception.
java.lang.NullPointerException: Attempt to read from field 'android.widget.TextView cti.cryptotrackerindia.Adapter$Viewholder.zsell' on a null object reference
tried the below as well
View row = recyclerView.getLayoutManager().getChildAt(getCategoryPos(device));
Maybe I am not getting the question, but you should be able to just get the textview on onCreateViewHolder after you inflated the view.
public Adapter.Viewholder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list1, parent, false);
TextView txtView = (TextView )itemView.findViewById(R.id.zb);
return new Viewholder(itemView);
}
and then just store it as a member in the adapter.
If you want to update data displayed in RecyclerView, you should use notifyItemChanged(position, payload) to perform partial re-bind of ViewHolder.
Modifying layout of ViewHolder directly without referencing represented data can lead to discrepancy in displayed views, especially when You start scrolling your list and ViewHolders start being recycled and reused for other items.

RecyclerView not calling getItemCount

I've investigated several SO answers on this question (here, here, and here) and none of the proposed solutions have worked. My problem is that my RecyclerView list items aren't being displayed. I've set breakpoints in MessengerRecyclerAdapter, onCreateViewHolder, onBindViewHolder, and getItemCount and only the first one is ever called. While in a breakpoint I've entered the expression evaluator and executed
MessengerRecyclerAdapter.getItemCount();
And received the expected answer of 20. The RecyclerView itself takes up the intended content area as demonstrated by the screenshot below (I turned the RecyclerView magenta to highlight the space it occupies).
My RecyclerView XML code is below:
<?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">
<android.support.v7.widget.RecyclerView
android:id="#+id/thread_list"
android:background="#color/colorAccent"
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:name="com.jypsee.jypseeconnect.orgPicker.MessengerListFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="LinearLayoutManager"
tools:context="com.jypsee.jypseeconnect.orgPicker.MessengerListFragment"
tools:listitem="#layout/fragment_messenger_cell"/>
</LinearLayout>
My RecyclerView Cell XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="#+id/id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="#dimen/text_margin"
android:textAppearance="?attr/textAppearanceListItem"
android:textColor="#color/blueText"/>
<TextView
android:id="#+id/content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="#dimen/text_margin"
android:textAppearance="?attr/textAppearanceListItem"
android:textColor="#color/darkText"/>
</LinearLayout>
My ListFragment class:
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
List<DummyContent.DummyItem> items = new ArrayList<>();
for (Integer i = 0; i<20; i++){
DummyContent.DummyItem item = new DummyContent.DummyItem(i.toString(),"Content","Details");
items.add(item);
}
View view = inflater.inflate(R.layout.fragment_messenger_list, container, false);
mRecyclerView = (RecyclerView) view.findViewById(R.id.thread_list);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mRecyclerAdapter = new MessengerThreadRecyclerAdapter(items, mListener);
mRecyclerView.setAdapter(mRecyclerAdapter);
mRecyclerAdapter.notifyDataSetChanged();
return view;
}
My Adapter class:
public class MessengerRecyclerAdapter
extends RecyclerView.Adapter<MessengerRecyclerAdapter.MessageThreadHolder>{
private final List<DummyItem> mValues;
private final RecyclerViewClickListener mListener;
public MessengerRecyclerAdapter(List<DummyItem> items, RecyclerViewClickListener listener) {
mValues = items;
mListener = listener;
}
#Override
public MessageThreadHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.fragment_messenger_cell, parent, false);
return new MessageThreadHolder(view);
}
#Override
public void onBindViewHolder(final MessageThreadHolder holder, final int position) {
holder.mItem = mValues.get(position);
holder.mIdView.setText(mValues.get(position).id);
holder.mContentView.setText(mValues.get(position).content);
holder.mView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mListener != null) {
mListener.recyclerViewListClicked(v, position);
}
}
});
}
#Override
public int getItemCount() {
return mValues.size();
}
public class MessageThreadHolder extends RecyclerView.ViewHolder {
public final View mView;
public final TextView mIdView;
public final TextView mContentView;
public DummyItem mItem;
public MessageThreadHolder(View view) {
super(view);
mView = view;
mIdView = (TextView) view.findViewById(R.id.id);
mContentView = (TextView) view.findViewById(R.id.content);
}
}
}
As you can see I've set the linearLayout orientation to vertical and set the layout manager, which were the 2 most common solutions. I'm really at a loss as to what to try next, so any help is appreciated.
As I said in previous Answer edit. The issues was in your xml. The main reason it was not showing was because, You were trying to add the fragment using include tag instead of fragment tag thus respective fragment class was never getting called on the fragment layout being added to your activity.
Below is the code you needed to add the Fragment correctly.
<fragment
android:id="#+id/message_thread"
android:name="com.jypsee.jypseeconnect.orgPicker.MessengerThreadListFragment"
layout="#layout/fragment_messengerthread_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout="#layout/fragment_messengerthread_list" />
And your fragment layout should be like this
<?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=".orgPicker.MessengerThreadListFragment">
<android.support.v7.widget.RecyclerView
android:id="#+id/thread_list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Here is the screenshot of working
In my case , I was missing calling notifyDataSetChanged() after setting list in adapter.

LinearLayout cannot be cast to TextView : tutorial Creating Lists and Cards

I'm trying to follow the Android official doc for Creating Lists and Cards.
I found here that it was necessary to cast in TextView the ViewHolder but when I do it I have the following error: java.lang.ClassCastException: android.widget.LinearLayout cannot be cast to android.widget.TextView
My Adapter
public class CardsViewAdapter extends RecyclerView.Adapter<CardsViewAdapter.ViewHolder> {
private Game[] mDataset;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public static class ViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public TextView mTextView;
public ViewHolder(TextView v) {
super(v);
mTextView = (TextView) v.findViewById(R.id.textViewName);
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public CardsViewAdapter(Game[] myDataset) {
mDataset = myDataset;
}
// Create new views (invoked by the layout manager)
#Override
public CardsViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.cards_resume_game, parent, false);
// set the view's size, margins, paddings and layout parameters
//...
ViewHolder vh = new ViewHolder((TextView) v);
return vh;
}
// Replace the contents of a view (invoked by the layout manager)
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
holder.mTextView.setText(mDataset[position].getId_game());
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return mDataset.length;
}
}
My Custom View 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"
android:tag="cards main container">
<android.support.v7.widget.CardView
android:id="#+id/card_view"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardBackgroundColor="#color/blue_50"
card_view:cardCornerRadius="10dp"
card_view:cardElevation="5dp"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<TextView
android:id="#+id/textViewName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge"/>
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
You have those 2 mixed up. Assuming that in
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.cards_resume_game, parent, false);
the R.layout.cards_resume_game is LinearLayout, you should then have:
ViewHolder vh = new ViewHolder(v);
and have ViewHolder constructor accept a view:
public ViewHolder(View v) {
mTextView = (TextView) v.findViewById(R.id.some_text_view_id);
}
where some_text_view_id is a TextView in said layout, which will be fetched by findViewById()
In your adapter you are casting TextView to ViewHolder which isn't necessary, and you are also calling ViewHolder in a redundant way. Try this:
return new ViewHolder(v) instead of ViewHolder vh = new ViewHolder((TextView)
The reason you do not need this cast is because you are already casting mView under your ViewHolder constructor, or rather you're already defining the view it should expect.

Android TextView SetText null object reference error

I am new to android and I am getting a
Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
error on my app. I have read other questions on here like this one - java.lang.NullPointerException - setText on null object reference but I still get the same issue. My format is a little bit different as this is done in a Fragment and what I am doing is having a Custom Adapter from a listview. Here is my code
fragment_song_genre.xml
<?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:bind="http://schemas.android.com/tools">
<data class="SongGenreBinding">
<variable
name="handler"
type="com.mgrmobi.joox.fragments.FilterSongGenreFragment" />
</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000">
<RelativeLayout
android:id="#+id/toprow"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp">
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginLeft="16dp"
android:background="#null"
android:onClick="#{ handler.onCloseClicked }"
android:src="#drawable/search_close" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginLeft="80dp"
android:text="Genre"
android:textColor="#fff"
android:textSize="20sp" />
<TextView
android:onClick="#{ handler.reset }"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="15dp"
android:text="#string/reset"
android:textAllCaps="true"
android:textColor="#fff"
android:textSize="12sp" />
</RelativeLayout>
<ListView
android:id="#+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/toprow"
android:layout_marginTop="24dp"></ListView>
</RelativeLayout>
That is the main page and it has a Listview in the Bottom and here is the fragment that calls that xml layout
public class FilterSongGenreFragment extends BaseFragment {
private SongGenreBinding binding;
private ArrayList<String> genres;
String[] names= {"Johm","Paul","Mike"};
#Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
}
private static final String GENRES_KEY = "genres";
public static FilterSongGenreFragment newInstance(ArrayList<String> genres) {
Bundle args = new Bundle();
args.putStringArrayList(GENRES_KEY, genres);
FilterSongGenreFragment fragment = new FilterSongGenreFragment();
fragment.setArguments(args);
return fragment;
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_song_genre, container, false);
binding.setHandler(this);
genres = getArguments().getStringArrayList(GENRES_KEY);
initList();
return binding.getRoot();
}
private void initList() {
// ArrayAdapter adapter = new ArrayAdapter(getActivity(), R.layout.genre_list_text, android.R.id.text1, genres);
FilterSongsAdapter filterSongsAdapter= new FilterSongsAdapter(getActivity(),names);
binding.list.setAdapter(filterSongsAdapter);
binding.list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view,int position, long l) {
((SongFilterListener) getActivity()).onGenreSelected(genres.get(position));
/*
textView = (ImageView) view.findViewById(R.id.selected_genre);
textView.setVisibility(View.VISIBLE);
*/
// close();
}
});
}
private void close() {
getActivity().getFragmentManager().beginTransaction().remove(this).commit();
}
public void onCloseClicked(View view) {
close();
}
public void reset(View view) {
((SongFilterListener) getActivity()).onResetFilters();
close();
}
}
Here is the xml for the listview custom style genre_list_text.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="#android:id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical|left"
android:text="Genre"
android:paddingBottom="16dp"
android:paddingLeft="4dp"
android:paddingTop="16dp"
android:textColor="#fff"
android:textSize="16sp" />
<ImageView
android:id="#+id/selected_genre"
android:layout_height="24dp"
android:layout_width="24dp"
android:visibility="invisible"
android:src="#drawable/check_circle"
android:layout_marginStart="140dp"
android:layout_centerVertical="true" />
</RelativeLayout>
and here is my adapter and as stated before the error happens in the SetText area
public class FilterSongsAdapter extends ArrayAdapter<String> {
private Context c;
String[] names= {};
LayoutInflater inflater;
public FilterSongsAdapter(Context context,String[] names) {
super(context,R.layout.genre_list_text,names);
this.c=context;
this.names=names;
}
public static class ViewHolder {
TextView text1;
}
#Override
public View getView(int position,View convertView,ViewGroup parent) {
ViewHolder holder;
if(convertView==null){
holder = new ViewHolder();
inflater = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.from(c).inflate(R.layout.genre_list_text, null);
// Initialize
holder.text1=(TextView) convertView.findViewById(R.id.text1);
convertView.setTag(holder);
}else {
holder = (ViewHolder) convertView.getTag();
}
holder.text1.setText(names[position]);
return convertView;
}
}
The SetText inside the GetView is throwing the exception every time, that TextView should have 3 objects names from the Names String Array which I have seen that it has. Based on the error I know that i'm setting the SetText before the FindByID method locates the TextView but I have moved things around and nothing works. Any help would be great . I also been following this tutorial for reference https://www.youtube.com/watch?v=99C_UpLcBRk . I do not know if maybe with a Fragment things are different.
in your layout you have given default id to TextView android:id="#android:id/text1".
and in JAVA file you are giving R.id.text1
make changes in xml or java.
ether change in xml from android:id="#android:id/text1" to android:id="#+id/text1"
or in java android.R.id.text1
#Override
public View getView(int position,View convertView,ViewGroup parent) {
ViewHolder holder = new ViewHolder(); //because error says null object reference, it means object of TextView `text1` is not found.
inflater = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if(convertView==null){
convertView = inflater.inflate(R.layout.genre_list_text, null);
holder.text1=(TextView) convertView.findViewById(R.id.text1);
holder.text1.setText(names[position]);
convertView.setTag(holder);
}else {
holder = (ViewHolder) convertView.getTag();
}
return convertView;
}
And from your provided XML code, I can see you did not provided a proper id for TextView. Change in XML from android:id="#android:id/text1" to android:id="#+id/text1".
In your genre_list_text.xml change android:id="#android:id/text1" to android:id="#+id/text1"
and in your getView Method
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
View view = convertView;
if (view == null) {
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.genre_list_text, parent, false);
viewHolder = new ViewHolder();
holder.text1=(TextView) view.findViewById(R.id.text1);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
holder.text1.setText(names[position]);
return view;
}

ListFragment doesn't seem be inflating

Hoping someone can help. I'm having an issue it seems inflating my view. My goal is to display a list of items in a custom layout using a custom array adapter. I re-worked some of my original code using another SO post, but where my simple adapter worked fine, the new list doesn't display. Please see below:
This is my Fragment class.
HomeFeedFragment.java
public class HomeFeedFragment extends ListFragment {
private ListView listView;
private ArrayList<MainEvent> items;
private MainEventListViewAdapter adapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_homefeed,
container, false);
listView = (ListView) rootView.findViewById(android.R.id.list);
return rootView;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//GetEvents is just a test method to return a list of pre-filled event objects
items = GlobalList.GetEvents();
adapter = new MainEventListViewAdapter(getActivity(), android.R.id.list, items);
listView.setAdapter(adapter);
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
// do something with the data
}
}
My custom row layout xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="5dip" >
<!-- ListRow Left sied Thumbnail image -->
<LinearLayout
android:id="#+id/thumbnail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginRight="5dip"
android:padding="3dip" >
<ImageView
android:id="#+id/list_image"
android:layout_width="50dip"
android:layout_height="50dip" />
</LinearLayout>
<!-- Heading Text -->
<TextView
android:id="#+id/eventheader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="#+id/thumbnail"
android:layout_toRightOf="#+id/thumbnail"
android:textColor="#040404"
android:textSize="15sp"
android:textStyle="bold"
android:typeface="sans" />
<!-- Event Description -->
<TextView
android:id="#+id/eventdescription"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/thumbnail"
android:layout_below="#id/eventheader"
android:layout_marginTop="1dip"
android:layout_toRightOf="#+id/thumbnail"
android:textColor="#343434"
android:textSize="10sp"
tools:ignore="SmallSp" />
<!-- Posted Time -->
<TextView
android:id="#+id/eventpostedtime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignTop="#id/eventheader"
android:layout_marginRight="5dip"
android:gravity="right"
android:textColor="#10bcc9"
android:textSize="10sp"
android:textStyle="bold"
tools:ignore="SmallSp" />
</RelativeLayout>
The actual fragment layout:
<?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" >
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
And my custom ArrayAdapter:
public class MainEventListViewAdapter extends ArrayAdapter<MainEvent> {
private Context context;
private List<MainEvent> eventList;
public MainEventListViewAdapter(Context context, int textViewResourceId, List<MainEvent> eventList){
super(context, textViewResourceId, eventList);
this.context = context;
//this.eventList = eventList;
}
/*private view holder class*/
private class ViewHolder {
ImageView imageView;
TextView txtEventHeader;
TextView txtEventDescription;
TextView txtEventPostedTime;
}
public int getCount(){
if(eventList!=null){
return eventList.size();
}
return 0;
}
public MainEvent getItem(int position){
if(eventList!=null){
return eventList.get(position);
}
return null;
}
public long getItemId(int position){
if(eventList!=null){
return eventList.get(position).hashCode();
}
return 0;
}
public View getView(int position, View convertView, ViewGroup parent){
ViewHolder holder = null;
MainEvent rowItem = getItem(position);
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if(convertView==null){
convertView = inflater.inflate(R.layout.fragment_homefeed_rowlayout, parent, false);
holder = new ViewHolder();
holder.txtEventHeader = (TextView) convertView.findViewById(R.id.eventheader);
holder.txtEventDescription = (TextView) convertView.findViewById(R.id.eventdescription);
holder.txtEventPostedTime = (TextView) convertView.findViewById(R.id.eventpostedtime);
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
holder.txtEventHeader.setText(rowItem.getHeadline());
holder.txtEventDescription.setText(rowItem.getDescription());
holder.txtEventPostedTime.setText(rowItem.getPostedTime());
/*TextView text = (TextView) v.findViewById(R.id.label);
text.setText(m.getHeadline());
ImageView imageView = (ImageView) v.findViewById(R.id.icon);
imageView.setTag(m.getImageURL());
//DownloadImageTask dt = new DownloadImageTask();
dt.execute(imageView);
return v;*/
return convertView;
}
public List<MainEvent> getEventList(){
return eventList;
}
public void setEventList(List<MainEvent> eventList){
this.eventList = eventList;
}
}
^ I initially had an Async Task in this class to retrieve images for each item, but I've removed all of that for now.
I don't get any actual errors in LogCat, no crashes or anything, the View just isn't inflating. Any help is appreciated.
Well this is embarrassing. I found out the issue. Apparently, I forgot to uncomment the line in the adapter constructor that initializes the event list:
//this.eventList = eventList;
I'd commented it out temporarily to fix another bug. Working fine now, but thanks for your suggestion.

Categories