Load data to a list fragment tab on the creation of the MainActivity - android

I am absolutely in love with these new components Android is introducing. So, I am building a standard mobile application with solely one activity using the Navigation components and Architecture components such as a View Model as I am performing a lot of communication with my data that I stored in room.
In one of my bottom navigation tabs, I have a list that is loaded from all my data in room. So far, I have set up my RecyclerView and my adapter in the OnCreateView() (only function used in this fragment) of this list fragment and every thing shows successfully.
The problem is that every time (especially more at first view) the fragment takes a solid 10 seconds to display all the data (which is normal considering there is a lot of it).
My question: Is there a way the adapter and and RecylcerView of this specific fragment could be setup (and load all my data) in the OnCreate() of my sole activity? So that when I view the fragment for the first time, everything pops up right away.
Also, how would I go about using OnPause() of the list fragment so that when I am on another tab, the list fragment doesn't get destroyed and when we go back on it, it displays right away?

Fetch all data from room inside onCreate() method of fragment. The onDestroyView() method calls everytime you moves away from the fragment.
To prevent recreation of views inside fragment store view in a variable.
Example:
class YourFragment extends Fragment{
View rootView;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
//fetch data from room
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState){
if(rootView == null)
rootView = inflater.inflate(R.layout.your_fragment_layout, container, false);
return rootView;
}
}

Related

keep each fragment selected inner ViewPager?

I implement the same fragment of 100 in ViewPager on my application. The fragment rather large display data from the server. When I put the code mViewPager.setOffscreenPageLimit (100), the app feels very heavy. Therefore, I use the way: remove setOffscreenPageLimit and invoke a method to check the data on the server and displays it when the fragment was selected. But when this happens: when Fragment "1" was chosen, then to fragment "2", back to fragment "1", Fragment "1" will repeat the activity. My question is how to keep the activity of each fragment is selected or when returning to the fragment that was selected at the last condition? Sorry for my English.
setOffscreenPageLimit : Set the number of pages that should be
retained to either side of the current page in the view hierarchy in
an idle state. Pages beyond this limit will be recreated from the
adapter when needed.
Don't setOffscreenPageLimit too large, because the view pager will keep the page active so your app will run slowly. And when you remove setOffscreenPageLimit, this setting defaults to 1. It means that pages beyond this limit (1) will be recreated from the adapter when needed.
https://developer.android.com/reference/android/support/v4/view/ViewPager.html#setOffscreenPageLimit(int)
if you remove setOffscreenPageLimit, The way to keep the activity of each fragment is store the state data of fragment in:
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putData("key", fragmentData);
}
when you leave it, when you back again, you update the fragment by the state data you have stored.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
fragmentData = savedInstanceState.getData("key", defaultData);
}
You should use some fragments in a viewpager, do not use too more. think about use a fragment and display many views, data in it.

Fragments: Replacing a fragment causes it to reinstantiate on back pressed

