I'm a newbie to android app dev and I have one little problem. I'm developing a note app with a single activity(MainActivity) which has a NavHost and host three fragments(NewNoteFragment, NoteListFragment and NoteUpdateFragment). The note details are stored in a sqlite database.
Whenever user creates new note or update the existing note, the changes can only be stored to the database in NewNoteFragment or NoteUpdateFragment's onPause override i.e when the user navigates from the said fragments to the NoteListFragment. Although the changes were saved but the recyclerView in the NoteListFragment doesn't update immediately until i kinda navigate away from the NoteListFragment to other fragment.
When I check the logcat i noticed the onResume override(which is where I called my adapter.notifydatasetchanged() method) in my NoteListFragment is called before onPause override of the replaced fragments.
Is there a way to change the fragments navigating behaviour where onpause is called before the onresume? Or any better way to achieve my said aim.
You cannot set onPause to be called before. Since you are using fragments try to update the recyclerView onViewCreated() function of Fragment.
You cannot change the Android Lifecycle, it is always set.
I would advise using Room and LiveData, any changes in the database would automatically update the RecyclerView you mentioned.
You can read more about live data here
Related
I am implementing a small app where I have a list of items (1).
With a fab button I start another activity that is able to add a new item (2).
In (1) I have a ViewModel loading data from a repository.
In (2) I store the new item on the repository.
When the user save the data in (2), that activity is closed (calling finish()), but "of course" in (1) I don't see any change.
I read around that I should call notifyDataSetChanged() on ViewModel used in (1), but I do not understand where: in (1) in method onResume()? or in another place?
Can you help me? Maybe e simple tutorial explaining this specific aspect?
If you are using just a repository without any modern storage like Room or Datastore and just save the data in memory(Repository) then you should make your repository Singleton and save items in LiveData OR Flows inside repository then observe it.
I'm practice in using Navigation component. Now i have a trouble. I'm using Room database and i'm update it in my Fragment multiple times. Somehow it's anyway taking my last result no matter that i'm updating it so i decided that i need to update my fragment but i don't know how. I'm already found solutions like to detach and then attach fragment but i don't know how to do it because in my MainActivity i'm attaching to my fragment through "setupActionBarWithNavController".
I think you are overcomplicating matters. If you are using Room to manage your data, and the values in the database are getting updated by your code, then you can simply use LiveData. You don't need to reload your fragment at all.
Have your Room DAO query return a LiveData<MyType> instead of just a MyType object (for example). You can then "observe" the LiveData in your Fragment, and write a callback function to update your UI every time the value returned by the query changes. See this page for more info.
This basically means that when you tell your model to updateInsulin, once the database value is changed, the LiveData watching your insulin level will change and trigger your Observer. The Observer can then do something like change the text of a TextView or naviagte to a different Fragment.
I have 3 fragments and a bottom navigation menu to switch between them.
In every fragment i have a recyclerview to display data gathered from FirebaseDatabase.
My question is: Should i use Replace() fragment? As it would result in restarting the fragment and requesting again Firebase SingleEventValue every time the user navigate between fragments
Or i must use Add Show Hide? Or that would lead in memory leaks?
The methods you use to deal with the fragments are mostly not relevant. The Firebase SDK will cache data previously fetched, so if you make a second request for some data, from any point in your app, you will be seeing cached data, and it will even work offline. There are no "leaks" involved here when using single value events.
Adding a listener to a database location is a different matter. Ideally, listeners should be attached when a fragment becomes visible, then detached when not visible.
I have a Fragment that shows some data saved in android Preference.
when these data changes due to various operations of the app, I want to update the fragment with the new data.
I have tried to use
myFragmentTransaction.notifyAll();
But unfortunately doesn't work and the fragment is updated only when I reopen my whole Activity
Houw could I refresh the Fragment on data changes?
notifyAll pertains to threading. Completely unrelated to what you are doing. Instead of trying to tell each fragment to redraw themselves have you tried OnSharedPreferenceChangeListener. Each fragment should listen to changes in the information they care for.
Let's say I have a list of homogenous items which is likely to be changed in the lifetime of my Activity by user interaction or OS events. The Activity contains a FragmentPager which shows a number of ListFragments.
These fragments share the previously mentioned data but display it in different ways. E.g. they differ in sorting order or display only a subset of the data. Currently each fragment keeps a separate list containing the respective part of the data in the respective order.
When the data changes, basicly every fragment has to be updated. This means resorting or adding/removing items from some of the fragments. What is the best practice to keep the data in the different fragments consistent?
Currently I have some sort of an observer object, which is notified when something changes and subsequently notifies the connected fragments. But there are a couple of problems:
When the app just started, some of the fragments haven't been created by the FragmentPager, so notifying them is impossible.
When swiping through the fragments some of them get paused. In this state, they can't update their list. Should they disconnect from the observer in this case? This leads to:
When a change happens, while a fragment is disconnected, it basicly misses it.
And so on...
If I understood your ViewPager shows the same data (or it's portion) but in different views. So, I belive ViewPager shouldn't act in any way when data is changed, it's responsibility of Adapter.
About points below you said:
a) creating of fragments inside ViewPager can be managed by you. Just see javadoc of ViewPager::setOffscreenPageLimit(int limit) method.
b) I think you should do nothing with UI when data changed but fragment is in paused state. If you want to update do it in onResume(). Or better to set some field in DB (if you have) to "updates present" state and check it when Activity(Fragment) appears.
c) As in previous option - if fragment disconnected just ignore updates. Or if you really interested in that update use sticky BroadcastReciver (be carefull sticky BR is expensive thing)
You can keep your data in Application class, update only visible fragments when data has changed, and always ask for the new data in Fragment's onResume(), that'll do it
What I would do is have each ListFragment use a Loader to load its data. Then, instead of having the observer notify the Fragment (which might have been killed) to refresh its data, register an observer for each Loader so that it will know when the data source has changed, and will re-query when one has been detected. (If your data source is an SQLite database and you are using a ContentProvider, the CursorLoader will do all of this for you).
This is the implementation I would recommend because
Each Fragments behavior remains self-contained (i.e. each is a re-usable component that is not tied to any specific ViewPager or Activity).
It avoids the complexities of having to deal with potentially destroyed Fragments within your ViewPager.
If you need a quick fix, you could probably get away with forcing the Fragments to remain in memory using ViewPager#setOffScreenPageLimit(int limit) as Ivan suggests... however, this isn't as clean of a solution in my opinion.