Communication between multiple fragments - android

I've a "A" fragment as follows (recyclerview):
https://img.exs.lv/e/z/ezeliitis/frags.png
How should I effectively duplicate fragment "A" with different images/text (same layout) and make fragment "B"?
How should I implement Database information and storage? For instance, I'll have fragments "A" category - 'GAMES'. When I click it, it should transfer to duplicate fragment "B", where it has "Basketball", "Football" ect... Also. If I click the fragments picture, it should show a small square with short information. Should I just make 3 seperate tables? How to link Fragments A - Fragment B - Detail information?
Also, if I've categories in Fragment "A" as following: cars/food/girls and I click food, then it goes to Fragment "B" which holds pizza/drinks ect - how to make sure fragment B gives right information according to fragment A (make sure it doesnt give from fragment 'a' (food) a result of fragment 'b' which holds information about cars for instance, which would be wrong)?

You can use manual constructors for passing data from fragment A to fragment B.
public class fragB extends Fragment{
int type;
public fragB(){
this.type = DEFAULT_TYPE;
}
public fragB(int type){
this.type = type;
}
}
From fragment A do this to define your fragB
Fragment f = new fragB(TYPE_CAR);
or
Fragment f = new fragB(TYPE_FOOD);
Note: Empty constructor is just for resolving exception.

Related

Passing data from one fragment to another when second fragment already has data

So, I have a fragment A, and a fragment B. Fragment A has some data, user presses a Button, goes to fragment B, performs some actions there, and when he is done I need the user to go back to fragment A with some data recovered from fragment B, while the data in fragment A is not recreated, but keeps the data it had in the first time. This shouldn't be so hard, but I am having some problems achieving it.
I can, of course, call fragment A from fragment B, but the data previously existing in fragment A is erased. Or I can go through the backstack to present fragment A again, but how could I pass data from fragment B while maintaining data present in fragment A?
both Fragments are attached to same Activity, so you can introduce some methods in it
private String data = null;
public void storeData(String data){
this.data = data;
}
public void restoreData(){
return data;
}
and call from Fragments side
// when B is detached/removed
((MainActivity) getActivity()).storeData(data);
// onCreateView of A?
String restoredData = ((MainActivity) getActivity()).restoreData();
if (restoredData!=null) ...

How to correctly get data from fragment to parent activity?

I have activity that contains A and B fragment. I used FrameLayout and BottomNavigation. I use following method to change fragment.
FragmentTransaction transaction =getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.frame, selectedFragment);
transaction.commit();
And i have one menu in activity which contains printer and mail. When i click printer or mail button from Activity. Activity have to get data from Fragment A or Fragment B. It's kind of sale process.
If Sale process is success i clear data of Fragment A and B. B contains lot of items. A contains one item.
My problem is I use Global variables to pass data.
Fragment B:
public static List<Product> ProductList = new ArrayList<>();
public static List<Product> itemSaleProductList = new ArrayList<>();
public static double itemSaleTotalPrice = 0;
Fragment A:
public static Product quickSale = null;
After user click item i save data. And when user click printer button it gets data from Global variables. Also If global variables have a value, Fragment B and A have to get that values.
It works. But Sometimes it can't get values. So How to get data correctly from activity?
Try this, make a setter from your activity then do this from your fragment
((MainActivity) getActivity()).setProductList(itemSaleProductList);
hope this helps

Sharing data between two fragments

