In my fragment's onCreateView method, I am inflating a layout that contains a RecyclerView. However, when I try to reference the view, I get a NullPointerException at the following line:
mRecyclerView.setLayoutManager(mStaggeredLayoutManager);
What am I doing wrong?
Here is my code:
public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstance){
final StaggeredGridLayoutManager mStaggeredLayoutManager = new StaggeredGridLayoutManager(1, StaggeredGridLayoutManager.VERTICAL);
mRecyclerView = (RecyclerView)getActivity().findViewById(R.id.list);
mRecyclerView.setLayoutManager(mStaggeredLayoutManager);
mRecyclerView.setHasFixedSize(true); //Data size is fixed - improves performance
mAdapter = new TravelListAdapter(getActivity());
mRecyclerView.setAdapter(mAdapter);
return inflater.inflate(R.layout.start_fragment,container,false);
}
You are doing getActivity.findViewById(), which wouldn't work. You just created the view, but it is not attached to the activity yet. For this to work, you have to find the view in the fragment's view, not the activity's view.
First, inflate the fragment's view, and then do inflatedView.findViewById(R.id.list).
Example:
public View onCreateView(...){
View inflatedView = inflater.inflate(R.layout.start_fragment, container, false);
mRecyclerView = (RecyclerView) inflatedView.findViewById(R.id.list);
return inflatedView;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
final StaggeredGridLayoutManager mStaggeredLayoutManager = new StaggeredGridLayoutManager(1, StaggeredGridLayoutManager.VERTICAL);
mRecyclerView = (RecyclerView) view.findViewById(R.id.list);
mRecyclerView.setLayoutManager(mStaggeredLayoutManager);
mRecyclerView.setHasFixedSize(true);
mAdapter = new TravelListAdapter(getActivity());
mRecyclerView.setAdapter(mAdapter);
super.onViewCreated(view, savedInstanceState);
}
this is what I would do
Related
I try to create a HORIZONTAL recyclerView but recyclerView can't find the context here is my Fragmnet code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.context =context;
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
ArrayList<CategoryModel> categoryModels = null;
RecyclerView recyclerView = container.findViewById(R.id.category_recycler);
// recyclerView.setHasFixedSize(true);
CategoryAdapter adapter = new CategoryAdapter(context,CategoryData.getCategory());
recyclerView.setAdapter(adapter);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
recyclerView.setLayoutManager(layoutManager);
return inflater.inflate(R.layout.main_fragment, container, false);
}
and here is Recycler view adapter code:
public class CategoryAdapter extends RecyclerView.Adapter<CategoryAdapter.ViewHolder> {
Context context;
ArrayList<CategoryModel> categorys;
public CategoryAdapter(Context context, ArrayList<CategoryModel> categoryModels) {
this.categorys = categoryModels;
this.context = context;
}
#NonNull
#Override
public CategoryAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.product_category,parent,false);
return new ViewHolder(view);
}
i'm also attached the Debug result please check the image
Try like this:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
// Defines the xml file for the fragment
return inflater.inflate(R.layout.main_fragment, parent, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
// Inflate the layout for this fragment
ArrayList<CategoryModel> categoryModels = null;
RecyclerView recyclerView = view.findViewById(R.id.category_recycler);
// recyclerView.setHasFixedSize(true);
CategoryAdapter adapter = new CategoryAdapter(getContext(), CategoryData.getCategory());
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
}
To use Context inside Fragment use getContext() method .
CategoryAdapter adapter = new CategoryAdapter(getContext(),CategoryData.getCategory());
From official doc
Return the Context this fragment is currently associated with.
If you are using Context only for inflating view inside onCreateViewHolder method in CategoryAdapter class then you don't need to pass Context in Constructor. You can get Context from ViewGroup which is first parameter of the onCreateViewHolder method.
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.product_category,parent,false);
In your onCreate() fragment callback I see this line:
public void onCreate(Bundle savedInstanceState) {
...
this.context =context;
...
}
This line doesn't do anything; there's no context argument to the onCreate() method or anything like that, so you're just assigning a variable back to itself. Since your Context context field doesn't have an explicit intialization, the default is null. So this is the same as writing
public void onCreate(Bundle savedInstanceState) {
...
this.context = null;
...
}
Later on, in onCreateView(), you're instantiating your adapter with this line:
CategoryAdapter adapter = new CategoryAdapter(context,CategoryData.getCategory());
Because of what I said above, this is functionally the same as
CategoryAdapter adapter = new CategoryAdapter(null, CategoryData.getCategory());
To solve this, you need some place to get a Context instance from. Fragments are often "attached" to a context, and, when they're attached, you can get that context by calling getContext(). A fragment is guaranteed to be attached to a context in the onActivityCreated() callback, so you will want to move your adapter creation to that callback instead of onViewCreated().
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.main_fragment, container, false);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
CategoryAdapter adapter = new CategoryAdapter(getContext(), CategoryData.getCategory());
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
RecyclerView recyclerView = getView().findViewById(R.id.category_recycler);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(layoutManager);
}
Previous Question:
May I know why this error will occur when I try to start RecyclerView activity doing a search from fragment.
After added adapter:
error: OwnerDAO.getOwner()' on a null object reference
Fragment code:
RecyclerView recyclerView;
RecyclerView.LayoutManager layoutManager;
SearchAdapter adapter;
OwnerDAO mOwnerDao;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.activity_search, container, false);
recyclerView = (RecyclerView)v.findViewById(R.id.recycler_search);
layoutManager = new LinearLayoutManager(this.getActivity());
mOwnerDao = new OwnerDAO(getContext())
adapter = new SearchAdapter(getContext(),mOwnerDao.getOwner());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setHasFixedSize(true);
recyclerView.setAdapter( adapter );
return v;
}
Search Adapter:
public SearchAdapter(Context context, List<Owner> owners) {
this.context = context;
this.owners = owners;
}
Set the layoutManager after setAdapter like this :-
recyclerView.setAdapter( adapter );
recyclerView.setLayoutManager(layoutManager);
The error will be removed !!
I want to display my data inside a fragment but it seems like some methods are not applicable in fragments only in Activity. The text with * are causing me errors. How i can execute it on a fragment?
String urlAddress = "http://capstonproject.xyz/project/tourist/retrieve/adventure";
RecyclerView recyclerView;
public Fadventure() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
//RecyclerView recyclerView = (RecyclerView) inflater.inflate(R.layout.fragment_fadventure, container, false);
return inflater.inflate(R.layout.fragment_fadventure, container, false);
recyclerView = view.findViewById(R.id.adventure_list);
recyclerView.setLayoutManager(new LinearLayoutManager(***this***));
recyclerView.setItemAnimator(new DefaultItemAnimator());
new DBFetch(***Fadventure.this***,recyclerView).execute();
//return recyclerView;
}
instead of this try with getActivity().getApplication().
hope it helps.
public class WorkFragment extends Fragment {
List<CardViewItem> items = new ArrayList<>();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("FRAGMENT", "Work Fragment started");
TypedArray icons = getResources().obtainTypedArray(R.array.project_icons);
TypedArray names = getResources().obtainTypedArray(R.array.project_names);
TypedArray descs = getResources().obtainTypedArray(R.array.project_descs);
for (int i=0;i<icons.length();i++){
items.add(new CardViewItem(icons.getDrawable(i),
names.getString(i),
descs.getString(i)));
}
icons.recycle();
names.recycle();
descs.recycle();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d("FRAGMENT", "Work Fragment onCreateView");
View rootView = inflater.inflate(R.layout.fragment_work, container, false);
RecyclerView recyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);
LinearLayoutManager llm = new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false);
recyclerView.setLayoutManager(llm);
recyclerView.setAdapter(new ItemAdapter(items));
return inflater.inflate(R.layout.fragment_work, container, false);
}
}
Gives me
E/RecyclerView: No adapter attached; skipping layout
I have tried out all the solutions I had found (setting an empty adapter, moving the code elswhere, using a seperate thread) but to no avail. This should work on a normal activity so I guess maybe I'm doing something wrong.
the problem is mostly this line
return inflater.inflate(R.layout.fragment_work, container, false);
you should have
return rootView
With the first return you are inflating a new totally different view hierarchy, starting from fragment_work.xml, from the one which has an the RecyclerView correctly set up.
I am getting an error saying "No adapter attached; skipping layout", however my images are loading into my LayoutManager just fine. However, when i try to scroll down and load additional data, the application crashes with a NullPointerException. Here is my related code.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
service.getPodcasts()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(podcasts -> mRecyclerView.setAdapter(new PodcastsAdapter(getActivity(), podcasts)));
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_podcasts, container, false);
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.podcasts_recycler_view);
mLayoutManager = new GridLayoutManager(getActivity(), 3);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
//mRecyclerView.setAdapter(mAdapter);
return rootView;
}
Any ideas on how to fix this?
You didn't attach the adapter because you create it after you try to attach it:
In my case:
mRecyclerView.setAdapter(mAdapter); // Here, mAdapter is null
mAdapter = new CountryAdapter(CountryManager.getInstance().getCountries(), R.layout.card_layout, getActivity());