I have implemented EventBus in my project but I am not getting all of my events
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = findViewById(R.id.btn);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
EventBus.getDefault().post(new MessageEvent());
EventBus.getDefault().post(new MessageEvent2());
}
});
}
#Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event)
{
Toast.makeText(this, "MainActivity called", Toast.LENGTH_SHORT).show();
};
#Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
#Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
}
Here i created 2 event inside onClick();
And this is my AnotherActivity where i have another #Subscribe
public class AnotherActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_another);
}
#Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent2 event2)
{
Toast.makeText(this, "AnotherActivity called", Toast.LENGTH_SHORT).show();//Not getting called
};
#Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
#Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
}
I dont know why my second toast is not getting called, i have done every thing correctly.
What i suspect is the AnotherActivity is not created yet so my event is not called is that is so what is use of EventBus then?
What i suspect is the AnotherActivity is not created yet so my event
is not called is that is so
Yes, if the event happened in past and the component(activity) is not active/created then the event will not be received.
what is use of EventBus then?
You can use Sticky Event to listen to past events in newly created activity
so use postSticky
EventBus.getDefault().postSticky(new MessageEvent2());
and add sticky = true in subscribe annotation
#Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent2 event2){
Toast.makeText(this, "AnotherActivity called", Toast.LENGTH_SHORT).show();//Not getting called
};
or you can receive them manually
MessageEvent2 msg2 = EventBus.getDefault().getStickyEvent(MessageEvent2.class);
// you can also remove it using
// EventBus.getDefault().removeStickyEvent(msg2);
or remove it from history as well
MessageEvent2 msg2 = EventBus.getDefault().removeStickyEvent(MessageEvent2.class);
if(msg2!=null){//do something}
Related
I'm trying to pass an event with Otto Event Bus from the SplashActivity to LoginActivity which is 2 o 3 activities later with:
SplashActivity
#Override
public void onStart() {
super.onStart();
BusProvider.getInstance().register(this);
if(UtilityManager.isAppOpenedFromNotificationTap(this)){
BusProvider.getInstance().post(new AppOpenedFromNotificationClickEvent());
}
}
#Override
public void onStop() {
super.onStop();
BusProvider.getInstance().unregister(this);
}
And I am getting value with:
LoginActivity
#Override
public void onStart() {
super.onStart();
BusProvider.getInstance().register(this);
}
#Override
public void onStop() {
super.onStop();
BusProvider.getInstance().unregister(this);
}
#Subscribe
public void onAppOpenedFromNotificationEvent(AppOpenedFromNotificationClickEvent event) {
Log.e("LOGIN", "ARRIVED" );
appOpenedFromNotification = true;
}
These Log that I put inside subscribe is never showed. What the problem?
Use a sticky event
for sending
EventBus.getDefault().postSticky(new MessageEvent("Hello everyone!"));
for receiving
// UI updates must run on MainThread
#Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onEvent(MessageEvent event) {
textField.setText(event.message);
}
Here I used #Subscribe annotation but my calender_text is not updated.But calender_text.setText("Test") properly working in side the oncreate method.What can be the issue?
#Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent(Date event) {
// your implementation
date = event.getSelected_date();
calender_text.setText("Test");
Toast.makeText(getActivity(), event.getSelected_date(), Toast.LENGTH_SHORT).show();
}
You need to register EventBus in onStart() method
#Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
You need to unregister EventBus in onStop() method
#Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
Problem:
For some communication scenarios I am using EventBus.
I have got an event that is already successfully fired and subscribed by different components in my app.
Now I need an activity to subscribe that event. Unfortunately it is not reached.
Question:
How can I achieve that the activity does subscribe the event correctly, either? Is the problem with registering the activity?
Note:
I have found that post that suggests to use onStart() and onStop() events.
my activity class:
public class MachineActivity extends AppCompatActivity{
(...)
#Override
protected void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
#Override
protected void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
#Subscribe(threadMode = ThreadMode.MAIN)
public void characteristicsChangeByUser(IntentChangeByUser intentChangeByUser) {
// Do something here.
}
(...)
}
EventBus class:
public class IntentChangeByUser {
int position;
int value;
public IntentChangeByUser(int position, int value){
this.position = position;
this.value = value;
}
public int getPosition() {
return position;
}
public int getValue() {
return value;
}
}
Could be because you have the wrong way to unregister then EventBus in onStop().
Change to this:
#Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
#Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
Then make sure in your Subscriber Activity, there is received Event:
#Subscribe(threadMode = ThreadMode.MAIN)
public void characteristicsChangeByUser(IntentChangeByUser intentChangeByUser) {
// Do something here.
Log.d("Activity", "IntentChangeByUser Event received");
}
I am working in a Hello Otto basic project in order to learn a bit how it works. This is my BusProvider over Otto 7.0.1. In MainActivity I have two buttons, after tap on the first one I post a string in the bus object. This is my BusProvider
public class BusProvider {
private BusProvider() {}
private static Bus bus;
public static Bus getInstance() {
if (bus == null){
bus = new Bus();
}
return bus;
}
}
MainActivity who will sent a String to Main2Activity using the bus class
public class MainActivity extends AppCompatActivity {
private Bus bus;
#Bind(R.id.myButton)Button mButton;
#Bind(R.id.button2)Button mButton2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setLibreries();
this.bus = BusProvider.getInstance();
}
#Override
protected void onPause() {
super.onPause();
}
#Override
protected void onResume() {
super.onResume();
}
public void setLibreries(){
ButterKnife.bind(this);
}
#OnClick(R.id.myButton)
protected void buttonPressed1( ){
Toast.makeText(this, "click on the 1 button",Toast.LENGTH_SHORT).show();
BusProvider.getInstance().post("HELLO OTTO");
Intent intent = new Intent(MainActivity.this,Main2Activity.class);
startActivity(intent);
}
#OnClick(R.id.button2)
protected void buttonPressed(){
Toast.makeText(this, "click on the 2 button",Toast.LENGTH_SHORT).show();
}
}
Main2Activity how receives the String
public class Main2Activity extends AppCompatActivity {
private Bus bus;
#Bind(R.id.this_is_a_text_view) TextView myTextButter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
bus = BusProvider.getInstance();
ButterKnife.bind(this);
myTextButter.setText("HELLO");
}
#Override
protected void onResume() {
BusProvider.getInstance().register(this);
super.onResume();
}
#Override
protected void onPause() {
super.onPause();
BusProvider.getInstance().unregister(this);
}
#Subscribe
public void gettingStringPosted(String message){
Log.d("OTTO", "OTTO subscribe has been called "+message);
Toast.makeText(this,message,Toast.LENGTH_SHORT).show();
}
}
The problem is that the Toast with the message I am sending in MainActivity to Main2Activity
HELLO OTTO
is never showed.
What I am doing wrong?
The problem is that your Main2Activity has not been registered yet to Otto when your BusProvider.getInstance().post("HELLO OTTO"); line comes.
Here is how your code does:
Bus.post()
Bus.register()
This is how it should go:
Bus.register()
Bus.post()
You can't solve this by moving the line BusProvider.getInstance().post("HELLO OTTO"); under the startActivity() call because Activity.onResume() might not get called straight away so your register call (in onResume) could still happen after post call. I hope this makes sense to you.
This is just example of otto, to make sense how it is. Let's assume you have a service, and in it getting locations and sending to activities.
public class TrackingService extends Service {
Bus bus;
LocationListener mListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
bus.post(new MyLocation(location));
}
};
// Other service related methods..
}
And activity
#Override
protected void onResume() {
BusProvider.getInstance().register(this);
super.onResume();
}
#Override
protected void onPause() {
super.onPause();
BusProvider.getInstance().unregister(this);
}
#Subscribe
public void locationChanged(MyLocation location){
Toast.makeText(this, "you got new location", Toast.LENGTH_SHORT).show();
}
Thats just it.
BTW, and this is the what i mentioned for you in my comment
In MainActivity
Intent intent = new Intent(getBaseContext(), Main2Activity.class);
intent.putExtra("MY_INFO", "INFO");
startActivity(intent)
In Main2Activity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view);
Intent intent = getIntent();
String info = intent.getStringExtra("MY_INFO");
}
I have BaseActivity with register() and unregister() methods:
public class BaseActivity extends AppCompatActivity{
...
#Override
protected void onResume() {
super.onResume();
// Register ourselves so that we can provide the initial value.
BusProvider.getInstance().register(this);
}
#Override
protected void onPause() {
super.onPause();
// Always unregister when an object no longer should be on the bus.
BusProvider.getInstance().unregister(this);
}
protected void setFragment(Fragment fragment){
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(ROOT_CONTAINER_ID, fragment);
if(!isFinishing()) {
transaction.commitAllowingStateLoss();
}
}
}
I have ChildActivity which fire DoneEvent to FrDetails fragment and it works fine.
public class ChildActivity extends BaseActivity implements View.OnClickListener{
private ImageView btnDone;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
btnDone = (ImageView) toolbarView.findViewById(R.id.btnDone);
btnDone.setOnClickListener(this);
setFragment(FrDetails.newInstance());
}
#Override
public void onClick(View v) {
int viewId = v.getId();
switch (viewId){
case R.id.btnDone:
BusProvider.getInstance().post(new DoneEvent());
break;
default:
break;
}
}
#Subscribe
public void onDataFilled(DataFilledEvent event) {
Log.e("Data filled", "Yessss");
}
}
But DataFilledEvent doesn't fire to ChildActivity from onActivityResult method of FrDetails fragment. I've called register() and unregister() methods in FrBase fragment. FrDetails fragment is child for FrBase fragment.
public abstract class FrBase extends Fragment {
...
#Override
public void onResume() {
super.onResume();
BusProvider.getInstance().register(this);
}
#Override
public void onPause() {
super.onPause();
BusProvider.getInstance().unregister(this);
}
}
This is my FrDetails class:
import com.squareup.otto.Subscribe;
public class FrDetails extends FrBase implements View.OnClickListener{
...
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View baseView = inflater.inflate(R.layout.one_fragment, null);
button = (Button) baseView.findViewById(R.id.btn1);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//WORK FINE HERE!
BusProvider.getInstance().post(new DataFilledEvent());
}
});
button2 = (Button) baseView.findViewById(R.id.btn2);
button2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(getBaseActivity(), ThirdActivity.class);
startActivityForResult(intent, SELECT_YEAR);
}
});
}
#Subscribe
public void onDone(DoneEvent event) {
//WORKS FINE HERE!
Toast.makeText(getActivity(), "Done", Toast.LENGTH_SHORT).show();
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//Log is called correctly
Log.e("OK", "log");
//DOENS'T WORK HERE!
BusProvider.getInstance().post(new DataFilledEvent());
}
}
Why BusProvider.getInstance().post(new DataFilledEvent()); doesn't fire event from onActivityResult() to ChildActivity? But it works if we fire event by click on button in FrDetails fragment.
Thanks in advance.
Based on the documentation on onActivityResult() (relevant snippet only):
You will receive this call immediately before onResume() when your activity is re-starting.
In other words, the event is fired before your activity has registered itself with the bus, because registration happens in onResume().
If you want to be able to fire and receive events at an earlier stage in the activity's life cycle, you should change registration (and unregistration) accordingly.
Alternatively, you may be able to get away with simply registering in onActivityResult() also. I haven't looked at Otto's code for a while, but I imagine that registering an already registered event handler will not result in the handler receiving events more than once. Do note that in this case you'll have to take into account the fact that your activity may not be in a state you expect it to be. That is, it will be somewhere inbetween onActivityResult() and onResume().
What you probably want to do is post the event as a runnable. By the time its executed, onStart|onResume where you register your eventbus should be executed.
new Handler().post(new Runnable() {
#Override
public void run() {
BusProvider.getInstance().post(new DataFilledEvent());
}
});