Reputation: 6971
I am beginner, trying to learn while doing, and the Google results are too complicated for me at this point.
I have an Activity and successfully managed to make a fragment open and close via button press.
public void pressedButton(View v) {
FragmentActivity fragmentActivity = new FragmentActivity();
FragmentManager fragmentManager = getSupportFragmentManager();
android.support.v4.app.FragmentTransaction ft = fragmentManager.beginTransaction();
ft.add(R.id.frame_which_takes_the_fragment, FragmentActivity, "FRAGMENT_TAG");
ft.commit();
As the fragment class stipulates, i implemented its "OnFragmentInteractionListener" interface in the Activity and overrode the onFragmentInteraction method.
@Override
public void onFragmentInteraction(Uri uri) {
}
And now I don't know how to progress. How do i send a variable from the activity to the fragment (for example to update a number in the user interface) and how do I send information back?
Please, keep in mind that I am a bloody beginner and try to keep it as basic and simple as possible.
Thanks in advance.
Upvotes: 2
Views: 7780
Reputation: 614
ViewModels approach:
Fragments can share a ViewModel using their activity scope to handle this communication, as illustrated by the following sample code: This is clearly explained in Google's official doc. https://developer.android.com/topic/libraries/architecture/viewmodel#sharing
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.
});
}
}
enter code here
Another very good blog to study this: 8 ways to communicate between Fragment and Activity in Android apps. https://hackernoon.com/8-ways-to-communicate-between-fragment-and-activity-in-android-apps-235b60005d04
Upvotes: 1
Reputation: 4808
There are many ways of the communication between two fragments of the same activity.
mainViewModel = ViewModelProviders.of(this).get(MainViewModel.class);
. So if we use this keyword, the scope for the ViewModel remains until the fragment is destroyed only, once the fragment is destroyed, the ViewModel is cleared as well. So if we use getActivity() as a scope for the ViewModel then ViewModel will remain until the Activity is destroyed. Now suppose, you have a ViewModelA for A fragment, and you want to pass some value to the B fragment from A, now what you can do is, you can bind B fragment to ViewModelB as well as ViewModelA and hence you can observe for any change in certain value of ViewModelA in fragment B. Upvotes: 0
Reputation: 18881
How do i send a variable from the activity to the fragment (for example to update a number in the user interface)?
I tried to do this by getting the ListFragment from my adapter and calling the fragment method, but I got this error:
IllegalStateException: Can't access ViewModels from detached fragment
My solution was to use LocalBroadcastManager instead:
Activity code
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this);
Intent broadcastIntent = new Intent("MAP_SETTINGS_CHANGED");
broadcastIntent.putExtra("NUMBER_TO_SHOW_IN_FRAGMENT", 11);
localBroadcastManager.sendBroadcast(broadcastIntent);
ListFragment/Fragment code
private Context mContext;
private BroadcastReceiver mBroadcastReceiver;
@Override
public void onAttach(Context context) {
super.onAttach(context);
mContext = context;
mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, Intent intent) {
String action = intent.getAction();
if ("MAP_SETTINGS_CHANGED".equals(action)) {
int numberToShow = intent.getIntExtra("NUMBER_TO_SHOW_IN_FRAGMENT", -1);
showNumber(numberToShow);
}
}
};
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(mContext);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("MAP_SETTINGS_CHANGED");
localBroadcastManager.registerReceiver(mBroadcastReceiver, intentFilter);
}
@Override
public void onDetach() {
super.onDetach();
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(mContext);
localBroadcastManager.unregisterReceiver(mBroadcastReceiver);
mContext = null;
}
Upvotes: 0
Reputation: 3657
As ViewModel
is released you can use shared ViewModel
to communicate between fragments and activity. You just need to create ViewModel
in activity
scope and the ViewModel
will be shared with activity
and all child fragment
.
SharedViewModel sharedViewModel = ViewModelProviders.of(getActivity()).get(SharedViewModel::class.java);
Then just observe the data
sharedViewModel.inputNumber.observe(this, observer); // observer is your observer object
Upvotes: 3
Reputation: 23655
So, you already created an interface in the fragment and implemented it in the activity? Then you just have to create the interface following your needs. The onFragmentInteraction(Uri uri)
method is just an example, which you can remove, if you don't want to pass an Uri from the fragment to activity.
So, to pass a number, your interface could look like this:
interface Listener {
void onNumberChanged(int number);
}
The relevant fragment code:
listener.onNumberChanged(someNumber);
The relevant activity code:
@Override
public void onNumberChanged(int number) {
someTextView.setText(Integer.toString(number));
}
Upvotes: 3