I'm try to use event bus lib, I could not understand it's functionality and see multiple examples. Is it use only services class or use activity and fragment then is use activity what situation we use event bus in activity or fragment.
Instead of interface we can simply use EventBus .we can pass messages from one class to one or more classes. EventBus in 3 steps
Define
Register and unregister
Post Event
Define events:
public static class MessageEvent { /* your getter and setter */ }
Prepare subscribers: Declare and annotate your subscribing method, optionally specify a thread mode:
#Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
/* event fire here when you post event from other class or fragment */
};
Register and unregister your subscriber. For example on Android, activities and fragments should usually register according to their life cycle:
#Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);//Register
}
unRegister
#Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);//unregister
}
Post events:
EventBus.getDefault().post(new MessageEvent());//post event
You can consider EventBus as a lightweight communication channel for passing data within activities, or services, or fragments or between any of them.
Think of EventBus as an underlying layer in your app which is independent of any active activities or services or fragments and their lifecycle.
The main concept on which an EventBus works is that you subscribe to events in either an activity or fragment or service or any components like that and whenever the EventBus has a specific event of the type you subscribed, it notifies your subscribed method in that component and you can perform any task there based on the event that you have received.
Triggering an event is easy and you can do it from any area of your app by just passing a specific event (which is basically a POJO class, let's say MyEvent) to the EventBus, and the bus will handle the rest and correctly deliver it to the appropriate receiver/s.
I would recommend you to try out EventBus 3 from GreenRobot, and go through their documentation here to incorporate their library n your code. I have been using the same without any problems.
EventBus 3 by GreenRobot
Hope this helps.
Mostly you shouldn't. In general its a hack for when you misarchitected your program and can't easily pass data from one point to another due to how your app is encapsulated and what objects are known at what levels. It can cause real spaghetti code where its difficult to figure out what code will actually be called when an event occurs. You shouldn't be writing your code around having an event bus, it should be a last resort if you can't refactor things to work the correct way.
One of the advantages of events is that you can pass objects around to 'somewhere', and you don't need to know where it is picked up. This makes it easy to push your activity or fragment state to a controller class, and then use events sent from this controller back to the activity or fragment.
Because of events, the controller doesn't need to know if the receiving end is an activity or a fragment. This makes it very easy to switch one for the other. On the other hand this also makes it easy to put the controller somewhere else. Like first you have it as an instance in the application class, and then you move it to a service.
I wrote an article with a very concrete example on how you can use events to deal with the Android life cycle as described above: https://medium.com/#JuliusHuijnk/beating-the-android-life-cycle-d00a2f3ed88
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.
I am developing an application in which I am using retrofit library for calling the web services . After calling web-service a callback return Response then I am passing the Response to the next activity. I want to know the best approach for this .
I am new in memory related problems please correct me if I am totally wrong.
Shall I make a new class then pass a weak reference to that class and call the function from that class on the main activity.
Or
I shall register a new event on event bus and when the callback returns the object ,fire the event and call the function.
Please consider what is good to avoid Memory Leaks.
Saving callbacks/listeners in weak references is not a good idea. See
Pros and Cons of Listeners as WeakReferences
Are anonymous listeners incompatible with weak references?
You can "broadcast" results of asynchronous operations (Network calls in your case) on completion using event bus, and have other objects (Views, Fragments, Activities) register to event bus. Points to note:
Listeners must always un-register properly, else its a memory leak.
You'll need to create a new class for each event type. Soon this number will grow.
Inheritance and Event bus do not play well. There is no proper "overriding" of listening methods possible.
Perhaps some other object also requested the same data. Since EventBus broadcasts to all, listeners might get multiple events of same type, at unsuspected timing.
Particular to Retrofit usage, if you do requests asynchronously as:
GitHubService service = retrofit.create(GitHubService.class);
Call<List<Repo>> repos = service.listRepos("octocat");
repos.enqueue(myCallback)
Then you must remember to cancel all calls that a component has made, when the life-cycle of component is complete. I.e onDestroy() of Activity, onDetach() of Fragment, onDetachFromWindow() of View:
repos.cancel();
I'm writing an android app right now using EventBus greenrobot. For example I have an Activity it's a publisher in our situation and we have some custom class - just simple class and it is subscriber. Let's assume that I'm posting event from activity. As far as i understand we don't have any instance of custom class, because right now it's decoupled from activity. So how can I make to have instance of this class always.
Or may be I'm using Eventbus incorrectly.
Every time you post an event, the subscriber has to be ready to get that event doing:
eventBus.register(this)
So that class always has to be initialized (from your Activity or from some other part in your app)
I've got 2 running classes registered for EventBus events - instance A and instance B. Both of them have implemented onEvent(SampleEvent event) method for receiving EventBus.post(new SampleEvent(int foo, String bar)); from a place C. So far so good.
But there is a time when I need to post SampleEvent from B to A. Is it possible to tell B that it shouldn't process SampleEvent sent by itself, or I need to do workaround like setting a flag in SampleEvent?
You could try to extend SampleEvent for exmaple SampleEventToA than you check within B by using reflection:
if (! event instanceof SampleEventA){
//do things here
}
Found this issue on otto EventBus: Derived events from super event will also call the subscriber of the super event. This would be a possible OO solution!
https://github.com/square/otto/issues/83
I have typical AsyncTask that I want to properly decouple from my Activity classes and UI logic.
I think of doing it this way:
Make listener interface
public interface MyTaskListener {
void onTaskProgress(...);
void onTaskDone(...);
}
Make my Activity implement MyTaskListener and pass this reference on task creation.
Call listener methods inonPreExecute(), onProgressUpdate() and onPostExecute().
But may be I'm reinvetning the wheel and Android framework has something better already implemented? I think of something like EventBus pattern where all interested parties can register for particular event types that I can fire from my AsyncTask.
The interface is most clean way of doing this, because your task class is 'sealed', knows nothing about surrounding environment (does not access any stuff from outer class which quite tempting when you use inner classes) and communicates back with generic channel.