I have this issue of sending some data back and forth between a fragment and its container activity, I succeeded in doing it. What puzzles me is sending my data from the fragment to the activity, at first I implemented OnResume(), OnStop() and sent the data through an intent and that created an infinite loop so I removed them. Then I did setRetainInstance(true) and it worked and gave me the wanted behavior.
My Question is How my data are really being sent and where in the fragment lifecycle ?
The Right approach is to use Interfaces. Don't use onStop or setRetainInstance()
See this. It will solve you problem.
Pass data from fragment to actvity
You can also achieve this by using Interface, using an EventBus like LocalBroadcastManager, or starting a new Activity with an Intent and some form of flag passed into its extras Bundle or something else.
Here is an example about using Interface:
1. Add function sendDataToActivity() into the interface (EventListener).
//EventListener.java
public interface EventListener {
public void sendDataToActivity(String data);
}
2. Implement this functions in your MainActivity.
// MainActivity.java
public class MainActivity extends AppCompatActivity implements EventListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public void sendDataToActivity(String data) {
Log.i("MainActivity", "sendDataToActivity: " + data);
}
}
3. Create the listener in MyFragment and attach it to the Activity.
4. Finally, call function using listener.sendDataToActivity("Hello World!").
// MyFragment.java
public class MyFragment extends Fragment {
private EventListener listener;
#Override
public void onAttach(Activity activity)
{
super.onAttach(activity);
if(activity instanceof EventListener) {
listener = (EventListener)activity;
} else {
// Throw an error!
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_my, container, false);
// Send data
listener.sendDataToActivity("Hello World!");
return view;
}
#Override
public void onDetach() {
super.onDetach();
listener = null;
}
}
Hope this will help~
This question already has answers here:
Communicating between a fragment and an activity - best practices
(11 answers)
Closed 4 years ago.
I need to pass data from activity to fragment. I know I can use bundle , but once I passed data,I can't send data without calling and creating fragment again.
In my activity, some thing may be changed and I need to notify my fragment for these changes without recreating fragment.
Create one interface in your Activity and pass your data via the interface to the fragment. Implement that interface in your fragment to get data.
For example
MainActivity.class
public class MainActivity extends AppCompatActivity {
DataFromActivityToFragment dataFromActivityToFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentA fr = new FragmentA();
FragmentManager fm = getFragmentManager();
dataFromActivityToFragment = (DataFromActivityToFragment) fr;
FragmentTransaction fragmentTransaction = fm.beginTransaction();
fragmentTransaction.replace(R.id.fragment_place, fr);
fragmentTransaction.commit();
final Handler handler = new Handler();
final Runnable r = new Runnable() {
public void run() {
dataFromActivityToFragment.sendData("Hi");
}
};
handler.postDelayed(r, 5000);
}
public interface DataFromActivityToFragment {
void sendData(String data);
}
}
FragmentA.class
public class FragmentA extends Fragment implements MainActivity.DataFromActivityToFragment {
TextView text;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.content_main, null);
text = (TextView) rootView.findViewById(R.id.fragment_text);
return rootView;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
#Override
public void sendData(String data) {
if(data != null)
text.setText(data);
}
}
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:id="#+id/fragment_place"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
</LinearLayout>
</LinearLayout>
content_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/fragment_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
In above example I have taken Runnable just to send data with delay of 5 seconds after creation of fragment.
Fragment object is just like other objects.Like String , you can invoke methods of string object, str.charAt(0) ,str.toUpperCase() etc. Just create a function in fragment, put your code there and call the function along with values
Inside Activity {
fragDemoObject.doWhatYouWant("this is passed as string object to fragment");
}
Inside FragmentDemo{
void doWhatYouWant(String input){
System.out.println(input);
// do what else you want to do with code
}
}
Actually your question is not related to:
I need to pass data from activity to fragmenet .I know I can use
bundle , but one i've passed data , I cant send anymore data without
calling and creating fragment once more .
The real one is this:
in my activity , some thing may be changed and I need to notify my
fragment from these changes without recreating fragment.
how can I do so ?
In this case I would store the fragment in the activity as reference and I would call a function, an interface implementation inside the fragment.
Something like this:
In Activity:
SomeEventListener myFragment ;
yourFragmentCreationMethod(){
if(myFragment == null){
myFragment = new MyFragment(maybeParamsHere);
}
}
yourNotificationMethod(){
myFragment .onEventHappent(param);
}
// declare an interface: - separate file
public interface SomeEventListener
{
void onEventHappent(param);
}
// implement the interface in Fragment - separate file
public class MyFragment extends Fragment implements SomeEventListener{
// add a constructor what you like
public void onEventHappent(param){
/// ... your update
}
}
The interface it will help you at testing only.
The host activity can deliver messages to a fragment by capturing the
Fragment instance with findFragmentById(), then directly call the
fragment's public methods.
In your fragment - MyFragment, create a public method
public void myFragmentDataFromActivity(int passedDataFromActivity) {
// do your stuff
}
In your activity to pass an integer value say, 100 :
get MyFragment instance using getSupportFragmentManager or getFragmentManager by providing id/tag/position. Then call the public method in MyFragment instance.
MyFragment myFragment = (MyFragment) getSupportFragmentManager.getFragmentById(id);
myFragment.myFragmentDataFromActivity(100);
You can also use getFragmentByTag(tag), getFragments().get(position) instead of getFragmentById(id) to get fragment instance.
read more about this
For notify fragment with some data after it's created, can be done using some Communicator, or you can always pass the data with bundle in creation time...
For example:
public interface FragmentCommunicator {
void updateDataToFragment(List<Parcelable> data);
}
then in your fragment implement this interface and calling it from the activity for example as:`
Fragment fragment = mSectionsPagerAdapter.getRegisteredFragment(i);
if (fragment instanceof FragmentCommunicator) {
FragmentCommunicator fragmentCommunicator = (FragmentCommunicator) fragment;
fragmentCommunicator.updateDataToFragment(data);
}`
This should works for your case...
try this one in Activity
fragment=new PdfFragment();
if (fragment != null) {
FragmentManager fragmentManager = getFragmentManager();
Bundle bundle = new Bundle();
bundle.putString("pdf", Pdf);
bundle.putString("flag", "0");
fragment.setArguments(bundle);
fragmentManager.beginTransaction().replace(R.id.container, fragment).addToBackStack(null).commit();
}
and in fragment
Pdf = getArguments().getString("pdf");
You should declare your method as public in the fragment to update new data. Then you will call that method via fragment instance. For example, write this in your activity when getting new data:
fragmentInstance.publicMethod(newData);
Happy coding!
I have also come across the same issue, I have used singleton class to
transfer data from activity to fragment (without making fragment
transaction or using inteface)
class DataPersistance {
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPlace() {
return place;
}
public void setPlace(String place) {
this.place = place;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
private String name;
private String place;
private String type;
private static final DataPersistance ourInstance = new DataPersistance();
static DataPersistance getInstance() {
return ourInstance;
}
private DataPersistance() {
}
}
to set and get data
DataPersistance.getInstance().setName(mEditText.getText().toString());
String name = DataPersistance.getInstance().getName();
Have two fragments A and B, Fragment A has Textview and Fragment B has edittext and button.
Click on submit in FragmentB need to update textview in FragmentA with Edittext text.
How to do communication between fragment?
n this example, FragmentA call notify.
INotifier
public interface INotifier {
public void notify(Object data);
}
Utils
public class Utils {
public static INotifier notifier;
}
FragmentA
public FragmentA extends Fragment {
public void onCreateView(...) {
}
public void inSomeMethod() {
if (Utils.notifier != null) {
Utils.notifier.notify(data);
}
}
}
FragmentB
public FragmentB extends Fragment implements INotifier {
public void onCreateView(...) {
Utils.notifier = this;
}
#Override
public void notify(Object data) {
// handle data
}
}
You need to interact the activity first which will interact the second fragment. and also read this article on how to do it.
https://developer.android.com/guide/components/fragments.html#CommunicatingWithActivity
The communication between Fragments is done usinng Listeners. When you want to update fragment, use the listener to tell the MainActivity to update the second fragment as recommended by Google http://developer.android.com/training/basics/fragments/communicating.html. Create the interface in Fragment and Implement this in Activity
Listener in Fragment
public interface FragmentUpdateInterface {
void updateFragment(String newText);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
mCallback = (FragmentUpdateInterface ) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement FragmentUpdateListener");
}
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
// Send the event to the host activity
mCallback.updateFragment("New Text");
}
MainActivity
Implement fragment in MainActivity as
public static class MainActivity extends Activity
implements MyFragment.FragmentUpdateListener{
public void updateFragment(String newText) {
OtherFragment otherFrag = (OtherFragment)
getSupportFragmentManager().findFragmentById(R.id.other_fragment);
if (otherFrag != null) {
otherFrag.updateFragment(newText);
} else {
// Otherwise, we're in the one-pane layout and must swap frags...
// Create fragment and give it an argument for the selected article
OtherFragment otherFrag = new OtherFragment();
Bundle args = new Bundle();
args.putInt(ArticleFragment.ARG_POSITION, position);
otherFrag.setArguments(args);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, otherFrag);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
}
}
Hope this helps.
UPDATE:
You can also use LocalBroadcastManager.getInstance().sendBroadcast() to notify to the other fragment as well.
I've Viewpager wit 2 fragments: CurrentWeatherFragment and ForecastFragment. I need to pass string from one to another, Iam using interface like below, but I keep getting NullPointerException, the message is not passing propertly...
public class CurrentWeatherFragment extends Fragment {
SendMessage SM
public void onCreateView(...) {
String Message = "Hello"
SM.sendData(Message);
}
interface SendMessage
{
public void sendData(String message);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
SM = (SendMessage) activity;
} catch(ClassCastException e) {
throw new ClassCastException("Musisz zaimplementowac metode sendData");
}
}
}
MainActivity.java
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.os.Bundle;
public class MainActivity extends FragmentActivity implements CurrentWeatherFragment.SendMessage {
ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//setting fragment view pager
viewPager = (ViewPager)findViewById(R.id.pager);
PagerAdapter pagerAdapter = new PagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(pagerAdapter);
}
public void sendData (String message){
ForecastFragment FF = new ForecastFragment();
FF.getData(message);
}
}
ForecastFragment.java
public class ForecastFragment extends Fragment {
public View onCreateView(){
TextView txt = (TextView)v.findViewById(R.id.txt_forecast);
}
public void getData(String message){
txt.setText(message);
}
}
I've used this method succesfully in other app where I've had 2 fragments in one activity and i could call them by ID
public void sendData(String message) {
SecondFragment f2 = (SecondFragment)getFragmentManager().findFragmentById(R.id.F2);
f2.getData(message);
}
But here Fragments dont have IDs and I think that message is not passed because i dont use FragmentManager(), but how to find fragment in viewpager without ID, any suggestion/ideas?
Although a little hacky what you can do is get the fragment by its tag by using the following code:
String tag = "android:switcher:" + R.id.pager + ":" + index;
Fragment f = getSupportFragmentManager().findFragmentByTag(tag);
Where R.id.pager is the id of the viewpager in your layout and index is the position (as an integer) in the Viewpager Adapter.
I can't say this will work forever but it works for me at the moment.
The Alternative i would suggest is using a LocalBroadcastManager and a BroadcastReciver to send data internally between your fragments as although its a little more work it helps get rid of the spaghetti code situation you may end up finding yourself in trying to reference the fragments directly.
To pass data between fragments you need to pass the data in the object constructor.
Be aware to don't override the default constructor, instead create a static method getInstance(String data).
public static YourClass getInstance(String data)
{
YourClass object = new YourClass();
Bundle bundle = new Bundle();
bundle.putString(key, data);
object.setArguments(bundle);
return object;
}
Then you can get the data in the fragment's onCreate method with getArguments()
For some other users like me who looking for fragment to viewpager data sending
Here is working solution :
Sending data from fragment TO tab layout's view pager's fragments:
In Main fragment :
For tab layout i am using two fragments
1) BillDetailFragment and
2) ClientDepMonFragment
private TabLayout tabLayout;
private ViewPager viewPager;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
view= inflater.inflate(R.layout.fragment_detail, container, false);
// adding fragment and passing data to it
BillDetailFragment billDetailFragment=new BillDetailFragment();
Bundle bundle=new Bundle();
bundle.putString("mobile",mobile);
bundle.putInt("c_id",client_id);
bundle.putInt("server_id",server_id);
billDetailFragment.setArguments(bundle);
ClientDepMonFragment clientDepMonFragment=new ClientDepMonFragment();
Bundle bundle1=new Bundle();
bundle1.putString("mobile",mobile);
bundle1.putInt("c_id",client_id);
bundle1.putInt("server_id",server_id);
clientDepMonFragment.setArguments(bundle1);
tabLayout=(TabLayout)view.findViewById(R.id.detail_txn_tab_layout);
viewPager=(ViewPager)view.findViewById(R.id.detail_txn_viewpager);
dtViewPagerAdapter=new DtViewPagerAdapter(getChildFragmentManager(),DetailFragment.this);
dtViewPagerAdapter.addFragments(billDetailFragment,"Lending Money");
dtViewPagerAdapter.addFragments(clientDepMonFragment,"Deposited Money");
viewPager.setAdapter(dtViewPagerAdapter);
tabLayout.setupWithViewPager(viewPager);
}
and here is how to access that data from fragment
BillDetailFragment: override onCreate method
private int client_id,server_id;
private String client_mobile;
#Override
public void onCreate(#Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
client_mobile=getArguments().getString("mobile");
client_id=getArguments().getInt("c_id");
server_id=getArguments().getInt("server_id");
}
Im trying to pass data between two fragmens in my program. Its just a simple string that is stored in the List. The List is made public in fragments A, and when the user clicks on a list item, I need it to show up in fragment B. The content provider only seems to support ID's, so that will not work. Any suggestions?
Why don't you use a Bundle. From your first fragment, here's how to set it up:
Fragment fragment = new Fragment();
Bundle bundle = new Bundle();
bundle.putInt(key, value);
fragment.setArguments(bundle);
Then in your second Fragment, retrieve the data using:
Bundle bundle = this.getArguments();
int myInt = bundle.getInt(key, defaultValue);
Bundle has put methods for lots of data types. Please see http://developer.android.com/reference/android/os/Bundle.html
If you use Roboguice you can use the EventManager in Roboguice to pass data around without using the Activity as an interface. This is quite clean IMO.
If you're not using Roboguice you can use Otto too as a event bus: http://square.github.com/otto/
Update 20150909: You can also use Green Robot Event Bus or even RxJava now too. Depends on your use case.
From the Fragment documentation:
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.
So I suggest you have look on the basic fragment training docs in the documentation. They're pretty comprehensive with an example and a walk-through guide.
So lets say you have Activity AB that controls Frag A and Fragment B.
Inside Fragment A you 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 detail 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 you make a new Android Application Package, it's the one titled MasterDetailFlow.
1- The first way is define an interface
public interface OnMessage{
void sendMessage(int fragmentId, String message);
}
public interface OnReceive{
void onReceive(String message);
}
2- In you activity implement OnMessage interface
public class MyActivity implements OnMessage {
...
#Override
public void sendMessage(int fragmentId, String message){
Fragment fragment = getSupportFragmentManager().findFragmentById(fragmentId);
((OnReceive) fragment).sendMessage();
}
}
3- In your fragment implement OnReceive interface
public class MyFragment implements OnReceive{
...
#Override
public void onReceive(String message){
myTextView.setText("Received message:" + message);
}
}
This is the boilerplate version of handling message passing between fragments.
Another way of handing data passage between fragments are by using an event bus.
1- Register/unregister to an event bus
#Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
#Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
2- Define an event class
public class Message{
public final String message;
public Message(String message){
this.message = message;
}
}
3- Post this event in anywhere in your application
EventBus.getDefault().post(new Message("hello world"));
4- Subscribe to that event to receive it in your Fragment
#Subscribe(threadMode = ThreadMode.MAIN)
public void onMessage(Message event){
mytextview.setText(event.message);
}
For more details, use cases, and an example project about the event bus pattern.
IN my case i had to send the data backwards from FragmentB->FragmentA hence Intents was not an option as the fragment would already be initialised All though all of the above answers sounds good it takes a lot of boiler plate code to implement, so i went with a much simpler approach of using LocalBroadcastManager, it exactly does the above said but without alll the nasty boilerplate code. An example is shared below.
In Sending Fragment(Fragment B)
public class FragmentB {
private void sendMessage() {
Intent intent = new Intent("custom-event-name");
intent.putExtra("message", "your message");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
}
And in the Message to be Received Fragment(FRAGMENT A)
public class FragmentA {
#Override
public void onCreate(Bundle savedInstanceState) {
...
// Register receiver
LocalBroadcastManager.getInstance(this).registerReceiver(receiver,
new IntentFilter("custom-event-name"));
}
// This will be called whenever an Intent with an action named "custom-event-name" is broadcasted.
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String message = intent.getStringExtra("message");
}
};
}
Hope it helps someone
That depends on how the fragment is structured. If you can have some of the methods on the Fragment Class B static and also the target TextView object static, you can call the method directly on Fragment Class A. This is better than a listener as the method is performed instantaneously, and we don't need to have an additional task that performs listening throughout the activity. See example below:
Fragment_class_B.setmyText(String yourstring);
On Fragment B you can have the method defined as:
public static void setmyText(final String string) {
myTextView.setText(string);
}
Just don't forget to have myTextView set as static on Fragment B, and properly import the Fragment B class on Fragment A.
Just did the procedure on my project recently and it worked. Hope that helped.
you can read this doc .this concept is well explained here http://developer.android.com/training/basics/fragments/communicating.html
I'm working on a similar project and I guess my code may help in the above situation
Here is the overview of what i'm doing
My project Has two fragments Called "FragmentA" and "FragmentB"
-FragmentA Contains one list View,when you click an item in FragmentA It's INDEX is passed to FragmentB using Communicator interface
The design pattern is totally based on the concept of java interfaces that says
"interface reference variables can refer to a subclass object"
Let MainActivity implement the interface provided by fragmentA(otherwise we can't make interface reference variable to point to MainActivity)
In the below code communicator object is made to refer to MainActivity's object by using "setCommunicator(Communicatot c)" method present in fragmentA.
I'm triggering respond() method of interface from FrgamentA using the MainActivity's reference.
Interface communcator is defined inside fragmentA, this is to provide least access previlage to communicator interface.
below is my complete working code
FragmentA.java
public class FragmentA extends Fragment implements OnItemClickListener {
ListView list;
Communicator communicater;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
return inflater.inflate(R.layout.fragmenta, container,false);
}
public void setCommunicator(Communicator c){
communicater=c;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
communicater=(Communicator) getActivity();
list = (ListView) getActivity().findViewById(R.id.lvModularListView);
ArrayAdapter<?> adapter = ArrayAdapter.createFromResource(getActivity(),
R.array.items, android.R.layout.simple_list_item_1);
list.setAdapter(adapter);
list.setOnItemClickListener(this);
}
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int index, long arg3) {
communicater.respond(index);
}
public interface Communicator{
public void respond(int index);
}
}
fragmentB.java
public class FragmentA extends Fragment implements OnItemClickListener {
ListView list;
Communicator communicater;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
return inflater.inflate(R.layout.fragmenta, container,false);
}
public void setCommunicator(Communicator c){
communicater=c;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
communicater=(Communicator) getActivity();
list = (ListView) getActivity().findViewById(R.id.lvModularListView);
ArrayAdapter<?> adapter = ArrayAdapter.createFromResource(getActivity(),
R.array.items, android.R.layout.simple_list_item_1);
list.setAdapter(adapter);
list.setOnItemClickListener(this);
}
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int index, long arg3) {
communicater.respond(index);
}
public interface Communicator{
public void respond(int index);
}
}
MainActivity.java
public class MainActivity extends Activity implements FragmentA.Communicator {
FragmentManager manager=getFragmentManager();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentA fragA=(FragmentA) manager.findFragmentById(R.id.fragmenta);
fragA.setCommunicator(this);
}
#Override
public void respond(int i) {
// TODO Auto-generated method stub
FragmentB FragB=(FragmentB) manager.findFragmentById(R.id.fragmentb);
FragB.changetext(i);
}
}
Basically Implement the interface to communicate between Activity and fragment.
1) Main activty
public class MainActivity extends Activity implements SendFragment.StartCommunication
{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public void setComm(String msg) {
// TODO Auto-generated method stub
DisplayFragment mDisplayFragment = (DisplayFragment)getFragmentManager().findFragmentById(R.id.fragment2);
if(mDisplayFragment != null && mDisplayFragment.isInLayout())
{
mDisplayFragment.setText(msg);
}
else
{
Toast.makeText(this, "Error Sending Message", Toast.LENGTH_SHORT).show();
}
}
}
2) sender fragment (fragment-to-Activity)
public class SendFragment extends Fragment
{
StartCommunication mStartCommunicationListner;
String msg = "hi";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View mView = (View) inflater.inflate(R.layout.send_fragment, container);
final EditText mEditText = (EditText)mView.findViewById(R.id.editText1);
Button mButton = (Button) mView.findViewById(R.id.button1);
mButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
msg = mEditText.getText().toString();
sendMessage();
}
});
return mView;
}
interface StartCommunication
{
public void setComm(String msg);
}
#Override
public void onAttach(Activity activity) {
// TODO Auto-generated method stub
super.onAttach(activity);
if(activity instanceof StartCommunication)
{
mStartCommunicationListner = (StartCommunication)activity;
}
else
throw new ClassCastException();
}
public void sendMessage()
{
mStartCommunicationListner.setComm(msg);
}
}
3) receiver fragment (Activity-to-fragment)
public class DisplayFragment extends Fragment
{
View mView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
mView = (View) inflater.inflate(R.layout.display_frgmt_layout, container);
return mView;
}
void setText(String msg)
{
TextView mTextView = (TextView) mView.findViewById(R.id.textView1);
mTextView.setText(msg);
}
}
I used this link for the same solution, I hope somebody will find it usefull.
Very simple and basic example.
http://infobloggall.com/2014/06/22/communication-between-activity-and-fragments/
getParentFragmentManager().setFragmentResultListener is the 2020 way of doing this. Your only limitation is to use a bundle to pass the data. Check out the docs for more info and examples.
Some other ways
Call to getActivity() and cast it to the shared activity between your fragments, then use it as a bridge to pass the data. This solution is highly not recommended because of the cupelling it requires between the activity and the fragments, but it used to be the popular way of doing this back in the KitKat days...
Use callbacks. Any events mechanism will do. This would be a Java vanilla solution. The benefit over FragmentManager is that it's not limited to Bundles. The downside, however, is that you may run into edge cases bugs where you mess up the activity life cycle and get exceptions like IllegalStateException when the fragment manager is in the middle of saving state or the activity were destroyed. Also, it does not support cross-processing communication.
Fragment class A
public class CountryListFragment extends ListFragment{
/** List of countries to be displayed in the ListFragment */
ListFragmentItemClickListener ifaceItemClickListener;
/** An interface for defining the callback method */
public interface ListFragmentItemClickListener {
/** This method will be invoked when an item in the ListFragment is clicked */
void onListFragmentItemClick(int position);
}
/** A callback function, executed when this fragment is attached to an activity */
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try{
/** This statement ensures that the hosting activity implements ListFragmentItemClickListener */
ifaceItemClickListener = (ListFragmentItemClickListener) activity;
}catch(Exception e){
Toast.makeText(activity.getBaseContext(), "Exception",Toast.LENGTH_SHORT).show();
}
}
Fragment Class B
public class CountryDetailsFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
/** Inflating the layout country_details_fragment_layout to the view object v */
View v = inflater.inflate(R.layout.country_details_fragment_layout, null);
/** Getting the textview object of the layout to set the details */
TextView tv = (TextView) v.findViewById(R.id.country_details);
/** Getting the bundle object passed from MainActivity ( in Landscape mode ) or from
* CountryDetailsActivity ( in Portrait Mode )
* */
Bundle b = getArguments();
/** Getting the clicked item's position and setting corresponding details in the textview of the detailed fragment */
tv.setText("Details of " + Country.name[b.getInt("position")]);
return v;
}
}
Main Activity class for passing data between fragments
public class MainActivity extends Activity implements ListFragmentItemClickListener {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
/** This method will be executed when the user clicks on an item in the listview */
#Override
public void onListFragmentItemClick(int position) {
/** Getting the orientation ( Landscape or Portrait ) of the screen */
int orientation = getResources().getConfiguration().orientation;
/** Landscape Mode */
if(orientation == Configuration.ORIENTATION_LANDSCAPE ){
/** Getting the fragment manager for fragment related operations */
FragmentManager fragmentManager = getFragmentManager();
/** Getting the fragmenttransaction object, which can be used to add, remove or replace a fragment */
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
/** Getting the existing detailed fragment object, if it already exists.
* The fragment object is retrieved by its tag name *
*/
Fragment prevFrag = fragmentManager.findFragmentByTag("in.wptrafficanalyzer.country.details");
/** Remove the existing detailed fragment object if it exists */
if(prevFrag!=null)
fragmentTransaction.remove(prevFrag);
/** Instantiating the fragment CountryDetailsFragment */
CountryDetailsFragment fragment = new CountryDetailsFragment();
/** Creating a bundle object to pass the data(the clicked item's position) from the activity to the fragment */
Bundle b = new Bundle();
/** Setting the data to the bundle object */
b.putInt("position", position);
/** Setting the bundle object to the fragment */
fragment.setArguments(b);
/** Adding the fragment to the fragment transaction */
fragmentTransaction.add(R.id.detail_fragment_container, fragment,"in.wptrafficanalyzer.country.details");
/** Adding this transaction to backstack */
fragmentTransaction.addToBackStack(null);
/** Making this transaction in effect */
fragmentTransaction.commit();
}else{ /** Portrait Mode or Square mode */
/** Creating an intent object to start the CountryDetailsActivity */
Intent intent = new Intent("in.wptrafficanalyzer.CountryDetailsActivity");
/** Setting data ( the clicked item's position ) to this intent */
intent.putExtra("position", position);
/** Starting the activity by passing the implicit intent */
startActivity(intent);
}
}
}
Detailde acitivity class
public class CountryDetailsActivity extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/** Setting the layout for this activity */
setContentView(R.layout.country_details_activity_layout);
/** Getting the fragment manager for fragment related operations */
FragmentManager fragmentManager = getFragmentManager();
/** Getting the fragmenttransaction object, which can be used to add, remove or replace a fragment */
FragmentTransaction fragmentTransacton = fragmentManager.beginTransaction();
/** Instantiating the fragment CountryDetailsFragment */
CountryDetailsFragment detailsFragment = new CountryDetailsFragment();
/** Creating a bundle object to pass the data(the clicked item's position) from the activity to the fragment */
Bundle b = new Bundle();
/** Setting the data to the bundle object from the Intent*/
b.putInt("position", getIntent().getIntExtra("position", 0));
/** Setting the bundle object to the fragment */
detailsFragment.setArguments(b);
/** Adding the fragment to the fragment transaction */
fragmentTransacton.add(R.id.country_details_fragment_container, detailsFragment);
/** Making this transaction in effect */
fragmentTransacton.commit();
}
}
Array Of Contries
public class Country {
/** Array of countries used to display in CountryListFragment */
static String name[] = new String[] {
"India",
"Pakistan",
"Sri Lanka",
"China",
"Bangladesh",
"Nepal",
"Afghanistan",
"North Korea",
"South Korea",
"Japan",
"Bhutan"
};
}
For More Details visit this link [http://wptrafficanalyzer.in/blog/itemclick-handler-for-listfragment-in-android/]. There are full example ..
Basically here we are dealing with communication between Fragments. Communication between fragments can never be directly possible. It involves activity under the context of which both the fragments are created.
You need to create an interface in the sending fragment and implement the interface in the activity which will reprieve the message and transfer to the receiving fragment.