In this fragment,
public class BlankFragment extends Fragment {
public BlankFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
final View rootView = inflater.inflate(R.layout.fragment_blank, container, false);
RecyclerView rv = rootView.findViewById(R.id.rv_recycler_view);
rv.setNestedScrollingEnabled(false);
SimpleDateFormat localDateFormat = new SimpleDateFormat("HH:mm");
SunTimes suntime = SunTimes.compute().at(latlang.Lat,latlang.Lang).today().execute();
String sun_rise = localDateFormat.format(suntime.getRise());
String sun_set = localDateFormat.format(suntime.getSet());
Date sunnoon = suntime.getNoon();
System.out.println("SUNRISE "+ sun_rise);
TextView cityField = rootView.findViewById(R.id.tv_city);
TextView sunrise = rootView.findViewById(R.id.tv_sunrt);
TextView sunset = rootView.findViewById(R.id.tv_sunst);
cityField.setText("Hello World"); //Line 45
sunrise.setText(sun_rise);
sunset.setText(sun_set);
return rootView;
}
I am getting error:
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
at com.example.phocast.BlankFragment.onCreateView(BlankFragment.java:45)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2354)
The question is while I have a normal string as a text, how it can get null point exception?
What am I doing wrong?
Update
the fragment_blank does not have the id, as its just an inflater:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/swiperefresh"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/rv_recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</android.support.v7.widget.RecyclerView>
</android.support.v4.widget.SwipeRefreshLayout>
</RelativeLayout>
That id is in item_blank.xml as:
<?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"
android:layout_width="match_parent"
android:layout_height="120sp" >
<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_margin="10dp"
android:layout_height="120sp"
card_view:cardCornerRadius="4dp"
card_view:elevation="14dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/iv_image"
android:layout_width="120sp"
android:layout_height="fill_parent"
android:scaleType="fitStart"
card_view:srcCompat="#drawable/property_image_3">
</ImageView>
<TextView
android:id="#+id/tv_city"
android:layout_width="wrap_content"
android:layout_height="30sp"
android:layout_marginBottom="1sp"
android:layout_toRightOf="#+id/iv_image"
android:gravity="top"
android:paddingLeft="5sp"
android:text="Hello World"
android:textAppearance="#style/TextAppearance.AppCompat.Large">
</TextView>
.....
and which is defined in the Adapter:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private String[] 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 MyViewHolder extends RecyclerView.ViewHolder {
public CardView mCardView;
public TextView mTextView;
public MyViewHolder(View v) {
super(v);
mCardView = (CardView) v.findViewById(R.id.card_view);
mTextView = (TextView) v.findViewById(R.id.tv_city);
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(String[] myDataset) {
mDataset = myDataset;
}
// Create new views (invoked by the layout manager)
#Override
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.card_item, parent, false);
// set the view's size, margins, paddings and layout parameters
MyViewHolder vh = new MyViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(MyViewHolder holder, final int position) {
holder.mTextView.setText(mDataset[position]);
holder.mCardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String currentValue = mDataset[position];
Log.d("CardView", "CardView Clicked: " + currentValue);
}
});
}
#Override
public int getItemCount() {
return mDataset.length;
}
}
So I am expecting the cardview to be read from the adapter, as it is working for this case:
public class BlankFragment extends Fragment {
public BlankFragment() {
// Required empty public constructor
}
//
// #Override
// public void onCreate(Bundle savedInstanceState) {
// super.onCreate(savedInstanceState);
//
// }
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
final View rootView = inflater.inflate(R.layout.fragment_blank, container, false);
RecyclerView rv = rootView.findViewById(R.id.rv_recycler_view);
rv.setNestedScrollingEnabled(false);
Weather_OWM.placeIdTask asyncTask = new Weather_OWM.placeIdTask(new Weather_OWM.AsyncResponse() {
public void processFinish(String weather_city, String weather_description, String weather_temperature, String weather_humidity, String weather_pressure, String weather_updatedOn, String weather_iconText, String sun_rise, String sun_set) {
TextView cityField = rootView.findViewById(R.id.tv_city);
TextView sunrise = rootView.findViewById(R.id.tv_sunrt);
TextView sunset = rootView.findViewById(R.id.tv_sunst);
cityField.setText(weather_city);
sunrise.setText(sun_rise);
sunset.setText(sun_set);
}
});
asyncTask.execute(Double.toString(latlang.Lat), Double.toString(latlang.Lang)); // asyncTask.execute("Latitude", "Longitude")
rv.setHasFixedSize(true);
MyAdapter adapter = new MyAdapter(new String[]{"Today", "Golden Hour", "Blue Hour", "Civil Twilight", "Nautical Twilight", "Astronomical Twilight", "Hello", "World"});
rv.setAdapter(adapter);
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
rv.setLayoutManager(llm);
return rootView;
}
}
It's not about the string argument but the cityField TextView you're calling setText() on. You're initialising it with
rootView.findViewById(R.id.tv_city);
which returns null if the view is not found. So your fragment_blank layout does not have a view with id tv_city.
Related
im trying to get data from firestore. but those data don't appears in my fragment activity.
and there is this error: E/RecyclerView: No adapter attached; skipping layout
i can only see the background of frangment activy, where is the error?
SecondFragment.class
public class SecondFragment extends Fragment {
public static final String TAG = "FireLog";
RecyclerView mMainList;
FirebaseFirestore mFirestore;
CollectionReference mRef;
View view;
public List<Offices> officesList;
public OfficesListAdapter officesListAdapter;
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.second_layout, container, false);
//Recycler View
mMainList = (RecyclerView) view.findViewById(R.id.main_list);
LinearLayoutManager manager = new LinearLayoutManager(getContext());
mMainList.setHasFixedSize(true);
mMainList.setLayoutManager(new LinearLayoutManager(getContext()));
mMainList.setAdapter(officesListAdapter);
mFirestore = FirebaseFirestore.getInstance();
officesList = new ArrayList<>();
officesListAdapter = new OfficesListAdapter(officesList);
mFirestore.collection("TICINO").addSnapshotListener(new EventListener<QuerySnapshot>() {
#Override
public void onEvent(#javax.annotation.Nullable QuerySnapshot queryDocumentSnapshots, #javax.annotation.Nullable FirebaseFirestoreException e) {
if (e != null){
Log.d(TAG, "Error : " + e.getMessage());
}
for (DocumentChange doc: queryDocumentSnapshots.getDocumentChanges()) {
if(doc.getType() == DocumentChange.Type.ADDED){
Offices offices = doc.getDocument().toObject(Offices.class);
officesList.add(offices);
officesListAdapter.notifyDataSetChanged();
}
}
}
});
second_layout.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"
xmlns:app="http://schemas.android.com/apk/res-auto">
<android.support.v7.widget.RecyclerView
android:id="#+id/main_list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
OfficeListAdapter.class
public class OfficesListAdapter extends RecyclerView.Adapter<OfficesListAdapter.ViewHolder> {
public List<Offices> officesList;
public OfficesListAdapter(List<Offices> officesList){
this.officesList = officesList;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_offices, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder viewHolder, int i) {
viewHolder.nameText.setText(officesList.get(i).getNameOffices());
viewHolder.cambioText.setText(officesList.get(i).getCambio());
}
#Override
public int getItemCount() {
return officesList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView nameText;
public TextView cambioText;
View mView;
public ViewHolder(#NonNull View itemView) {
super(itemView);
mView=itemView;
nameText = (TextView) mView.findViewById(R.id.text_view_name_office);
cambioText = (TextView) mView.findViewById(R.id.text_view_cambio_offices);
}
}
}
Offices.class
public class Offices {
String name, cambio;
public Offices(){}
public Offices(String name, String cambio) {
this.name = name;
this.cambio = cambio;
}
public String getNameOffices() {
return name;
}
public void setNameOffices(String name) {
this.name = name;
}
public String getCambio() {
return cambio;
}
public void setCambio(String cambio) {
this.cambio = cambio;
}
}
list_offices.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_marginTop="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
app:cardBackgroundColor="#ffffe8">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="8dp">
<TextView
android:id="#+id/text_view_name_office"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Title"
android:layout_alignParentLeft="true"
android:maxLines="1"
android:ellipsize="end"
android:textAppearance="#style/TextAppearance.AppCompat.Large" />
<TextView
android:id="#+id/text_view_cambio_offices"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:text="Description"
android:layout_below="#id/text_view_name_office"/>
</RelativeLayout>
</android.support.constraint.ConstraintLayout>
Try to set the adapter after instantiating it. E.g.:
// Inside OnCreate
//Recycler View
mMainList = (RecyclerView) view.findViewById(R.id.main_list);
LinearLayoutManager manager = new LinearLayoutManager(getContext());
mMainList.setHasFixedSize(true);
mMainList.setLayoutManager(new LinearLayoutManager(getContext()));
mFirestore = FirebaseFirestore.getInstance();
officesList = new ArrayList<>();
officesListAdapter = new OfficesListAdapter(officesList);
// Here your adapter is initialised
mMainList.setAdapter(officesListAdapter);
Create your adapter object before set it on RecyclerView
// add below method in your adapter class
public void dataChanged(List<Offices> officesList){
this.officesList = officesList;
notifyDataSetChanged();// make sure dont forget to call this method
}
// create adapter object before set it on RecyclerView
LinearLayoutManager manager = new LinearLayoutManager(getContext());
mMainList.setHasFixedSize(true);
mMainList.setLayoutManager(new LinearLayoutManager(getContext()));
officesListAdapter = new OfficesListAdapter(null);// add this line here
mMainList.setAdapter(officesListAdapter);
mFirestore = FirebaseFirestore.getInstance();
officesList = new ArrayList<>();
// and finally update data on your adapter from your firebase onEvent() method
for (DocumentChange doc: queryDocumentSnapshots.getDocumentChanges()) {
if(doc.getType() == DocumentChange.Type.ADDED){
Offices offices = doc.getDocument().toObject(Offices.class);
officesList.add(offices);
}
}
officesListAdapter.dataChanged(officesList);// update from here
I know that my question has been asked several times but i have been searching for a while and none of all the answers fixed my problem.
The issue is that when i create the recyclerview adapter and all the stuff in the method "onViewCreated" in my "HomeFragment" i am not having any compilation error but my recyclerview doesn't load any image since none of the methods Overriden in recyclerview adapter are called even when i call "mAdapter.notifyDataSetChanged()"
HomeFragment.java
public class HomeFragment extends Fragment implements Response.Listener<GalleryItem[]>, Response.ErrorListener {
RequestQueue requestQueue;
List<GalleryItem> myDataset = new ArrayList<>();
RecyclerView mRecyclerView;
RecyclerView.Adapter mAdapter;
RecyclerView.LayoutManager mLayoutManager;
CustomJsonObjectRequest jsonObjectRequest;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.home_fragment, container, false);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
mRecyclerView = view.findViewById(R.id.my_recycler_view);
mRecyclerView.setHasFixedSize(true);
mAdapter = new GalleryAdapter(myDataset);
mLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
mRecyclerView.setAdapter(mAdapter);
jsonObjectRequest = new CustomJsonObjectRequest(Constants.HOME_URL, GalleryItem[].class, this, this);
requestQueue = VolleySingleton.getInstance(this.getContext()).getRequestQueue();
VolleySingleton.getInstance(this.getContext()).addToRequestQueue(jsonObjectRequest, "headerRequest");
}
#Override
public void onResponse(GalleryItem[] response) {
myDataset = Arrays.asList(response);
mAdapter.notifyDataSetChanged();
}
#Override
public void onErrorResponse(VolleyError error) {
Log.d(Constants.API_ERROR_TAG, error.getMessage());
}
GalleryAdapter.java
public class GalleryAdapter extends RecyclerView.Adapter<GalleryAdapter.MyViewHolder> {
private List<GalleryItem> mDataset;
public static class MyViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
Log.d("tagdetest2","myviewholder");
imageView = itemView.findViewById(R.id.gallery_image);
}
}
public GalleryAdapter(List<GalleryItem> myDataset) {
mDataset = myDataset;
}
#NonNull
#Override
public GalleryAdapter.MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int i) {
Log.d("tagdetest2","onCreateViewHolder");
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_gallery, parent, false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull GalleryAdapter.MyViewHolder myViewHolder, int i) {
Log.d("tagdetest2", mDataset.get(i).link);
Glide.with(myViewHolder.itemView.getContext()).load(mDataset.get(i).link).into(myViewHolder.imageView);
}
#Override
public int getItemCount() {
Log.d("tagdetest", "size = " + mDataset.size());
return mDataset.size();
}
item_gallery.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">
<ImageView
android:id="#+id/gallery_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
home_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<android.support.v7.widget.RecyclerView
android:id="#+id/my_recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.constraint.ConstraintLayout>
myDataset = Arrays.asList(response);
overrides the reference, in your Fragment not in your adapter.
Try with
mDataset.addAll(Arrays.asList(response));
insetad
I put a Button in fragment with the corresponding listener. Every time I call on this activity the app crashes. Logcat show a null pointer exception. The code below is a snippet from the Fragment class.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_carprofile_list, container, false);
// Set the adapter
if (view instanceof RecyclerView) {
Context context = view.getContext();
RecyclerView recyclerView = (RecyclerView) view;
if (mColumnCount <= 1) {
recyclerView.setLayoutManager(new LinearLayoutManager(context));
} else {
recyclerView.setLayoutManager(new GridLayoutManager(context, mColumnCount));
}
recyclerView.setAdapter(new MyCarProfileRecyclerViewAdapter(carProfileContent.ITEMS, mListener));
}
Button imgbtn = (Button) view.findViewById(R.id.editCarProfileButton);
imgbtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
startActivity(new Intent(getActivity(),ReserveActivity.class));
}
});
return view;
}
Logcat shows:
FATAL EXCEPTION: main
Process: com.example.app, PID: 13571
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.app/com.example.app.CarProfileListActivity}: java.lang.NullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2377)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2429)
at android.app.ActivityThread.access$800(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1342)
at android.os.Handler.dispatchMessage(Handler.java:110)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:5333)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:828)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:644)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at com.mikepuno.parkeazy.CarProfileFragment.onCreateView(CarProfileFragment.java:78)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2354)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1419)
at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1740)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1809)
at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:799)
at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2580)
at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2367)
at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2322)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2229)
at android.support.v4.app.FragmentManagerImpl.dispatchStateChange(FragmentManager.java:3221)
at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:3171)
at android.support.v4.app.FragmentController.dispatchActivityCreated(FragmentController.java:192)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:560)
at android.support.v7.app.AppCompatActivity.onStart(AppCompatActivity.java:177)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1174)
at android.app.Activity.performStart(Activity.java:5353)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2340)
I've been looking at multiple similar issues here but it just don't seem to work for me. Am I missing anything from the way I added the Button and the listener?
fragment_carprofile_list.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView 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:id="#+id/list"
android:name="com.mikepuno.parkeazy.CarProfileFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
app:layoutManager="LinearLayoutManager"
tools:context="com.mikepuno.parkeazy.CarProfileFragment"
tools:listitem="#layout/fragment_carprofile" />
fragment_carprofile.xml:
<?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"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="#+id/plateNumberTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:textAppearance="?attr/textAppearanceListItem" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="#+id/brandTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:textAppearance="?attr/textAppearanceListItem" />
<TextView
android:id="#+id/modelTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:textAppearance="?attr/textAppearanceListItem" />
<TextView
android:id="#+id/colorTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:textAppearance="?attr/textAppearanceListItem" />
<Button
android:id="#+id/editCarProfileButton"
android:layout_width="64dp"
android:layout_height="64dp"
android:text="Edit" />
</LinearLayout>
</LinearLayout>
Adapter Class
public class MyCarProfileRecyclerViewAdapter extends RecyclerView.Adapter<MyCarProfileRecyclerViewAdapter.ViewHolder> {
private final List<CarProfile> mValues;
private final OnListFragmentInteractionListener mListener;
public MyCarProfileRecyclerViewAdapter(List<CarProfile> items, OnListFragmentInteractionListener listener) {
mValues = items;
mListener = listener;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.fragment_carprofile, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.mItem = mValues.get(position);
holder.mPlateNumberTextView.setText(mValues.get(position).getPlateNumber());
holder.mBrandTextView.setText(mValues.get(position).getBrand());
holder.mModelTextView.setText(mValues.get(position).getModel());
holder.mColorTextView.setText(mValues.get(position).getColor());
holder.mView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (null != mListener) {
// Notify the active callbacks interface (the activity, if the
// fragment is attached to one) that an item has been selected.
mListener.onListFragmentInteraction(holder.mItem);
}
}
});
}
#Override
public int getItemCount() {
return mValues.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public final View mView;
public final TextView mPlateNumberTextView;
public final TextView mBrandTextView;
public final TextView mModelTextView;
public final TextView mColorTextView;
public CarProfile mItem;
public ViewHolder(View view) {
super(view);
mView = view;
mPlateNumberTextView = (TextView) view.findViewById(R.id.plateNumberTextView);
mBrandTextView = (TextView) view.findViewById(R.id.brandTextView);
mModelTextView = (TextView) view.findViewById(R.id.modelTextView);
mColorTextView = (TextView) view.findViewById(R.id.colorTextView);
}
#Override
public String toString() {
return super.toString() + " '" + mPlateNumberTextView.getText() + "'";
}
}
}
After you inflate your view
View view = inflater.inflate(R.layout.fragment_carprofile_list, container, false);
you assume that view is RecyclerView. That means root element is recyclerview.
Then trying to find a button inside of that recyclerview by doing
Button imgbtn = (Button) view.findViewById(R.id.editCarProfileButton);
which returns null ofcourse. Then trying to set a click listener on null object.
Looks like your xml file is wrong. If your each row has button that you are trying to find, you need to catch it in your adapter class then notify fragment to do your process.
SOLUTION (EDIT):
Remove these lines from onCreateView in Fragment.
Button imgbtn = (Button) view.findViewById(R.id.editCarProfileButton);
imgbtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
startActivity(new Intent(getActivity(),ReserveActivity.class));
}
});
You have already a interface that notify the fragment.
So that we are going to use it for editing.
So the final adapter class should be like
public class MyCarProfileRecyclerViewAdapter extends RecyclerView.Adapter<MyCarProfileRecyclerViewAdapter.ViewHolder> {
private final List<CarProfile> mValues;
private final OnListFragmentInteractionListener mListener;
public MyCarProfileRecyclerViewAdapter(List<CarProfile> items, OnListFragmentInteractionListener listener) {
mValues = items;
mListener = listener;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.fragment_carprofile, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.mItem = mValues.get(position);
holder.mPlateNumberTextView.setText(mValues.get(position).getPlateNumber());
holder.mBrandTextView.setText(mValues.get(position).getBrand());
holder.mModelTextView.setText(mValues.get(position).getModel());
holder.mColorTextView.setText(mValues.get(position).getColor());
}
#Override
public int getItemCount() {
return mValues.size();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
public final TextView mPlateNumberTextView;
public final TextView mBrandTextView;
public final TextView mModelTextView;
public final TextView mColorTextView;
public CarProfile mItem;
public ViewHolder(View view) {
super(view);
view.setClickable(true); // This is important
view.setOnClickListener(this);
mPlateNumberTextView = (TextView) view.findViewById(R.id.plateNumberTextView);
mBrandTextView = (TextView) view.findViewById(R.id.brandTextView);
mModelTextView = (TextView) view.findViewById(R.id.modelTextView);
mColorTextView = (TextView) view.findViewById(R.id.colorTextView);
}
public void onClick(View view) {
if (null != mListener) {
mListener.onListFragmentInteraction(mValues.get(getAdapterPosition()));
}
}
#Override
public String toString() {
return super.toString() + " '" + mPlateNumberTextView.getText() + "'";
}
}
Then your fragment
#Override
public void onListFragmentInteraction(CarProfile profile) {
// TODO Pass your profile to ReserverActivity by using bundles.
startActivity(new Intent(getActivity(), ReserveActivity.class));
}
You can improve the code by notify fragment on your button click. So your button click listener and notify code must also be in here.
View view = inflater.inflate(R.layout.fragment_carprofile_list, container, false);
You are inflating fragment_carprofile_list.xml, which contains the RecyclerView. There is no mention of Button in that XML, which is why you are getting a NullPointerException
I'm making a music player application where I'm using a loader to load song data to the adapter which is to be shown using a RecyclerView. However, I'm getting this weird error of my adapter methods not working. Only the constructor method of adapter is getting called.
I'm also getting "No adapter attached; skipping layout" despite going through all the available solutions here in stack overflow.
Few points to be noted:
I've tried all the solutions for "No adapter attached; skipping layout" in
recyclerview No adapter attached; skipping layout thread and all associated duplicate threads.
The RecyclerView I'm using is not the regular one but FastScrollRecyclerView, but since it extends from the regular RecyclerView and there are no relatable issues mentioned on github so I'm convinced that using this library is not an issue here
I've also tried all solutions for the adapter methods not being called from this thread but no luck.
Here's the code:
SongsFragment.java
public class SongsFragment extends Fragment
implements LoaderManager.LoaderCallbacks<List<Song>>{
public static final String LOG_TAG = SongsFragment.class.getSimpleName();
private static final int LOADER_ID = 1;
private ContentResolver mContentResolver;
private SongListAdapter mSongListAdapter;
private List<Song> mSongs;
#BindView(R.id.rvSongs) FastScrollRecyclerView mRecyclerView;
public SongsFragment() {}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ButterKnife.bind(getActivity());
mSongs = new ArrayList<>();
mRecyclerView = new FastScrollRecyclerView(getContext());
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(layoutManager);
mRecyclerView.setHasFixedSize(true);
mSongListAdapter = new SongListAdapter(getContext(), mSongs);
mRecyclerView.setAdapter(mSongListAdapter);
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getLoaderManager().initLoader(LOADER_ID, null, this).forceLoad();
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_songs, container, false);
}
#Override
public Loader<List<Song>> onCreateLoader(int id, Bundle args) {
mContentResolver = getActivity().getContentResolver();
return new SongsLoader(getContext(), mContentResolver);
}
#Override
public void onLoadFinished(Loader<List<Song>> loader, List<Song> data) {
mSongs = data;
mSongListAdapter.setData(mSongs);
}
#Override
public void onLoaderReset(Loader<List<Song>> loader) {
mSongListAdapter.setData(new ArrayList<Song>());
}
}
SongsListAdapter.java
public class SongListAdapter
extends FastScrollRecyclerView.Adapter<SongListAdapter.SongItemViewHolder>
implements FastScrollRecyclerView.SectionedAdapter{
public static final String LOG_TAG = SongListAdapter.class.getSimpleName();
private Context mContext;
private List<Song> mSongList = new ArrayList<>();
public SongListAdapter(Context context, List<Song> songList) {
Log.d(LOG_TAG, "Constructor called");
mContext = context;
mSongList = songList;
}
#NonNull
#Override
public String getSectionName(int position) {
return String.valueOf(mSongList.get(position).getTitle().charAt(0)).toUpperCase();
}
#Override
public SongItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Log.d(LOG_TAG, "onCreateViewHolder called");
View view = LayoutInflater.from(mContext).inflate(R.layout.list_item_song, null);
return new SongItemViewHolder(view);
}
#Override
public void onBindViewHolder(SongItemViewHolder holder, int position) {
Log.d(LOG_TAG, "onBindViewHolder called");
Uri albumArtUri = mSongList.get(position).getAlbumArtUri();
Glide.with(mContext)
.load(albumArtUri)
.into(holder.albumArt);
holder.titleText.setText(mSongList.get(position).getTitle());
holder.artistText.setText(mSongList.get(position).getArtistName());
Log.d("Data", albumArtUri.toString() + "\n" + mSongList.get(position).getTitle() + "\n" + mSongList.get(position).getArtistName());
}
#Override
public int getItemCount() {
Log.d(LOG_TAG, "getItemCount called");
return (mSongList != null ? mSongList.size() : 0);
}
public void setData(List<Song> songs){
mSongList = songs;
notifyDataSetChanged();
}
public class SongItemViewHolder extends FastScrollRecyclerView.ViewHolder {
ImageView albumArt;
TextView titleText;
TextView artistText;
SongItemViewHolder(View view) {
super(view);
Log.d(LOG_TAG, "SongItemViewHolder called");
albumArt = (ImageView) view.findViewById(R.id.item_song_image);
titleText = (TextView) view.findViewById(R.id.item_song_title);
artistText = (TextView) view.findViewById(R.id.item_song_artist_name);
}
}
}
fragment_songs.xml (SongsFragment is inflating this layout)
<?xml version="1.0" encoding="utf-8"?>
<ScrollView 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="match_parent">
<com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView
android:id="#+id/rvSongs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:fastScrollPopupBgColor="#color/colorAccent"
app:fastScrollPopupTextColor="#android:color/primary_text_dark"
app:fastScrollThumbColor="#color/colorAccent"/>
</ScrollView>
list_item_song.xml (Individual item in recycler view)
<?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="wrap_content"
android:orientation="vertical">
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_gravity="center_horizontal"
android:layout_marginStart="12dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:background="#FFFFFF"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingBottom="10dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:paddingStart="8dp"
android:paddingTop="10dp">
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/item_song_image"
android:layout_width="64dp"
android:src="#drawable/music_placeholder"
android:layout_height="64dp"/>
</FrameLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:orientation="vertical">
<TextView
android:id="#+id/item_song_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:text="Song_Title"/>
<TextView
android:id="#+id/item_song_artist_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:textSize="12sp"
android:text="Song_Artist"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
This has been really frustrating. Please review the code and help me with this. I think I've done everything correctly but I may be wrong. I know scrollview and recyclerview don't go that well but I've seen the preview and the recycler view shows. Any help will be appreciated. Thanks!
Try setting adapter in onLoadFinished() and also use getActivity() for context in adapter object
#Override
public void onLoadFinished(Loader<List<Song>> loader, List<Song> data) {
mSongs = data;
mSongListAdapter = new SongListAdapter(getActivity(), mSongs);
mRecyclerView.setAdapter(mSongListAdapter);
}
also in this
mRecyclerView = new FastScrollRecyclerView(getContext()); to
mRecyclerView = new FastScrollRecyclerView(getActivity());
Basically use getActivity() for context in fragment class
Ugh! I wasted a lot of time in this but finally came out with the solution. I removed Butterknife binding and used conventional findViewById inside onCreateView() of SongsFragment after capturing the view instance by changing the onCreateView() to this:
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_songs, container, false);
mRecyclerView = (FastScrollRecyclerView) rootView.findViewById(R.id.rvSongs);
//Rest of the things
}
Turns out I was using ButterKnife the wrong way so the instance mRecyclerView was null but later with line
mRecyclerView = new FastScrollRecyclerView(getContext()); it wasn't null anymore but it still wasn't connected to the view so I didn't get NullPointerException and the code didn't work.
I know it was a noob mistake :D
Correct way to use ButterKnife with fragments as picked up from official website is:
public class FancyFragment extends Fragment {
#BindView(R.id.button1) Button button1;
#BindView(R.id.button2) Button button2;
#Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fancy_fragment, container, false);
ButterKnife.bind(this, view);
// TODO Use fields...
return view;
}
}
I want to use custom ListView in extends from ListFragment class. After create new subClass extends from BaseAdapter into current class and set layout to that I get ... has stopped error.
list_fragment.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="vertical"
>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/txt1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"/>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/txt2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"/>
</LinearLayout>
ResivedSMS.java :
public class ResivedSMS extends ListFragment {
private String testArray1[];
private String testArray2[];
private ListView listFragment;
public ResivedSMS() {
testArray1 = new String[] {
"1111111111",
"2222222222",
"3333333333",
"4444444444",
"5555555555",
"6666666666",
};
testArray1 = new String[] {
"AAAAA",
"BBBBB",
"CCCCC",
"DDDDD",
"FFFFF",
"GGGGG",
};
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
listFragment = (ListView) inflater.inflate(
R.layout.list_fragment, container, false);
ViewResivedSMSDetailes customListView = new ViewResivedSMSDetailes(getActivity(),testArray1,testArray2);
listFragment.
setAdapter( customListView );
return listFragment;
}
#Override
public void onListItemClick(ListView list, View v, int position, long id) {
Toast.makeText(getActivity(), getListView().getItemAtPosition(position).toString(), Toast.LENGTH_LONG).show();
}
class ViewResivedSMSDetailes extends BaseAdapter
{
private LayoutInflater inflater;
private String[] values1;
private String[] values2;
private class ViewHolder {
TextView txt1;
TextView txt2;
}
public ViewResivedSMSDetailes(Context context,String[] values1,String[] values2)
{
this.values1=values1;
this.values2=values2;
inflater = LayoutInflater.from(context);
}
#Override
public int getCount() {
return values1.length;
}
#Override
public Object getItem(int index) {
return values1[index];
}
#Override
public long getItemId(int arg0) {
return arg0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder = null;
if(convertView ==null){
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.list_fragment, null);
holder.txt1 = (TextView)convertView.findViewById(R.id.txt1);
holder.txt2 = (TextView)convertView.findViewById(R.id.txt2);
convertView.setTag(holder);
}
holder = (ViewHolder) convertView.getTag();
holder.txt1.setText(values1[position]);
holder.txt2.setText(values2[position]);
return convertView;
}
}
}
logcat Result:
08-24 10:33:34.675 349-349/ir.tsms E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.ClassCastException: android.widget.LinearLayout
at ir.tsms.ResivedSMS.onCreateView(ResivedSMS.java:50)
ResivedSMS.java:50 is:
listFragment = (ListView) inflater.inflate(
R.layout.list_fragment, container, false);
Whats my code problem and how to resolved Thanks?
problem:
inflater.inflate(R.layout.list_fragment, container, false);
You are inflating a LinearLayout not a ListView thus giving you ClassCastException
solution:
Since you are using ListFragment you can directly set the adapter, since ListFragment has its own default ListView. Set the adapter in the onCreate Method.
sample:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ViewResivedSMSDetailes customListView = new ViewResivedSMSDetailes(getActivity(),testArray1,testArray2);
setListAdapter( customListView ); //call the method if listFragment
}