Android: Preserve complex view data of Fragments - android

In my application I have a FragmentActivity that uses a FragmentViewPager. The Fragments have a quite complex structure of views with ListViews and Adapters. The FragmentViewPager appears to destroy the Fragments that are out of sight, and to recreate them if the user swipes back to it. This leads to all member variables are cleared that hold the lists and adapters with all content, so the Fragment is empty if it comes back to the top.
My question now is: How can I preserve these data? If I'm not mistaken, I have to save and resume the list with the content the adapter works on. When and where should I save it?
Is it a good idea to save the data in the FragmentActivity or in a helper singleton class outside the activity?

How can I preserve these data?
Your data is already "preserved". You loaded it from somewhere originally from some data model. Load it again.
If there are changes the user is making on-screen to the data, you need to be persisting that to your data model as the user makes the changes. This is no different than dealing with, say, a RatingBar in a ListView row.

Related

OnScreenRotation with RecyclerView in tabbed Activity

I am using a tabbed Activity. In one of the tabs I have two buttons and a Recyclerview. In the RecyclerView I have two spinners and an edittext.
The purpose of the first button is to add a new item in the RecyclerView and the second one is to save the chosen elements in the spinners and edittexts.
My problem is that when the screen is rotated, the Recyclerview is emptied. I tried using the OnSaveInstanceState() and the OnRestoreInstanceState of the LayoutManager of the Recyclerview to save the state but it still gets deleted.
I'd appreciate any help !
By default, activities and fragments have an onSaveInstanceState() method that the system uses to provide a Bundle to which you can write primitive data and parcelable objects.
This is okay as long as your data is simple. In your case, it isn't.
The framework may decide to destroy or re-create a UI controller in response to certain user actions or device events that are completely out of your control.
For example screen rotation (orientation change).
ViewModel comes to the rescue.
ViewModel is a class that’s part of the Android Architecture Components and it is lifecycle aware.
For more check this documentation.

Best User Experience when navigating between 2 Lists (Fragment / Activity)

This question is more my way of gauging a better understanding of the "Proper" way to handle this content flow instead of just "whatever works" or the "quickest" solution to code. Im looking for the best on performance and user experience.
The situation:
So my main activity handles my NavigationDrawer and is the basis of the app. The initial view that is loaded (navitem 0) is a Fragment which contains a RecyclerView(custom adapter, list item model, view holder). This list displays data pulled from an XML file and is returned as an Arraylist of Topic objects (each containing 3 strings and an array of Issue objects).
The array of Topic objects are used to populate the listitem w/ a title, desecription and image_name strings. (Not using the Issue array yet).
Here is where you come in ...
I know need to handle the click event on the Topic and display a new list (w/ different adapter) of the specific Issue object array for that Topic.
I'd like to know if its better to replace the current fragment w/ a new fragment for handling the Issue data. Or would it be better to launch a new activity to display the Issue list data.
Keep in mind, i want to ensure that navigation up will return the user to the previous view. ie. when clicking a Topic you should get the Issues for that topic. When going back, the TopicFragment should be displayed w/ its initial list.
If this is confusing you?
The core part of this question is needing to know the proper navigational way of displaying a List that when clicked needs to display another List specific to the parent object. Is fragment to fragment handled by callbacks in the MainActivity the best way, or is Intent'ing to another activity to handle the 2nd list better?
Whether you use a Fragment or an Activity to display the second list, it doesn't matter from a performance standpoint. If I were you, I'd use an Activity: it is always better to use a Fragment only in situations that require the explicit use of Fragments (such as a FragmentTabHost or a ViewPager).
But I do have another suggestion for you. Instead of going to another list, why not display your Issue objects as the child items of an ExpandableListView, and the Topic objects as the parent items ? Then when the user clicks on an Issue child item, go to the detail page containing details of that Issue object. To me, the List->Detail pattern is a far more familiar idiom than a List->List->Detail flow. Its what ExpandableListView was made for.

