I want to pass a function from one activity to another using Broadcasts. Like we can pass Strings and int by putExtra, Is there a way I can pass a whole function? I know there are other ways to do this, but I need to do this with the help of broadcasts. Any help?
Ex:
void myFunc(){ /* foo */ }
Can I use myFunc in some other activity via broadcast? I don't mind declaring the function again in the new activity as long as I get data from broadcast.
Is there a way I can pass a whole function?
No, sorry.
Can I use myFunc in some other activity via broadcast?
No, sorry.
Alternatives:
Use one activity rather than two
Have both activities work with some other object that is outside each of those activities (e.g., a singleton serving as a repository)
Related
In my app, I have to call an activity method from the fragment.
I know I can do this in two ways:
1. Via sending a broadcast to activity:
Intent intent = new Intent("FILTER");
intent.putExtra("EXTRA", 1);
sendBroadcast(intent);
2. Or Calling the activity method directly:
((MyActivity) getActivity()).method();
I would like to know which way is faster and safe to communicate. Any help would be appreciated.
Thank you.
Loosely Coupled Fragment?
I am not sure about the speed. But on the design perspective You should use an interface to communicate with an Activity rather calling Activity method directly from your Fragment. ie ((MyActivity) getActivity()).method();
Because using an interface makes your Fragment independent from your
Activity. Let's say in future you want to use your fragment in Some
other Activity then you will not have to change anything in your
Fragment.
Interface
public interface Somelistener {
public void someMethod();
}
Your Loosely coupled Fragment
YourFragment extends Fragment {
Somelistener listener;
public void onActivityCreated(Context context){
listener = (SomeLisner)context;
}
public void buttonClick()
{
listener.someMethod();
}
}
So if you are using in your MainActivity. No problem
MainActivity implements SomeListener{
#Override
public void someMethod()
{
// Activity method
}
}
In future you want to use Fragment in SomeOtherActivity. No problem
SomeOtherActivity implements SomeListener{
#Override
public void someMethod()
{
// somethother method
}
}
BroadcastReceiver Approach?
TBH I have seen this approach for Service-Activity Communication. Not for Activity - Fragment communication.
For communicating between Fragments and the Activity that contains it, there's actually a much better 3rd option.
The better option is to use an Interface as a callback method. This is described very well in this documentation: https://developer.android.com/training/basics/fragments/communicating
Using an interface is much more preferred over your two methods because it's both safer and more efficient.
For your first method of using Broadcast Receivers, this is actually a very inefficient solution due to Broadcast Receivers not being meant for a task like what you're after.
Let me quote you something from the Android documentation:
Warning: Limit how many broadcast receivers you set in your app. Having too many broadcast receivers can affect your app's performance and the battery life of users' devices. For more information about APIs you can use instead of the BroadcastReceiver class for scheduling background work, see Background Optimizations.
https://developer.android.com/guide/topics/manifest/receiver-element
So yes, Broadcast Receivers will have a bigger effect on your app's performance and the device's battery life over the other method you suggested and the method I suggested.
Additionally, don't forget that a Broadcast Receiver is meant to listen to broadcasts. The type of Broadcast Receiver you're using in your example is actually a Global Broadcast where you didn't explicitly limit it's "range", so any Broadcast Receiver could potentially "listen" in to your broadcast. In terms of security, using a Global Broadcast like this isn't safe either.
You also don't want other apps to potentially fire off a Broadcast that coincidentally coincides with your app's Broadcast Receiver, causing it to receive data not meant for it and crashing due to this accidental and coincidental naming.
Honestly, there's more potential issues of using a Broadcast Receiver in a way it's not meant for.
As for your second method of directly calling the Activity's method... this is actually very inefficient for managing code. You're basically tying the Fragment tightly together with that specific Activity.
However, Fragments, by design, makes it common to be swapped into other Activities or Fragments... you'll basically have to do multiple if statements and casts each time you want to run code from it's parent.
Also, keep in mind that if you later change code in MyActivity, it can cause problems for this fragment due to you forgetting how tightly bound it is to the Activity.
But if you use the more preferred Callback Interface approach, it's simply a middleman meant to deliver a "Hey, DO something for me" message. Quick and direct. It's also plays friendly with any Activity or Fragment you want to attach this Fragment to later since those Activities or Fragments simply have to implement the Interface and the callback bridge between both parent and child is formed.
It is better to use interface to communicate from fragment to activity rather than a Local broadcast.
Activity will implement the interface and fragment will call the methods.
Many times we use intents to send data to a Fragment or get data back from a child. Can't we just put data in a public variable?
For example imagine if we want to get data from user from a dialog box.
I'm just talking about the "possibility". Undoubtedly, It is superior to use intents for code cleanness or safety...
you don't send intent's to fragments, if you want to use objects you need to have your object implement Parcelable then you can just send the object in the intent bundle
public class MyActivity extends Activity {
public int someValue = 1;
}
And in any fragment which has MyActivity as a host you can access ((MyActivity) getActivity()).someValue.
I think what he means is sending (local)broadcast... which is by the way the proper way of doing it according to my understanding.
Of course it is possible to have public (or even protected) fields and access them from a child-fragment with something like this:
assuming your parent activity is named "MainActivity"
((MainActivity) getActivity()).mMyPublicField
or:
((MainActivity) getActivity()).getPublicMethod()
- but I would never recommend doing this!
especially when you also start manipulating the public field you can run into ugly trouble when different threads are in play.
If something needs so be shared across the whole application, use SharedPreferences (if you want to store it for the next app session too) or as I mentioned first LocalBroadCastManager.
is it expensive to always pass Activity as an argument to a method?
You see, I have this class (this is where I put the commonly used methods by my activities). And all my methods there have Activity as a parameter, because the results of those methods will need to be send back to the activity that invoked the method, so basically I need to know to whom should I throw back the results, so I always have like:
public static void processThis(Activity activity){
// some Code
}
I just like to know if this is against the best practices or if this is expensive to use?
Thanks. Looking forward for your explanations that will enlighten me.
Added:
I'm extracting commonly used methods from my activities to promote code reuse. Like, ActivityA use methodA and send broadcast back to ActivityA, same way goes for ActivityB which uses methodB(same as methodA) and send broadcast back to ActivityB. So what I want to achieve is to to extract that methodA and methodB which basically are the same, and put them into another class, and add a parameter Activity so I can know to whom do I need to send the broadcast back. Thanks.
In Java, all parameters that are not primitives are implicit pointers; consequently, passing an object such as activity only requires passing around the address at which the Activity is located in memory, so passing such a thing is not an expensive thing to do in Java.
So, the real question you should ask yourself is not whether it is expensive, but rather if it makes the most sense (from a logical / maintainability perspective). If it makes sense, then by all means do it.
Is it possible to register a global broadcast receiver that gets notified every time a new activity is started (either by startActivity, startActivityForResult, etc)? What would the IntentFilter be?
EDIT: Just to clarify, I don't mean across apps I mean within my own app
You could potentially create your own partial subclass of Activity where it overrides onCreate(), onStart(), etc and manually calls a static/singleton instance of your global receiver as appropriate. After that, just derive your own activities' implementations from that subclass.
However, I'm assuming the reason you want to do this is that the "receiver" actually contains or otherwise represents some globally available state or resource - if you can find a way to implement your application without having any global state (and just passing it along as payload for an activity call, for instance), that would be best.
No, there is no way to do that.
I have an activity which has a static method for updating a textfield. This way I can update this view from another activity.
But now I'm trying to get a Context variable in this static method which is not possible. I've tried declaring a Context variable and initialising it in onCreate ( context = getApplicationContext();)
But still I can't access context in this static method. How is this normally done?
edit: a little bit more information about my situation. I'm starting a countdowntimer in an activity(a) which updates another activity's(b) ``textfield every second. And it does this by accessing b's setTextField in a static way..
How is this normally done?
Accessing a TextView via a static method is not the best way to update the field from another activity. If you want to pass a value to the activity when it starts, you can send data via the intent (i.e. intent.getExtras). If you want to pass data back from a sub-activity, you can use startActivityForResult.
The way you are going is very strange. Why are you trying to change one activity content from another? May be you need to use startActivityForResult to strat a new activity and then return result from it and change views depending on it?
You might want to check some documentation on OO and using static functions. It is not considered a very good approach.
But as we are not talking about a better complete sollution: you can add a parameter with a context to the function, and just give it when you call the function :)
I would suggest the LocalBinder pattern to update the other Activity:
http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html
Can you do something like this?
something like this <viewobj>.getContext()
Ref: How can I start an Activity from a non-Activity class?
Whenever you're busy with Activity A, there's no point in updating something on Activity B as it is simply not shown to the user at that point in time.
Seems to me you need to have some kind of global variable here that can be picked up in the onResume of Activity B.
Checkout this question : How to declare global variables in Android?
It shows you how to use the Application class to maintain global application state, accessable from all activities when needed.