I am using one activity all fragment approach. Now I have a fragment A and when I go to fragment B I replace A in container with B with
.replace(R.id.master_fragment_container_above_toolbar, fragment)
.addToBackStack("")
.commit();
As you can see, I have added fragment to backStack. But now when I press back on device, it re-instantiates the fragment A and thus takes time to go back.
Is there another way to do it? I don't want to use add(), if I add multiple fragments to container, it will take up a lot of memory.
The short answer - there's no silver bullet in your case. You'll have to use replace() and it will re-create fragment's View on going back. That's "by design".
The good news is that there're a few tricks you can do to make it less dramatic for UX.
Cache whatever you can. If you load content from web - write it into the local SQLite db. And fill the screen from Local Storage while refreshing the data from the server.
In onCreateView() avoid re-creating Adapters once they are already exist. If user is getting back to FragmentA from the FragmentB, FragmentA will recreate its View. But it doesn't mean, that local variables are null at this point. So I do it like this:
public class FeedFragment extends Fragment {
private FeedAdapter adapter;
......
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = initialize(inflater, container, R.layout.fragment_with_recyclerview);
....
if (adapter == null) {
adapter = new FeedAdapter();
}
RecyclerView recyclerView = (RecyclerView)rootView.findViewById(R.id.recyclerView)
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));
return rootView;
}
}
It matters, because filling TextViews, etc. are so fast operations, that you don't really care about it, while huge ListView or RecyclerView can be much more expensive;
Use image-caching and good image-loading tool. I'd recommend Picasso from Square. It has automatic memory and disk caching;
Try to logically decouple your app. Let's take a Gmail-style application, as an example:
It has NavigationDrawer, which is switching user through the root fragments (i.e. no need to keep navigation stack). Once you open mail-thread - it replaces the root fragment with MailThread fragment. There you can consume the content.
But once you click on "Compose email" - you are redirecting to a separate Activity - as you move from consuming content to composing content state (I.e. significant change in user's behaviour: new user scenario == new activity).
Many top developers go even further and having Activities for pretty much everything. Twitter (and it's satellite products) as an example. But personally, I prefer to keep it in balance (as opening new activity is an expensive operation from perf. point of view).

Android - How the state of views are preserved during Fragment Transforamtion

This confuses me a lot.
I had two fragments, and I use FragmentTransaction.replace() the swap the two fragments. State of some input controls like RadioGroup and checkbox is always preserved when I switch to the other fragments and switch back again.
.
I set break point on my OnCreateView() of Fragment, and every swap seems to trigger the method and new views are created each time. The savedInstanceBundle is always null as well. Since the new views are created, how do they get the state of the old views?
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_fieldsetup_marking, container, false);
// ...
return v;
}
This effect is fine for my app, but I just want to know how it is implemented.
where are the states stored?
Where is the android SDK code to restore this (I can not find any in the class FragmentTransection).

Fragment save the state of a listener

In an Android Fragment, which is a part of a ViewPager, there is a ListView with EditText for filtering.
filterEditText = (EditText) view.findViewById(R.id.filter_friends);
filterEditText. addTextChangedListener(textWatcher);
When I navigate to another Fragment ondestroyview is called and then when I navigate back to this fragment onCreateView is called and the filtering doesn't work anymore, though the instance variables still exist.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_new_game_facebook, container,
false);
return view;
}
How this situation should be handled correctly?
You are probably using a FragmentStatePagerAdapter, which will destroy all non-active fragments to save memory. This is helpful for when you do not know how many fragments you will use until runtime, but is overly aggressive if you know which fragments will be in the pager. Try using a FragmentPagerAdapter instead, which will not destroy the fragments as soon as you navigate away from them, so you will not need to manually persist the state of each fragment and reload it.

Populating ListFragment from JSON

I've an Activity that extends ActionBarActivity and implements ActionBar.Listener.
It's acting like a View Pager. Inside that I have 3 ListFragment (organized in 3 tabs).
Now, I need to populate fragments with data from a back end.
Could you help me to organize code structure?
Should I use AsyncTask or a Loader? Is it better to put them in a separate public class?
Is it a good idea using retained fragments to preserve data through tabs swipe and
configuration changes?
The result I've in mind is a big loader image, placed in the center of the fragment waiting
for data. After a while it disappears and shows records inside ListFragment rows. Where should I put
the call to the AsyncTask (assuming use of this class)? In activity? Inside each fragment?
Which is the correct way to communicate to fragment that activity is calling onPostExecute and data are ready for use?
I'm quite confused about that, I just need a good way to start, it seems that everyone is approching
this in a different way and I don't know which is the best...
I've used json to populate a listfragment like this:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View view = inflater.inflate(R.layout.activity_lista_ordens, null);
context = inflater.getContext();
ordemServicoLista = new ArrayList<HashMap<String, String>>();
}
Here i execute the method to call webService and put all information in a listAdapter:
new CarregaOrdens().execute();
setListAdapter(adapterListaOrdens);

Categories

Resources