I have an app with 3 tabs. There's a main activity, and a fragment for each tab.
In fragment 1 (the first tab) I am able to add/remove items from a list view (stored in an arraylist). In fragment 2 (the second tab) I want to populate a spinner from the arraylist in the first tab; however I notice that I am unable to access objects from separate fragments (whether private, protected, or public).
What's the best way to pass the arraylist between fragments?
Fragment-to-fragment communication should go through the hosting Activity. Pass data up to the Activity from fragment1 (probably via a custom interface, to allow easy re-use of the Fragment), and then from the Activity into fragment2. See this section of the documentation for more details:
Often you will want one Fragment to communicate with another, for example to change the content based on a user event. All Fragment-to-Fragment communication is done through the associated Activity. Two Fragments should never communicate directly.
Related
Let's say I have an Arraylist named PersonList stored in Firebase FireStore. Every Person has a bunch of attributes (name, contact number, email, etc.).
I have RecyclerView displaying each person's name. That RecyclerView is stored in Fragment A. When I click on an Item in Recycler View, I use Fragment Manager to replace Fragment A with Fragment B. Fragment B lets me view all of that person's data (not just his name), plus maybe add or edit some data as well. Currently, I am able to get that person's name from Fragment A and pass it off as an argument and display it in Fragment B.
Now I plan to get the position of that Person Object onClick in Fragment A, call another instance of PersonList and use position to get all of a particular person's data (not just his name) displayed in Fragment B. I also want to be able to edit that data in Fragment B and have the changes reflected in my Firestore. My question is this: should I keep on replacing Fragment A with Fragment B? Or should I use intent instead? I am new to Java and AndroidStudio and am just feeling my way through, any other insights or opinions with my plan are welcome.
To answer your questions:
My question is this: should I keep on replacing Fragment A with Fragment B?
That's a way to go from one fragment to another. However, a more convenient way would be to use navigation between fragments, which is a component of Android Architecture Components.
If you understand Kotlin, here is a useful article where you can see how to interact with Firestore:
How to make a clean architecture Android app, using MVVM, Firestore, and Jetpack Compose?
Or should I use intent instead?
Intents are used for navigation between activities, not fragments.
I usually open a new fragment from an existing fragment or activity. However, with an adapter, which can be used in multiple fragments / activities, how do I open a particular fragment dynamically?
I usually use the following piece of code:
Navigation.findNavController(view).navigate(R.id.action_startFragment_to_destinationFragment);
after creating an action in the navgraph.
As navigation occurs among fragments, so normally you'd keep the fragment's the responsibility to do that.
As you told that adapter which can be used in multiple fragments, so it should be attached to a particular fragment at a time, which normally it's the fragment that instantiated it.
So, you can pass a listener interface to the adapter which is implemented by the fragment; where you can trigger its callback in the adapter whenever you want to navigate to another fragment in the nav graph.
This callback method will be executed at the fragment which already implements the listener, and you can normally use the traditional navigation code:
Navigation.findNavController(view).navigate(R.id.action_startFragment_to_destinationFragment);
This way your adapter can be reused, and every time a fragment wants to reuse it, it should implements the listener.
Note: Probably you can pass an int argument to the listener callback that pass in the row number in the adapter back to the fragment so that you might decide to navigate to some other fragment.
This way you can keep the navigation only through fragments.
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 would like to create an user interface that always displays a menu panel on the left side, and a content block which changes depending on which menu entry is selected, i.e something similar to many websites.
I am new to creating Android user interfaces so I am wondering how to properly and dynamically change the content.
Is it better to create two different views, each of them including the same panel fragment (meaning 2 instances ?) and a different content fragment, and change that view using Activity#setContentView(), or should I create a single view and replace the fragment of the content dynamically ?
You should definitely use the Fragment approach.
Use a FragmentActivity and use the FragmentManager (getFragmentManager in the Activity) to create a transition and replace the Fragment depending on what item the user clicked.
See: http://developer.android.com/training/basics/fragments/fragment-ui.html
Use this below code with library from github it will answar you perfectly
https://github.com/neokree/MaterialNavigationDrawer
I have fragments 'A,B,C' inside host Activity 'H'.
I want to click a button in C, which will pull user inputted data from textviews or something in A and B. So that when it is done, I have collected all the data placed in fragments A,B and C.
I imagine this requires some sort of interface but I'm a little confused as to how this might be done.
I see this example shows how to pass data From a fragment to the host, and from the host to a fragment, but I'm not sure how to request info from one fragment to another.
Create callbacks to the host activity in A and B (see http://developer.android.com/guide/components/fragments.html#CommunicatingWithActivity).
So when the data is input, it will be passed to 'H'.
Then when the button is pressed in fragment C, it can just pull that data from the host activity.
So basically, don't communicate directly between fragments, but rather push and pull your variables from the host activity. (Use the callbacks for 'pushing').
Also, see this link: http://developer.android.com/training/basics/fragments/communicating.html