I am having a problem with an application that I am trying to write. The application opens 2 fragments in a viewpager which are configured to use the same cursorloader configured to use contentprovider which access's an sqllite database. The first fragment has a "category" spinner which is populated by the cursorloader and the second fragment has a "category" spinner and also an "item" spinner as the "items" are grouped by category, both spinners are populated using the same cursorloader.
From the main screen I have icons to edit/insert a "category" or edit/insert an "item". If I click to edit a "category" it loads the first fragment and selects the "category" in the spinner. If I click to edit an "item" it loads the second fragment and selects the "category" and "item" based on the item selected.
The first time I click to edit an item the second fragment loads correctly and both the "category" and "item" spinner are displayed correctly, however if I go back to the starting screen and click to edit another "item" the second fragment loads but no data is displayed. After debugging I can see that the second fragment is created and the cursorloader is initialised (initloader) and onCreateLoader is called then the first fragment is created and the cursorloader is initialised (initloader), onCreateLoader is called followed by onLoadFinished. onLoadFinished never gets called for the second fragment and hence no data is displayed. If I swipe to the first fragment and back to the second fragment it finishes the original call.
Is this an issue that you cannot use the same CursorLoader simultaneously?
I have tried using the getLoaderManager().getLoader("data") to determine whether to use initloader or restartloader but each fragment seems to have its own loader and getLoaderManager().getLoader("data") always returns null. I have also tried setting up a view of the table and accessing the table via the cursorloader on one fragment and the view via the cursorloader on a different fragment.
I hope you get an idea of the problem I am facing and can either suggest a fix or even a different way of using the same data in two fragments. The reason I decided to use cursorloader was due to how it integrates with spinners and updates the data held in the controls by itself. If need be, I can post some code.
Update
After further investigation the onStart() and onResume() methods of the second fragment are not being called after being created the second time, although when I swipe to the first fragment and then back to the second they are then called.
Related
I have a Viewpager Activity with three fragments inside it. The activity has an filter with list of filter options. When activity is started the filter options list is fetched from the server and then the first filter is selected by default.
Fragment A ViewModel --> contains getXList(selectedFilterOption)
Fragment B ViewModel --> contains getYList(selectedFilterOption)
Fragment C ViewModel --> contains getZlist(selectedFilterOption)
So first filter options is fetched from the server and then adapter is set with the first selected option.
As its a viewpager it loads the first as well as second fragment i.e Fragment A and Fragment B will be loaded.
Now suppose, Fragment A is visible and fragment B is already loaded and filter option is changed. As different filter is selected the data needs to be updated in every fragment based on the selected filter.
This is handled like this :
As filter is changed , the current fragment's data is reloaded. OnPageChangeListener is implemented and on its change respective fragment's data is reloaded.
But due to this, everytime a tab is changed ,api call is triggered and data is fetched.
Second thing when the activity is loaded for first time it has already loaded the second fragment. So on tab change the second fragment's data is going to be loaded again which should not happen.This can be avoided with the checks but its going to be a mess.
Is there any better approach using observable pattern, the fragments data can be loaded after filter option is changed.
You can call api once the activity is started..After getting the data
you can create tab and through the viewpager you can pass the value
with doing filteration.. This will not call api again as long as you
stay in activity
Additionally if you want some observable you can see and use greenrobot event bus. It's pretty simple eventbuslibrary
I have a custom ListView inside a fragment that represents a list of activities. Each activity is saved in a database (I'm using Parse), and the ListView is populated with the Activities from the database. There is an add button in the fragment that takes the user to an screen where he/she can create a new Activity object. When the user is done, the activity is finished (I call finish() on the Activity), and the fragment is brought back up. The problem is that the ListView doesn't refresh- it's the same list before the user was sent to the Activity Create screen.
I tried to override the onStart and onResume in my fragment class and call notifyDataSetChanged() or invalidateViews() but neither method works, the list view doesn't refresh so it includes the new Activity that was just created by the user.
Start the activity that adds Activity with startActivityForResult(). Override the onActivityResult() in your listview fragment to get notified when the user has finished adding an Activity. Then, refresh your ListView by querying the database again or adding the new Activity to the adapter (depending on how you implemented the listview adapter).
In your case it looks like you forget to refill the activity list attached to adapter from which listview generate views.
Refill the list again from scratch and then call notifyDataSetChanged();. Your listview will be updated with new entries.
Cheers
So I currently have an app that has 4 tabs (fragments). They are fragments A,B,C,D, in that order.
Fragment A is the first view opened (along with B because viewPager loads the view before and after the current view).
When I click a button in Fragment A, it sends Data back to MainActivity and then sends that data out to Fragments B and C.
However, this is where the issue comes into play. Since Fragment B was already called, the View isn't updated once I click the button and send the data over, but Fragment C is because the view wasn't called before.
Is there any way that I can remedy this?
You can do it a few ways right.
Just set the data to the fragment and have it update its views
Have all the fragments like B and C register themselves to recieve data from the MainActivity and when MainActivity gets it's data set you tell all the registered receivers of the new data
Recreate the fragment
Use an event bus and tell all subsribers of the new data and MainActivity, Fragment B would get notified of new data. Fragment C would get its data when created by MainActivity
I think this list is pretty endless tbh
The key here is the fragments need to fetch the data from the actvitiy aswell as be updated by the activity. In which case you need to break your UI update behaviour out of onCreateView and into its own updateUI() function. updateUI(MyData) can then be called from onCreateView and also called in a setMyData() on the fragment. Just make sure you check the isAdded flag in setMyData.
This pretty much says it all:
http://developer.android.com/training/basics/fragments/communicating.html
I used a simple fragment communicator that allows the activity to call the fragment, and the same for a fragment to talk to the activity.
You can change the views with the new data based on calling the method from within the activity. The way I do it is set the fragments in the activity then pass them into the page adapter this way I can call the methods within the fragment and implement the fragmentcommunicator interface on the fragments.
You can honestly even avoid the interface if you want, but if you are going to include the same method in all the fragments to talk to them it is easiest.
If you show code, I can show you a quick example.
I have 2 fragments which are called from the action bar of an activity. Both are gridviews, the first one displays applications with a dedicated adapter, and the second one displays a file list with another adapter. My problem is that when I launch a file then when I back to my activity I switch from one fragment to another, when I come back to the previous one, its content disappears. And when I rotate tablet I have the some problem, because my Fragment restart so for this I think that removing fragment give the possibility to create a new Fragment up to date. How can I save and reload data in my fragment.
How can I manage to update the content of the first fragment while coming back from the second one ? And how to remove fragment after the rotation in order to recreate the Action with new Fragment? I asked this questions but I don't have any responses. the code is given below
If your data is just strings or integers, you can make use of shared preferences to store and retrieve data.
Solution to your first problem -how to save fragment state
Use setRetainInstance(true) in you fragments onCreate() *it prevents your fragment from destroying and hence recreating.
Add your fragment to back stack
declare your adapter globally in fragment and resuse it when you get back.
when, you get back to fragment its onCreateView() method will be called directly. hence initialize your adapter in onCreate() method and use it in onCreateView().
Solution to your second problem -how to update fragment content
For this you can use interface. create interface in your second fragment and implement it in your first fragment. prefer this doc for this,
http://www.vogella.com/tutorials/AndroidFragments/article.html#fragments_activitycommunication
I have a ListFragment, which data is loaded by a SimpleCursorLoader(own imlementation; it loads with a curser and does not use URI).
When an item in the list is selected. I either start up a new activity (detail activity) or I show what is selected in the detail fragment next to the ListFragment. Depending on the screen size.
If the detail fragment is added to the ListActivity, I have figured out how to reload the list. I assign an interface to the ListActivity and call it from the detail fragment, when the change is happening. And in the list fragment I reload the list using getLoaderManager().restartLoader(0, null, this);
Now my problem is, if the detail activity is loaded, I don't have access to methods on the ListActivity. I could probably implement some observer pattern. But there must be a best practice for this.
How do you make a ListFragment reload the list, when a detail fragment has changed the data in the database.
Try moving your list creation code to onResume. That way it runs on activity creation and every time you go away from the activity and come back.