Hy,
My activity must receive an object using sockets ..
This activity has within fragment A and fragment B.
I wish that every time the activity receiving the object, send it to fragment A.
how can I do?
I think this is a perfect example of where an event bus would be very handy. Check out Square's Otto. If you create an event bus and make it available to your activity and to your fragments (either via a static class or using dependency injection) you can send myObject via the bus without the need to serialize it.
Here's some example code. First I create a statically accessible global event bus in OttoBus.java. This is the bus on which we'll pass messages back and forth between the activity and the fragments. In the Activity I assume you'll have some kind of method that receives the data from the socket. The received data will be put in a SocketDataReceivedEvent object and sent on the bus. In your Fragment you register the fragment on the bus when the Fragment is started and unregister it when it's stopped (to avoid leaking). The Fragment must also have a method to handle the SocketDataReceivedEvent. This method can be named whatever you like as long as it's annotated with #Subscribe and takes a SocketDataReceivedEvent as it's only parameter.
---- OttoBus.java
import com.squareup.otto.Bus;
public class OttoBus {
private static Bus bus = new Bus();
public static void register(Object o) {
bus.register(o);
}
public static void post(Object data) {
bus.post(data);
}
public static void unregister(Object o) {
bus.unregister(o);
}
}
---- SocketDataReceivedEvent.java
public class SocketDataReceivedEvent {
public Object data;
public SocketDataReceivedEvent(Object data) {
this.data = data;
}
}
---- YourActivty.java
public class YourActivity extends Activity {
public void receiveSomethingOnSocket(Object theDataYouReceived) {
OttoBus.send(new SocketDataReceivedEvent(theDataYouReceived));
}
}
---- YourFragment.java
public class YourFragment extends Fragment {
#Override
public void onStart() {
super.onStart();
OttoBus.register(this);
}
#Override
public void onStop() {
super.onStop();
OttoBus.unregister(this);
}
#Subscribe
public void onSocketData(final SocketDataReceivedEvent e) {
// do something with e.data
}
}
Related
For Fragment(put data to activity)
m=(MainActivity)getActivity();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Intent in=new Intent(getActivity(),MainActivity.class)
in.putExtra("test",test);
startActivty(in)
}
},10);
For Activity (get data from fragment )
{
String get_data=getIntent.getStringExtra("test");
}
//it will return always null...any body help me?
startActivty(in) will start the same activity.
Instead of this, you can make use of Interface. It's the easiest way to pass the data.
in your fragment, you can have an interface like,
SubmitData mSubmitData;
public interface SubmitData{
void DataListener(String s);
}
mSubmitData.DataListener("data to be sent");
In your activity, implement the SubmitData interface. It will make you override the DataListener method, where you can get the data.
public class MyActivity extends AppCompatActivity implements YourFragment.SubmitData{
#Override
public void DataListener(String s) {
// Data from the fragment
}
This questions has been asked and answered multiple times. You can find a valid reply here https://stackoverflow.com/a/9977370/5828132
Basically, it consists of creating an interface in the Fragment (for example) including a simple method. The Fragment has to declare a field of that type, and the Activity hosting the Fragment has to implement (implements) that interface. Both entities are usually connected using a explicit cast, in the onAttach() callback of the Fragment life-cycle, i.e.:
#Override
public void onAttach(Context context) {
super.onAttach(context);
// fragmentField_interfaceType = (interfaceType) context;
}
Hope it helps!
I am using websocket for the first time, It's a Uber kind of application. I am receiving data from the socket , the socket connection and receiver is in common class, but i am confused how to pass data for the particular activity or fragment in a optimized way. As per my knowledge i thought of using Broadcast receiver in required class, but its not a good way ...So any help would be appreciated.
found a good solution i don't think it's the ultimate but, it works faster than Brad cast receiver.
I created a Interface in Main Activity, with a method that send the received data.
public class MainActivity extends AppCompatActivity{
SendData sendData;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public interface SendData {
public void sendData(String data);
}
}
In Fragment Class where i need the response from Main Activity, I implemented the above Interface of Main Activity.
public class Storage extends Fragment implements MainActivity.SendData{
View view;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
view = inflater.inflate(R.layout.driver_info_fragment,container,false);
return view;
}
#Override
public void SendData(String data) {
String dataReceived = data;
}
}
When i receive the data in Main Activity i will get the current fragment, if i want data to be sent to that fragment then i should have implemented the Main Activity Interface in that fragment and Create a casting in Main Class when i have the data and notify the fragment with the value
public class MainActivity extends AppCompatActivity{
#Override
public void notifySocketMessage(final String message) {
if(message != null){
dataPasser = // define the fragment class name where you need to send the data.
dataPasser.onDataPass(message); // add the message to the notifier
}
}
}
I call my DialogFragment like so:
If I am in an Activity:
MyDialogFragment dialogfragment = new MyDialogFragment();
dialogfragment.show(getFragmentManager(), "");
If I am already in a Fragment:
MyDialogFragment dialogfragment = new MyDialogFragment();
dialogfragment.show(getActivity().getFragmentManager(), "");
In MyDialogFragment, which inflates an XML and allows the user to input some values to EditTexts and so forth, I want to be able to return those values back to wherever I called the dialog from.
For the sake of the question let's say my dialog class wants to return some private variables String mName and int mValue.
Is there a proper way to do this without knowing where the dialog is being called from (either an Activity or a Fragment)? How do I pass the values back / how do I receive them?
If you want to send data to activity from fragment. You can do that by calling public method of activity by:
((MainActivity)getActivity()).sendData(Object object);
You can't do the same for sending data to a fragment.
As doc says:
All Fragment-to-Fragment communication is done through the associated Activity. Two Fragments should never communicate directly.
What you should do is:
Define an Interface in the fragment.
Implement that Interface in the activity
Deliver data to the activity
then activity will deliver data to some other fragment.
BTW, you can also use this practice to send data to activity (upto point 3).
Reference and example
Defining an interface:
public interface DataListener {
public void onDataReceived(Object obj);
}
inside the fragment:
public class MyFragment extends Fragment {
DataListener callback;
#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 {
callback = (DataListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement DataListener");
}
}
}
Sending data from fragment;
callback.onDataReceived(object); // some object data
Receiving data in activity:
public static class MainActivity extends AppCompatActivity
implements DataListener{
public void onDataReceived(Object object) {
// Do something here with object data
}
}
Now if you want, you can send this data to any other fragment.
Sending data from activity to some other fragment:
AnotherFragment anotherFrag = (AnotherFragment)
getSupportFragmentManager().findFragmentById(R.id.fragment_container);
if (anotherFrag != null) {
anotherFrag.receiveDataInFrag(object);
}else{
// create a new instance of the fragment and pass data to it.
}
Create a callback interface and have pass it into your dialogfragment
interface DialogValuesCallback {
void callThisFunctionWhenUserClicksOnOkInDialog(String passinmName,int passinmValue);
}
You can have your Activity or Fragment implement this interface.
Have a constructor in your MyDialogFragment which accepts the interface and assigns it to an member variable.
MyDialogFragment(DialogValuesCallback activityOrFragmentWhichImplementsThis){
mInterfaceCallbackObjectRef = activityOrFragmentWhichImplementsThis;
}
#Rohit Arya this is what you should know first that fragments needs to declare an interface that must be implemented by every activity that uses that fragment so you can pass data from the fragment to the activity(s)... and must cast the activity displaying the fragment currently into this interface like this in your onAttach method
//#param Listener is the declared interface in your fragment class
public class MyFragment extends Fragment {
Listener mInterface;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mInterface = (Listener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()`
+ " must implement DataListener");
}
}
public interface Listener{
//#param type = data type, cont = variable
public void sendData(type cont, type2 cont2)
;
}
}
make sure the interface declared in your fragment get implemented in your baseActivity then what ever data you pass to the interface using
mInterface.sendData(value, value1);
you can get it in the base activity like
public class baseActivity extends Activity implements MyFragment.Listener{
//#param cont & cont2 are data sent from MyFragment
#Override
public void sendData(type cont, type cont2){
//do what ever with your values here
}
}
got it now?
In my main Activity, I have a DialogFragment that contains a FragmentTabHost. I have two tabs, one that is a DialogFragment and one that is a ListFragment. When either the 'OK' button is pressed in the inner DialogFragment or when an element in the ListFragment is pressed, I want to pass two Strings (that are entered in two TextView's in the inner DialogFragment and are displayed in each element in the ListFragment) back to the Activity, but I am unsure of how to do this with multiple levels of Fragments.
Any help is appreciated!
There's no magic.
You can achieve with two approaches.
Use callback.
Create interface and class to pass the data through child Fragment to Activity. You don't need to modify bridged TabHostFragment as Fragment always rely on its mother Context (Activity) no matter how many fragments wrap the fragment.
public class TwoStrings {
public TwoStrings(String one, String two){
this.one = one;
this.two = two;
}
public String one;
public String two;
}
First, declare interface.
public interface DataPassListener {
void dataPassed(TwoStrings data);
}
And, implement interface in Activity.
public class MainActivity extends Activity implements DataPassListener {
#Override
public void dataPassed(TwoStrings data) {
// do something with data.
Log.d("string one", data.one);
Log.d("string two", data.two);
}
}
Finally, let child Fragment acknowlege that mother Activity has the callback listener.
public class DialogFragment1 extends DialogFragment {
DataPassListener listener;
#Override
public void onAttach(Activity activity) {
if (activity instanceOf DataPassListener)
listener = (DataPassListener) activity;
}
public void setDataPassListener(DataPassListener listener){
listener = ((DataPassListener) listener);
}
public void doSomeThing(){
if(listener != null) // important to prevent NullPointerException
listener.dataPassed("a", "b");
}
}
Use EventBus.
I prefer to use Otto in order to publish and subscribe data.
To subscribe event for listening in Activity,
public class MainActivity extends Activity {
#Override
public void onResume() {
super.onResume();
BusProvider.getInstance().register(this);
}
#Override
public void onPause() {
super.onPause();
BusProvider.getInstance().unregister(this);
}
#Subscribe
public void onUpdateTwoStrings(TwoStrings event) {
// do something with data.
Log.d("string one", data.one);
Log.d("string two", data.two);
}
}
And, publish event in anywhere in Fragment.
bus.post(new TwoStrings("a", "b"));
Take a look at setTargetFragment() and getTargetFragment() methods. You could connect fragments with each other through it without any additional callbacks and libs.
I searched all over the web, couldn't find a good reference on how to call fragment from another fragment.
Fragment A -> Fragment B (fragment A calls fragment B after 3 seconds)
Well, first of all you need to consider that it's a very bad idea to keep somehow a direct reference from FragmentA to FragmentB. Why:
FragmentB may be recreated and you may keep a reference to an older reference of FragmentB. So you have a memory leak.
FragmentB may be not created, added or visible. So you would have a null/unusable reference.
For this reason you need to consider methods that base on sending messages from FragmentA to FragmentB. I see several options:
Send a broadcast message using a custom action from FragmentA. FragmentB registers itself as a receiver for this kind of message (in onCreate/onResume/onAttach and de-register in onDestroy/onPause/onDetach) and when the message arrives it can handle it. This is very suitable if you have no data to send from FragmentA to FragmentB or if you do these are primitive types or easy-to-implement Parcelables. Here's an example:
Have this in FragmentA:
private void sendMessageToFragmentB(String someData) {
Intent messageIntent = new Intent("com.your_package.A_TO_B_ACTION");
messageIntent.putExtra("DATA_VALUE", someData);
LocalBroadcastManager.getInstance(getActivity()).sendBroadcast(messageIntent);
}
While in FragmentB you could have this:
public class FragmentB extends Fragment {
private BroadcastReceiver messagesFromAReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if ("com.your_package.A_TO_B_ACTION".equals(intent.getAction())) {
String dataFromA = intent.getStringExtra("DATA_VALUE");
dataFromAReceived(dataFromA);
}
}
};
protected void dataFromAReceived(String data) {
// here you have the data
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
IntentFilter messageFromAIntentFilter = new IntentFilter("com.your_package.A_TO_B_ACTION");
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(messagesFromAReceiver,
messageFromAIntentFilter);
}
#Override
public void onDestroy() {
super.onDestroy();
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(messagesFromAReceiver);
}
}
Use the hosting activity as a proxy: The host activity implements some kind of interface defined in FragmentA and when requested it can search if it can find FragmentB and if so call some method in there. The advantage is that you can send any data, no matter its weight. The base idea is descrived in Android dev articles. To exemplify, you could have FragmentA as:
public class FragmentA extends Fragment {
public static interface CallerProxy {
public void sendCustomMessage(Object... dataParams);
}
private CallerProxy proxyActivity;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (activity instanceof CallerProxy) {
this.proxyActivity = (CallerProxy) activity;
}
}
#Override
public void onDetach() {
super.onDetach();
this.proxyActivity = null;
}
private void sendMessageToFragmentB(String someData) {
if (proxyActivity != null) {
// send whatever data
proxyActivity.sendCustomMessage(new Integer(1), new Object());
// or don't send anything ...
proxyActivity.sendCustomMessage();
}
}
}
The proxy activity would have at least these methods and signature:
public class MyProxyActivity extends FragmentActivity implements CallerProxy {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// call setContentView and then make sure you've added FragmentA and
// FragmentB.
}
#Override
public void sendCustomMessage(Object... dataParams) {
// FragmentB must be identified somehow, either by tag,
// either by id. Suppose you'll identify by tag. This means you've added
// it previously with this tag
Fragment fragment = getSupportFragmentManager().findFragmentByTag("FragmentB-TAG");
if (fragment != null) {
FragmentB fragB = (FragmentB) fragment;
fragB.dataFromAReceived(dataParams);
}
}
}
While in FragmentB all you need is a method that can be called with above sent parameters:
public void dataFromAReceived(Object ... data) {
// here you have the data
}
Use or implement some sort of event bus. Some general details here. For Android I remember that Otto event bus was very handy and easy to use. Here's a link with this. This is very similar to first option as you need anyway to register and un-register.
In the end it depends on what you need to send as a message, when should it be received and how flexible does it need to be. ... your choice!
Enjoy programming!
Fragments are not supposed to connect to each other directly, that may be your problem in finding a decent guide to do this.
Your approach makes the assumption that a fragment B will always be reachable (and ready) for a fragment A to interact, and that is actually not true, will kill the flexibility of your Fragment and will cause you problems in the future.
A better approach to interaction of Fragments is to talk only through interfaces that talk directly to a activity that can handle who is alive when where and should receive what.
-> http://developer.android.com/training/basics/fragments/index.html
This Android guide above, specifically on the last topic, shows you how to do this.
i hope this code help you..
in your first fragment add this code
onCreateView
LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(getActivity());
IntentFilter intentFilter = new IntentFilter("update");
// Here you can add additional actions which then would be received by the BroadcastReceiver
broadcastManager.registerReceiver(receiver, intentFilter);
#Override
public void onDestroyView() {
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(receiver);
super.onDestroyView();
}
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action != null && action.equals("update")) {
// perform your update
getOngoingOrderData();
}
}
};
in your second fragment add this code where you send broadcast..
Intent intent = new Intent("update");
LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(getActivity());
broadcastManager.sendBroadcast(intent);