I just started with my first Android project. My application contains two fragments that are connected with the navigation controller.
As for now, all I have on my first fragment is only two EditText. However, I realize that when I switch to my other fragment and navigate back, the texts entered have been cleared.
So I would like to know what I can do to save the date and restore them when I switch it back
I have already tried saving them in onSaveInstanceState() as suggested by the majority of people, however, it is not working. So I did a little test, turns out the onSaveInstanceState() is not even being called when I switch the fragment. Instead, onDestroy() and onPause() are being called, ones where people don't recommend to save my data
I have also tried to use ViewModel to save the data but it seems that the data saved into the ViewModel is also gone when I switch back to the original Fragment.
So I am not sure what to do? Thanks!
You should use ViewModel, create your ViewModel by Activity instead of Fragment, inside your Fragment.onViewCreated() method
val myViewModel = ViewModelProvider(activity as ViewModelStoreOwner).get(MyViewModel::class.java)
Related
Hi im currently building my First android app and i have a problem that i cant solve this past 3 days. so i have MainActivity and on it there is a Fragment with Recyclerview and ArrayList< Item > listOfItem, on this Fragment there is a Floating button that when i click it will take me to SecondActivity there is a edit text on this SecondaryActivity that i have to fill then i will pass the data back to listOfItem.My problem is what method can i call on SecondActivity to create/add an listOfItem when i go back to MainActivity Fragment? I dont want to make Adapter and listOfItem to be static. Is there a way? thanks
Simple, You can achieve this by using Shared Preference.
What you need to do is just save that Edit Text data to Model(POJO), save that Model to Preference and in your Main Activity - Fragment on Resume method show updated data from that Preference.
Yeah here you need to take care of
The fragments onResume() or onPause() will be called only when the Activities onResume() or onPause() is called. They are tightly coupled to the Activity.
For more convient and efficient handling of data from any activity or fragement to any activity or fragment, you can use Event Bus.. Here is link where you will get the details information: https://github.com/greenrobot/EventBus
The best solution would be to start the second Activity for result.
startActivityForResult(ActivityBIntent)
Then checking the result overriding
onActivityResult() on the first activity and updating your list/adapter from it
I have a ViewPager with 2 tabs. Each tab just holds a Fragment with a RecyclerView. The RecyclerView in the first tab holds a list of all Articles while the RecyclerView in the second tab only holds the list of user's favorite Articles. Each Article in the first tab has a button in the RecyclerView row that allows the user to favorite it. I want new favorites to be displayed automatically (without forcing the user to manually press the refresh button) when the user navigates to the second tab. How can I go about doing this? Essentially I need to add / remove items from the RecyclerView which contains the favorites, but from the first fragment.
Things I have tried
Call adapter.notifyDataSetChanged() in the onRefresh() method of the favorites fragment. This works, but the performance hit is big because notifyDataSetChanged() is not a cheap operation. I would like to avoid this if possible.
Tried following this guide, and implemented some interfaces. The problem is, when I try to reference the adapter in my fragment from the containing activity, the adapter is always null. I can post code if needed to show what I was doing if this is supposed to be possible.
Now I am considering using SQLite DB to store changes (favorite removals/additions) in the onClickListeners, and then checking that table in the onResume() method and processing the changes individually, one by one with notifyItemChanged()
Is there a better way to do this?
For SQlite use CursorLoader to load data from SQlite. You can register to be notified when a data changed in a table. Then your loader will automatically load data again. Check this answer. Also check this Thread.
For getting data from internet you can use
Communicate with 2 fragments via parent Activity. Check this and this answer. This tutorial is good for better understanding.
LocalBroadcastManager to notify from one fragment to another fragment.
I am working on my hobby project to learn more about android programming and stuffs. So i recently ran into a simple problem but couldn't find a solution for it.
My project for now have 2 activity [MainActivity], [CommentActivity].
In MainActivity, I have a listadapter (cusAdapter) will fetch all the content from a database and display it on a listview. Everything works fine there. It will fetch all the comments and total comments for a certain post based on the post id. In the same MainActivity, i have a comment button and a onclick listener which when clicked will bring user to the next activity [CommentActivity] and load all the comments and data needed using another custom adapter. I also have a total comment TextView that will show the total comment fetched by the json and display it in my listview.
When a user posted a comment on CommentActivity, it will save into the database via AsyncTask.
Now the problem is, when i press back button and navigate back from CommentActivity to MainActivity, i use intent with flag (intent.flag_activity_reorder_to_front). So it will never reload the MainActivity again when back button is pressed. Also it will never update the total comment in the MainActivity. What i want to do is when back button is pressed on CommentActivity, i want it to refresh/reload the ListAdapter in MainActivity to fetch the latest data from database.
Also i don't want to reload the whole MainActivity, i just wanna update the view without reloading the whole activity.
I believe there must be some easy way to do this. I can post codes if you guys need it to assists me.
Thank you.
Yes, there is an easy way.
Start your sencond activity using:
startActivityForResult(intent, RESULT_CODE)
use setResult(RESULT_OK) in your second activity after doing the commit of the changes to the database
override onActivityResult() in your first activity to check when the second activity returns properly
update the first adapter as needed.
Hope it helps.
In your MainActivity you could check in onResume to see if the data has changed, as this will be called when you go back to it from the CommentActivity.
If the data has changed, calling notifyDataSetChanged() on the adapter will reload the view with the new data
How exactly v4.app.Fragment works? I have viewPager with 7 Fragments. I was sure that when moving between fragments, depending on the situation each fragment can be automatically destroyed and created. However it seems not to be true.
I decided to play a bit with debugging and set some flag for my Fragment class object, something like
class MyClass extends Fragment {
public boolean myFlag=false;
When I set ex. true somewhere in the code which is run only once (ex. true is set after button click), it seems that this value is true until the app ends. Thus it suggest the object is kept all the time in memory.
However when user moves between Fragments onCreateView and onViewStateRestored methods seems to be called.
And now I feel quite confused. If Fragments are not destroyed, why those methods are executed by Android?
Do I have the guarantee that my Fragment object will be kept always with all fields (when user only moves beteween Fragments and doesn't leave the app)?
If not how should I save and restore its state? public void onSaveInstanceState(Bundle savedInstanceState) method seems to be only run when user left the app, not when user moves between Fragments.
Have you seen any good tutorial concerning ViewPager and Fragments?
And now I feel quite confused. If Fragments are not destroyed, why
those methods are executed by Android?
If you look at this diagram, Fragments do not need to be destroyed to call onCreateView().
Do I have the guarantee that my Fragment object will be kept always
with all fields (when user only moves beteween Fragments and doesn't
leave the app)?
This depends on what you are doing. If your case is dealing with ViewPager it really boils down to what PagerAdapter you use and your ViewPager configuration.
If not how should I save and restore its state? public void
onSaveInstanceState(Bundle savedInstanceState) method seems to be only
run when user left the app, not when user moves between Fragments.
It depends under what conditions you are wanting to restore state. For example, for orientation changes you can call setRetainInstance(true) on the Fragment and the Fragment's state will be preserved when there is a configuration change given your Fragment is not on the backstack.
Have you seen any good tutorial concerning ViewPager and Fragments?
The Android Guide has a good tutorial.
You can re-initialize all the values of a specific fragment in it's onCreate(...) method. So that when ever it is navigated to, it will have the default values that you setup in your onCreate(...) method.
Here are some useful links related to the Implementation of Fragments in a ViewPager:
1. http://thepseudocoder.wordpress.com/2011/10/13/android-tabs-viewpager-swipe-able-tabs-ftw/
2. http://androidtrainningcenter.blogspot.co.il/2012/10/viewpager-example-in-android.html
3. http://manishkpr.webheavens.com/android-viewpager-example/
4. http://thepseudocoder.wordpress.com/2011/10/05/android-page-swiping-using-viewpager/
I hope this helps.
I'm looking at some demo code that shows how to use a Fragment Adapter (Tab Adapter in this case). I'm curious as to what exactly the instantiate() method does. I see it used in the following demo code on this page:
http://developer.android.com/reference/android/support/v4/view/ViewPager.html
(see the getItem() method within the TabsAdapter class)
If I'm reading the demo code correctly, every time a user clicks on one of the tabs, a new Fragment is created? And thus the fragment starts the entire life-cycle again (onAttach()...onCreate()... etc)? This sounds awfully inefficient. I would think that the fragment that will represent the content for each tab should be instantiated only once (perhaps in the addTab() method), and then saved into some collection where it can be fetched when getItem() is called.
Please correct me if I'm mistaken in any of this. I'm trying to better understand how to manage fragments.
My money would be on that the setCurrentItem() function doesn't actually destroy the existing Fragment being shown in that tab. Otherwise there's really not much of a reason for the adapter to have a List of available tabs. Likely, when you switch from one tab to another, setCurrentItem() just detaches the UI from the currently active Fragment (or calls its onPause() method) and then re-attaches the UI for the newly selected Fragment (or calls its onResume() method).
But, if you're in doubt, you could read the source :)
Hope it helps,
David
I was able to find an explanation for my question here