FragmentTabHost - don't destroy fragments

Can I tell FragmentTabHost to not destroy fragments(views) when I switch tabs? In one of the fragments I fetch some data from the Internet (or from a local database, depending on the situation), which takes a bit of time. I want to always keep this fragment in memory when it's posible.
I like the way ViewPager handles it with setOffscreenPageLimit() set to something bigger than 1.
A better solution would be to use a retained fragment without UI for fetching data and posting it to other fragments when data is there. The logic would be like this. Every fragment asks the retained fragment for data. If data is not there, they show "loading" state. If data is there, they show the data. If you want to have an event based communications between fragments, instead of calling fragments through interfaces, you can have a look at Otto event bus.

Getting data (asynchronous) and populating ViewPager's fragments

I have an activity with a ViewPager with a variable number of fragments (tabs).
Upon start the activity checks if the associated (complex) data has been loaded. If it hasn't it shows a progress bar view and starts an AsyncTask which fetches the data. Depending on the data the activity creates a number of fragments (tabs) and gives each fragment a sub set of the data.
I currently hold references to the fragments (I know that it is discouraged) and I run into all sorts of problems when the fragments gets reused - I'm giving the data to the wrong instance of the fragment.
So, is there an "android way" of solving this problem?
I run into all sorts of problems when the fragments gets reused
Fragments usually don't get reused in a ViewPager. This is not like an AdapterView where rows get recycled. Using FragmentPagerAdapter or FragmentStatePagerAdapter, a fragment represents one and only one page.
I re-instantiate the ViewPager each time (but the fragments get reused?)
Ah. That's a slightly different problem.
The stock implementations of FragmentPagerAdapter and FragmentStatePagerAdapter make a couple of assumptions:
They are in complete control over the fragments, particularly in terms of running the transactions to add and remove them from the UI
That those fragments will only ever be used by one "logical" ViewPager (IOW, recreating that ViewPager for a configuration change is fine, but that' pretty much it)
Complicating matters is that these adapters store the fragments under certain tags, and therefore if those fragments still exist in those tags, those existing ones will get used, instead of new ones being created.
So, is there an "android way" of solving this problem?
It's unclear from your question why you even need to "re-instantiate the ViewPager". I'm assuming that this is tied to some sort of refresh operation, or something else that is forcing you to go through the process described in your second paragraph.
You could give my ArrayPagerAdpater a try, as it is friendlier about external agents mucking about with the fragments. Since you control the fragments' tags, you can always be certain that you are working with the right fragment -- rather than caching them yourself, just retrieve the right one and manipulate it.

Pattern for using dynamic loaders to load ListView pages in a ViewPager without ListFragments?

If I have a ViewPager with a certain number of pages, what would be the best way of loading the data for each page using the Loader framework? Each page contains a ListView with its own adapter instance.
Use a separate loader for each page; or
Use a single loader that checks which pages are not loaded and loads them
The thing is, it's possible the user may want to quickly swipe through a bunch of pages and thus it should be easy to "cancel" loading pages that aren't needed for performance reasons.
On the other hand it seems like there might be an overhead with having a lot of loaders.
EDIT: My Loaders actually need to have dynamic IDs to represent the content they are loading. I'm probably going to go with using a mask on the loader ID, and then once the loader is done call destroyLoader().
I would use a separate Loader for each ListFragment. Things will get messy very quickly if you try to manage the fragments' Loaders from the parent Activity (especially if those fragments are being held by a ViewPager). Fragments are supposed to be designed for reuse and should not rely on a specific Activity in order to function properly. The fact that each Activity and each Fragment get their own LoaderManager instance is further evidence that the Android team didn't want developers to have their Activitys loading data for its attached Fragments.
I don't think there will be as much overhead as you are probably expecting there to be... Loaders should retain their data across the component's lifecycle and re-query only when the underlying content has changed. It might be a good idea to use a FragmentStatePagerAdapter too.

Categories

Resources