I'm currently trying to make a create account fragment and a choose profile pic fragment.
Fragment A/create account:
This houses Edittextfields for name, password, E-mail address.
There is also an Image view which represents the profile pic.
This Image view has a button on the side, which I want to use to switch over to Fragment B.
Fragment B/Choose Profile Pic:
Fragment is just an Image view and a couple of Image Buttons.
My Problem
Let's say the user has typed in all information on Fragment A and now wants to choose a profile pic, how do I save all the data temporary which is entered in Fragment A.
The second question is then, when the user clicks the Accept button on Fragment B, how do I sent the chosen Pic to Fragment A. So that I can switch over to Fragment A and restore the previously saved information and receive the drawable Image which the user has selected, to display it in the Image view.
Have a look at the new Android Architecture Components. Especially ViewModel.
https://developer.android.com/topic/libraries/architecture/viewmodel.html#sharing
There is a section on sharing data between fragments.
It's very common that two or more fragments in an activity need to
communicate with each other. Imagine a common case of master-detail
fragments, where you have a fragment in which the user selects an item
from a list and another fragment that displays the contents of the
selected item. This case is never trivial as both fragments need to
define some interface description, and the owner activity must bind
the two together. In addition, both fragments must handle the scenario
where the other fragment is not yet created or visible.
This common pain point can be addressed by using ViewModel objects.
These fragments can share a ViewModel using their activity scope to
handle this communication, as illustrated by the following sample
code:
public class SharedViewModel extends ViewModel {
private final MutableLiveData<Item> selected = new MutableLiveData<Item>();
public void select(Item item) {
selected.setValue(item);
}
public LiveData<Item> getSelected() {
return selected;
}
}
public class MasterFragment extends Fragment {
private SharedViewModel model;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
itemSelector.setOnClickListener(item -> {
model.select(item);
});
}
}
public class DetailFragment extends Fragment {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SharedViewModel model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
model.getSelected().observe(this, { item ->
// Update the UI.
});
}
}
Making Activity as an intermediate can enable your fragment communication.
Refer Communicating with Other Fragments for "fragment-activity-fragment" communication. If you want to persist the data refer SharedPreference of android.
Why you want to create 2 Fragments ?
You can achieve same thing with different views. Let's say you can create one Linear/Relative(Layout Group) Layout with all the controls of 1st Fragment and create another layout(Layout Group) with 2nd Fragment controls. And then using animation show and hide layouts so you can have both the things in same fragment or activity and user won't even notice that thing.
This way you don't have to save data temporary and you will have to implement all the things in single file.

How to start a fragment from a RecyclerView Adapter which is inside another fragment?

