I have a view pager with multiple fragments but, I'm facing some performance problems as the onCreateView of the fragment is really slow. I've seen that the fragment takes some time to create the view, why is this?
In order to solve that I've thought about using a private variable so the view mustn't be recreated each time. The code would be as bellow (as you can see in the code, the content of the fragment is just a recyclerview):
private View iView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if(iView != null) {
return iView;
}
iView = inflater.inflate(R.layout.fr_view, container, false);
rv = (RecyclerView) iView.findViewById(R.id.rv);
rv.setHasFixedSize(true);
final GridLayoutManager iLayoutManager = new GridLayoutManager(getActivity(), MAX_COLUMNS);
rv.setLayoutManager(iLayoutManager);
rv.setAdapter(iAdapter);
rv.setItemAnimator(new DefaultItemAnimator());
return iView;
}
Is that a good solution? Why inflating the view may be taking so time?
Thanks in advance!
Related
I have a question. Currently, I am creating a small Android app with Android Studio. I have two fragments. In fragment 1 I have an overview of tiles. These are passed to the RecyclerView via an adapter. This is all handled in onCreateView.
When clicking on a card, I get to fragment 2 using navigation (NavHostFragment.findNavController(CategoryFragment.this) .navigate(R.id.action_Category_to_Second);) This works.
When I click the back button from fragment 2 (toolbar) to fragment 1, the view remains empty. Why? Or does anyone know a code example where I can rebuild this?
Am I doing something wrong here by overdriving the view?
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(R.layout.fragment_category, container, false);
categoriesData = new CategoriesService( view.getContext(), this.queue, this.sharedPreferences);
categoriesData.loadData();
CardViewAdapter mAdapter = new CardViewAdapter(view.getContext(), categoriesData.getCategories());
mAdapter.setClickListener(this);
recyclerView = view.findViewById(R.id.categoriesGrid);
recyclerView.setLayoutManager(new GridLayoutManager(view.getContext(), 6));
recyclerView.setAdapter(mAdapter);
view zurückgeben;
}
For some reason my recyclerView doesn't attach to the Firebase RecyclerView adapter. I'm implementing the recyclerView inside a fragment that shows in a tabbed activity. my code (relevant parts):
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = LayoutInflater.from(container.getContext())
.inflate(R.layout.fragment_fresh, container, false);
// Initialize ProgressBar and RecyclerView.
mProgressBar = (ProgressBar)rootView.findViewById(R.id.progressBar);
mSessionRecyclerView = (RecyclerView) rootView.findViewById(R.id.sessionRecyclerView);
mLinearLayoutManager = new LinearLayoutManager(getActivity());
mLinearLayoutManager.setStackFromEnd(true);
mSessionRecyclerView.setLayoutManager(mLinearLayoutManager);
//implement recyclerview
mFirebaseDatabaseReference = FirebaseDatabase.getInstance().getReference();
mFirebaseAdapter = new FirebaseRecyclerAdapter<Session, SessionViewHolder>(
Session.class,
R.layout.item_session,
SessionViewHolder.class,
//change back to SESSIONS_CHILD
mFirebaseDatabaseReference.child("test")) {
#Override
protected void populateViewHolder(final SessionViewHolder viewHolder,
Session session, int position) {
//implementing populateViewHolder..
}
};
mSessionRecyclerView.setLayoutManager(mLinearLayoutManager);
mSessionRecyclerView.setAdapter(mFirebaseAdapter);
return inflater.inflate(R.layout.fragment_fresh, container, false);
}
}
The XML is just a recyclerView and a progressBar.
Worth mentioning that I've gone through this thread.Tried setting recycler's size to wrap_parent, move setAdapter to onCreate, and pretty much every other answer - to no avail.
EDIT: I got this working when inside an activity, but whenever I try from within a fragments I get this error. Also tried with a regular recyclerView and a custom adapter and the same thing happens.
Does the recyclerView attaches itself to an adapter differently in a fragment?
OK, I finally fixed it. The problem was actually in the tabbed activity - the getItem method inside the PlaceHolder fragment created a new instance of PlaceHolder.
Therefore, my fragments hadn't even been created.
None of the threads on the skipping layout advise checking that, hope this helps.
I checked all answers about my problem on StackOverFlow but no one solves my problem.
I have a Fragment and init RecyclerView in the onCreateView method and nothing more.
But I still have problem.
my code:
private RecyclerView mStatisticView;
private StatisticAdapter adapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_stat, container, false);
mStatisticView = (RecyclerView) v.findViewById(R.id.rv_stats);
mStatisticView.setHasFixedSize(true);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
mStatisticView.setLayoutManager(linearLayoutManager);
adapter = new StatisticAdapter();
List<StatisticLabel> list = new ArrayList<>();
list.add(<Data object>);
list.add(<Data object>);
list.add(<Data object>);
adapter.addItems(list);
mStatisticView.setAdapter(adapter);
return v;
}
Could you please help me, what is wrong?
You shouldn't be worrying much about this message at all. This happens when the RecyclerView is in layout phase and attempts to check if in that same phase can layout also its children. So everything is laid out in one phase. After you set the adapter this message will not appear.
In the methode onCreateView() the Activity is not finished loading, so getActivity() should return null.
This could become a problem, so try to set your things in onActivityCreated()
Im using 3 fragments in my ViewPager adapter. I will be loading data from Parse(parse.com) and displaying them in recycler views. The following code is causing my app to crash. What my understanding is that when my MainActivity loads, this is my first fragment ie, it gets viewed by user immediately so the setUserVisibleHint function gets called immediately and in that v.findViewById code causes a null pointer exception since setContentView hasnt/ may not been called. My proof for this is if i add a 1sec delay to setUserVisisbleHint then my code works properly.
Now I want to add server PULL requests using Parse, add data in a list to an adapter and populate recyclerview AFTER user views the page so
1) Should i add all the code in setUserVisisbleHint and just add a 0.5secc delay so it gets executed after setContentView is called ensuring I dont get a null pointer exception error OR
2) Is there a better way/ other functions I can use to achieve the same?
public class NewsFeed extends Fragment {
LinearLayoutManager mLayoutManager;
boolean _areLecturesLoaded=false;
View v;
ProgressBar bar;
public NewsFeed() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
// Inflate the layout for this fragment
v=inflater.inflate(R.layout.fragment_news_feed, container, false);
RecyclerView mRecyclerView = (RecyclerView)v.findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(v.getContext());
mRecyclerView.setLayoutManager(mLayoutManager);
MyStickyAdapter mAdapter = new MyStickyAdapter(v.getContext());
mRecyclerView.setAdapter(mAdapter);
// mRecyclerView.addItemDecoration(new StickyRecyclerHeadersDecoration(mAdapter));
return v;
}
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser && !_areLecturesLoaded ) {
_areLecturesLoaded = true;
v.findViewById(R.id.asd).setVisibility(View.GONE);
}
}
}//Closes Fragment
Im using this library for my recycler view StickyHeaderRecyclerView
I would highly recommend avoiding adding delays especially if you're running this on the main thread. To avoid the NPE, try moving the findViewById(R.id.asd) into your onCreateView method after you inflate the view:
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
// Inflate the layout for this fragment
v=inflater.inflate(R.layout.fragment_news_feed, container, false);
v.findViewById(R.id.asd).setVisibility(View.GONE);
This is assuming that R.id.asd is in R.layout.fragment_news_feed
This post could also provide some insight:
setUserVisibleHint called before onCreateView in Fragment
Anyone have issue that RecyclerView doesn't save scroll position after changing orientation?
mMyAdapter = new MyAdapter(context, MyAdapter.generateKey(this), savedInstanceState);
mMyAdapter.setHasStableIds(true);
mLayoutManager = new LinearLayoutManager(context, VERTICAL, false);
int padding = ResourceUtils.dp2px(context, 8);
mRecycleView.setClipToPadding(false);
mRecycleView.setPadding(0, ResourceUtils.getPixelSize(R.dimen.toolbar_height), 0, padding);
mRecycleView.setOverScrollMode(View.OVER_SCROLL_ALWAYS);
mRecycleView.setLayoutManager(mLayoutManager);
mRecycleView.setAdapter(MyAdapter);
mRecycleView.setHasFixedSize(false);
mRecycleView.setOnScrollListener(mScrollManager); // only to hide Toolbar on scroll
so i'm not modifed onDestroy or OnSaveInstanceState methods, only saving adapters data, so when i'm rotating phone, scroll position of RecyclerView reseting, some advice?
Recently I've improved and created a FlexibleAdapter pattern for all RecyclerView. It is able to maintain the state after rotation.
Very simple to use, just copy 2 classes in your common files + some xml in order to enable the selection (Single/Multi) as it was for ListView.
Please have a look at the description and full working example: https://github.com/davideas/FlexibleAdapter
I understood where i had mistake, i used RecyclerView from
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
//used this instance of recycler view
mRecyclerView = inflater.inflate(R.layout.recycle_fragment, container, false);
return mRecyclerView;
}
but need to
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// instead of searching it after view created
mRecycleView = ButterKnife.findById(getView(), R.id.recycler_view);
}
Problem solved