is there a way to send some data from an activity to a running fragment?
In my app I'm adding a second fragment over another fragment. I intentionally use the add method instead of the replace method. So now I want to hide my second fragment with
fragmentManager.popBackStack();
and my first fragment reappears. After hiding the second fragment I want to send some data from my activity to the still running frist fragment.
Any idea how to do this? It doesn't work with bundles (put extra), because I don't rebuild the fragment, I just hide the second one!
one simple solution is:
MyFragment oldFragment = (MyFragment) fragmentManager.findFragmentById(R.id.fragment_place);
fragmentManager.popBackStackImmediate();
MyFragment newFragment = (MyFragment)fragmentManager.findFragmentById(R.id.fragment_place);
newFragment.postData(...);
You can use an EventBus library like this one, it's easy to use and very convenient.
You can use tags on the Fragments when you create them to call them when needed.
getFragmentManager().beginTransaction()
.add(R.id.content, new SomeFragment(), SomeFragment.class.getSimpleName())
.commit();
So above I use the simple name of the class to tag the fragment when I create and add it to the activity.
SomeFragment fragment = (SomeFragment) getFragmentManager().findFragmentByTag(SomeFragment.class.getSimpleName());
And I can call it back when I need it and know it is being displayed like above, now I can call send it data like normal by calling a public method in the custom fragment and passing it the data as a param.
Related
I know this question has been asked before in other threads like this one :
Trying to replace one fragment with another
But, in these cases the layout file would have a node with an id. In my case, I created a custom SettingsFragment and this SettingsFragment consists of many items. When I click on one item, it will start another fragment CreatePasswordFragment.
Now, my SettingsFragment does not have an id (or does it? I am a newbie to android....), so I don't know how to use .replace(R.id.fragment_container,CreatePasswordFragment.newInstance())
So far, I have used the following method, and while it works I am wondering if there is a better way to do it?
getActivity()
.getSupportFragmentManager()
.beginTransaction()
.remove(SettingsFragment.this)
.replace((android.R.id.content, CreatePasswordFragment.newInstance(userProfile.email))
.addToBackStack(null)
.commit();
The id in the replace() method is the container id, not your fragment id. So it would be the id of whatever layout in your activity is displaying the fragment. So you are doing it right. One thing to note, however, is that you do not need to call remove(). You can just call replace() and the FragmentManager will automatically call remove() for you.
I simply want to replace a fragment from the current fragment and add a new one.
I have studied that Replace is Equal to removeCurrent + Add anotherFragment
But in my situation i am facing a Problem. For the first two times it is running properly but after third attempt instead of replacing . it ads the fragment on me.
My approach fails now. Now i am asking that how can i send an id to other fragment like we do in Activities. I have a listView with a ReadMore button. I simply want to show the details in another fragment and want to send the index of a List.
I listen about some Interface but don't know how to implement . or there an easy way for communication. I tried doing it by passing it in Constructor . but it will give me an error . because
how to get currentFragment and hide it?
how to add onBackPressed to fragment.
how to send data between fragments The easy way.
i know how to hide or show a fragment
getFragmentManager().beginTransaction().hide(frag[j]).commit();
getFragmentManager().beginTransaction().show(frag[0]).commit();
also know how to add or replace a fragment
getFragmentManager().beginTransaction().add(R.id.container, frag[i])
//.addToBackStack(null)
.commit();
getFragmentManager().beginTransaction().replace(R.id.container, frag[i])
//.addToBackStack(null)
.commit();
Tell me a better approach to send data and why my layout add instead of replacing.
I recommend using EventBus for Activity/Fragment/Service or any other communication.
There is a good one from Square: http://square.github.io/otto/
Or this one (also very good): https://github.com/greenrobot/EventBus
It makes it simplier and your code gets cleaner.
It is pretty easy to send data to fragment with constructor.
In your fragment class, add constructor like this:
public class MyFragment extends Fragment{
String id;
public MyFragment(String id)
this.id = id;
}
Then, when calling a fragment,you can easily send data like this :
getSupportFragmentManager().beginTransaction().replace(android.r.id.container,new MyFragment("123")).commit();
You can't override onBackPressed within fragment, you can only do that in activity
You can set try set the variables in the fragment as public static then you can declare them before you instantiate your fragment to be shown.
in your onDestroy method of the fragment you can set the variables = null, so they dont take space in memory.
could be smth like this
MyFragment.theString = "A String";
getSupportFragmentManager().beginTransaction().replace(android.r.id.container,new MyFragment()).commit();
And in your fragment
public static String theString;
...
public void onDestroy(){
super.onDestroy();
theString = null;
}
I have an Activity called Mytaskonclick extends Activity and a Fragment called SentTaskFragment extends Fragment. I want to go from Mytaskonclick to SentTaskFragment on click of a button. I tried using the code
Intent ii=new Intent(Mytaskonclick.this,SentTaskFragment.class);
startActivity(ii);
But this code doesn't work. Can anyone suggest me how to do it?
Fragments does not work like this.You need to put a place holder in your activity, say FrameLayout for example and, inside on click, you get the fragment and attach it inside this placeholder. I suggest you read the Fragment Tutorial Here. It contains all what you need to know and extremely useful for you.
When you want to switch to a Fragment them you have to do that through FragmentManager. Pass that thae Fragment object into beginTransaction() method of FragmentManager along with the container layout which will hold the Fragment as below...
SentTaskFragment fragment = new SentTaskFragment();
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().add(R.id.frame_container, fragment).commit();
You can see some tutorial from below link...
Android Developer-Fragment
Multi-pane development in Android with Fragments - Tutorial
Android Fragments
Android Fragments Example
Based on the example from http://developer.android.com/training/basics/fragments/communicating.html I tried to reproduce the communication between two fragments which are sub fragments of a larger fragment.
In the example, AB activity contains A fragment and B fragment. But I am trying to achieve the same but in my case AB Fragment contains A fragment and B fragment.
The problem is the overridden method in the AB Fragment never gets called. Does this not work because the containing component is a Fragment and not a Activity like in the example? Am I missing out something here?
If you are referring to onClick() or some other onSomething() handler, then these always get called in the Activity class, not the fragment. So in the example you linked, the onArticleSelected() must remain in the Activity, even if you have nested fragments.
To pass info on to the fragment, you have a few options. One, you can keep a reference to the fragment within the activity. This might be lost if your activity recreates (settings event for example).
The second and better way would be to tag your fragments, and then use findFragmentByTag.
When you add your fragment (notice the parameter "my_fragment" which is the tag I gave to the fragment):
getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, myFragment, "my_fragment").commit();
Or when you replace one fragment with another:
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, myFragment, "my_fragment").comit();
Then, when you want to do something in the fragment from within your onArticleSelected of the activity:
Fragment fragment = getSupportFragmentManger().findFragmentByTag("my_fragment");
if (fragment != null) {
fragment.articleSelected(articleId);
}
You can always use an Interface to communicate between fragments. It is the safest way to do so.
I have an activity where I dynamically replace fragments:
private void goToFragment(Fragment newFragment, String tag) {
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.fragment_container, newFragment, tag);
ft.addToBackStack(null);
ft.commit();
}
Now, I want to access the views inside the fragment so I can put data (that I have stored in my activity) into them, immediately after calling goToFragment.
The problem is, the fragment's onCreateView isn't called before the fragment is rendered completely, at least to my understanding.
I know overriding the onAttach(Activity activity) in the fragment is one way to go about it, but then I have to cast it specifically to my activity - and I just want to avoid that because I consider it bad practice for the fragment to be dependent on a specific activity.
As far as I can see, Fragment doesn't have any listeners (as a subject) implemented.
So I figure I have to make my own listener (Using the Observer Pattern to make the fragment a subject and the activity an observer), and then calling it whenever the onCreateView or onAttach is done, and then finally calling back to the fragment with the data that needs to be set. However, I need to do this for several fragments so I would have to make a listener for each fragment, which I again think is bad.
Is there any better/easier way to do this?
FragmentTransaction isn't applied instantly after calling commit(). You may force update manually:
...
mFragmentManager.executePendingTransactions();
AFAIK event callbacks' purpose is custom communication with Fragment beyond it's usual lifecycle.
The correct way to do it would be to define an interface for Activity classes wishing to display your Fragment should implement. That way, on onAttach you don't cast to a specific Activity but to your interface.
See for instance: http://developer.android.com/guide/topics/fundamentals/fragments.html#EventCallbacks
You should use onActivityCreated to set the values.
Set references in onCreateView and then set values to them in onActivityCreated.