I have a tab view with two fragments. Those two fragments contain a recycler view with cards.
Each card in both fragments had a button.
Clicking on fragment 1's button should open the fragment 2 as a separate page and vice-versa.
I am struggling to find a method to implement this without making every too complex and tightly coupled.
This is fragment one with its own Adapter.
And this is fragment two:
Clicking on that SELECT DONOR button in Donees page should open donor fragment in a new page where the user will be able to assign a donor for the selected donee.
So I have two needs here
1) To start a fragment from a fragment
2) To Keep track from which Donee the new donor page was opened so that I can assign a donor for that specific donee.
I hope this is understandable.
so far I have tried LocalBroadcast and FragmentManager but its hard to keep track of what I'm doing with the code.
Can you guys suggest a better technique to achieve this ?
the easiest solution would probably be, starting a new activity, passing something like an ID, name or something to the intent on an Button click.
Context.startActivity(new Intent(Context, YourAssigneeActivity.class)
.putExtra("ID",id));
So I assume that you do not switch to the other tab when you click a button on one tab. Therefore the fragment should fill the whole screen.
With this assumption in mind you most likely have to switch the Activity. This can be dones easily with an Intent:
Intent intent = new Intent(getActivity(), ActivityB.class)
intent.putExtra("KEY", <your required data to transfer>);
getActivity().startActivityForResult(intent);
Note that when you use putExtra() don't forget that you need to implement Parcelable in those objects (explained here)
To get to know which item was clicked you can use the following pattern (pseudocode - I personally think it's really clean):
FragmentA implements YourAdapter.callback {
onItemClicked(<YourObject> item) {
<starting new activity as described above>
}
}
class YourAdapter extends RecyclerView.Adapter {
Callback mCallback;
YourAdapter(Context context, otherStuff) {
mCallback = (Callback) context;
}
interface Callback {
onItemClicked(<YourObject> item)
}
YourViewHolder implements View.OnClickListener {
onClick(View v) {
mCallback.onItemClicked(<YourObject> item)
}
}
}
Once you are in your Activity, you can set the Fragment in onCreate() of your Activity. In the Activity retrieve the data with getIntent() in the onCreate before creating the Fragment. Then you can put your data in the Fragment with setArguments(<Bundle>). In the Fragment in the onCreateview() retrieve it with getArguments().
I know this is kind of conmplicated. A better solution would be to just switch to an Activity and forget about the Fragment. This would remove one layer of complexity.
If you directly go from Fragment to Fragment you can ignore the Activity part but the rest should stay the same.
Hope this was the answer you were looking for!
Edit: Note that mCallback = (Callback) context is null if the Activity is not implementing Callback

How can I avoid code duplication with Fragment callbacks to a details activity?

I'm using a master/detail pattern with one activity managing the 2-pane view and the selector list and the other activity managing the detail fragments. I'm using an interface to handle fragment callbacks to the Activities.
There seems to be a lot of code duplication though with the details activity copying many of the callback methods from the 2-pane activity. Where appropriate, I've used static methods where context isn't required, but where context is required I'm not sure how to remove the code duplication neatly.
Inheritance with an Abstract parent Activity is an option but seems like a lot of overhead.
Is there a better way of doing this?
I asked a similar question here: How many Activities vs Fragments?
I too was worried about the duplication of logic, and the answers I got caused quite a healthy debate.
In the end I chose to follow Stephen's answer, of putting as much of the logic into the Fragments themselves.
However other contributors seemed very keen on duplicating the logic as per the examples.
So lets say u have Activity AB that controls Frag A and Fragment B.
MY ANSWER:
If the variable is used by Frag A and Frag B, put it in Activity AB. Then pass it to Frag A or Frag B everything they need it. Or have Frag A or Frag B retrieve it from Activity AB.
If the variable is used by Frag A only or Frag B only, put it in Frag A or Frag B respectively.
For methods that are used by both Frag A and Frag B, put those methods in another class and create instances of that class inside Frag A and Frag B for each of the 2 fragments to use.
The following is an answer I gave to another person. However, it seems relevant to your question so I am re-posting it here.
Inside Fragment A u need an interface that Activity AB can implement.
In the sample android code, they have:
private Callbacks mCallbacks = sDummyCallbacks;
/*A callback interface that all activities containing this fragment must implement. This mechanism allows activities to be notified of item selections.
*/
public interface Callbacks {
/*Callback for when an item has been selected. */
public void onItemSelected(String id);
}
/*A dummy implementation of the {#link Callbacks} interface that does nothing. Used only when this fragment is not attached to an activity. */
private static Callbacks sDummyCallbacks = new Callbacks() {
#Override
public void onItemSelected(String id) {
}
};
The Callback interface is put inside one of your Fragments (let’s say Fragment A). I think the purpose of this Callbacks interface is like a nested class inside Frag A which any Activity can implement. So if Fragment A was a TV, the CallBacks is the TV Remote (interface) that allows Fragment A to be used by Activity AB. I may be wrong about the details because I'm a noob but I did get my program to work perfectly on all screen sizes and this is what I used.
So inside Fragment A, we have:
(I took this from Android’s Sample programs)
#Override
public void onListItemClick(ListView listView, View view, int position, long id) {
super.onListItemClick(listView, view, position, id);
// Notify the active callbacks interface (the activity, if the
// fragment is attached to one) that an item has been selected.
mCallbacks.onItemSelected(DummyContent.ITEMS.get(position).id);
//mCallbacks.onItemSelected( PUT YOUR SHIT HERE. int, String, etc.);
//mCallbacks.onItemSelected (Object);
}
And inside Activity AB we override the onItemSelected method:
public class AB extends FragmentActivity implements ItemListFragment.Callbacks {
//...
#Override
//public void onItemSelected (CATCH YOUR SHIT HERE) {
//public void onItemSelected (Object obj) {
public void onItemSelected(String id) {
//Pass Data to Fragment B. For example:
Bundle arguments = new Bundle();
arguments.putString(“FragmentB_package”, id);
FragmentB fragment = new FragmentB();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction().replace(R.id.item_detail_container, fragment).commit();
}
So inside Activity AB, you basically throwing everything into a Bundle and passing it to B. If u are not sure how to use a Bundle, look the class up.
I am basically going by the sample code that Android provided. The one with the DummyContent stuff. When u make a new Android Application Package, it's the one titled MasterDetailFlow.

Categories

Resources