Weird "Could not dispatch event" and "No subscribers registered for event" issue

android, event-bus

Solution

I was wrong. The warning is about nobody being registered at the time of posting. The actual exception probably has to do with the Activity not being attached when the event runs. You probably want `onAttach()`.

http://developer.android.com/reference/android/app/Fragment.html#onAttach(android.app.Activity)

Still feels like kind of a weird architecture, but it would be false to say none of my apps have weird architectures.

Update:

Let me start over. My original answer said EventBus was crashing because nobody was registered for your event. However, that log statement isn't a crash. It's just a debug. I have found EventBus to be a bit aggressive with that kind of thing, but on the balance it probably helps.

The NullPointerException is different. When `onCreate()` is called on your fragment, it registers to your sticky event. This IMMEDIATELY calls your event. It's right there in the stack. At that point, your fragment is probably attached to your activity, but `onCreateView()` has (probably) not been called, so your TextView doesn't exist. I can't see which line is throwing the exception exactly. See the life cycle:

If you want to use a sticky event, you'll need to register later in the Fragment life cycle. I would guess you want `onCreateView()`/`onDestroyView()`. I've never seen that kind of register/unregister pairing, but it should work.

Generally I think we'd do this with arguments to the fragment, or possibly getting the data from the activity directly, but all methods are fairly clumsy and/or verbose, which is why I'm still an "only when needed" kind of person with the fragments.

An alternative would be to create a Handler in the UI thread and post a Runnable that does the register, which should schedule that after the pending life cycle events, but if you don't need that, don't do it.

Also, you could probably just post/register the `Servico` rather than the `ServicoActual`, but that shouldn't make any difference to your issue.

Problem

I've been trying to debug this thing for hours and I really can't see the issue here. This is my MainActivity. The main thing to look for here is the `ArrayList<Servico>`, being `Servico` a custom object. I've created a simple "event" class - `ServicoActual` - that has just a `Servico` object reference (and a constructor/getter): ``` import android.app.Activity; import android.app.Fragment; import android.app.FragmentManager; import android.app.SearchManager; import android.content.Intent; import android.content.res.Configuration; import android.os.Bundle; import android.support.v4.app.ActionBarDrawerToggle; import android.support.v4.view.GravityCompat; import android.support.v4.widget.DrawerLayout; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import net.pedromoreira.billper.events.ServicoActual; import java.util.ArrayList; import java.util.Locale; import de.greenrobot.event.EventBus; public class MainActivity extends Activity { private DrawerLayout mDrawerLayout; private ListView mDrawerList; private ActionBarDrawerToggle mDrawerToggle; private CharSequence mDrawerTitle; private CharSequence mTitle; private ArrayList<Servico> servicos; //private String[] mPlanetTitles; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); servicos = new ArrayList<Servico>(); servicos.add(new Servico("Luz")); servicos.add(new Servico("Água")); servicos.add(new Servico("Gás")); //Log.i("onCreate", "Servicos: " + servicos.size()); setContentView(R.layout.activity_main); mTitle = mDrawerTitle = getTitle(); //mPlanetTitles = getResources().getStringArray(R.array.planets_array); mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); mDrawerList = (ListView) findViewById(R.id.left_drawer); // set a custom shadow that overlays the main content when the drawer opens mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START); // set up the drawer's list view with items and click listener mDrawerList.setAdapter(new ArrayAdapter<Servico>(this, R.layout.drawer_list_item, servicos)); mDrawerList.setOnItemClickListener(new DrawerItemClickListener()); // enable ActionBar app icon to behave as action to toggle nav drawer getActionBar().setDisplayHomeAsUpEnabled(true); getActionBar().setHomeButtonEnabled(true); // ActionBarDrawerToggle ties together the the proper interactions // between the sliding drawer and the action bar app icon mDrawerToggle = new ActionBarDrawerToggle( this, /* host Activity */ mDrawerLayout, /* DrawerLayout object */ R.drawable.ic_drawer, /* nav drawer image to replace 'Up' caret */ R.string.drawer_open, /* "open drawer" description for accessibility */ R.string.drawer_close /* "close drawer" description for accessibility */ ) { public void onDrawerClosed(View view) { getActionBar().setTitle(mTitle); invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu() } public void onDrawerOpened(View drawerView) { getActionBar().setTitle(mDrawerTitle); invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu() } }; mDrawerLayout.setDrawerListener(mDrawerToggle); if (savedInstanceState == null) { selectItem(0); } } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.main, menu); return super.onCreateOptionsMenu(menu); } /* Called whenever we call invalidateOptionsMenu() */ @Override public boolean onPrepareOptionsMenu(Menu menu) { // If the nav drawer is open, hide action items related to the content view boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList); menu.findItem(R.id.action_websearch).setVisible(!drawerOpen); return super.onPrepareOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { // The action bar home/up action should open or close the drawer. // ActionBarDrawerToggle will take care of this. if (mDrawerToggle.onOptionsItemSelected(item)) { return true; } // Handle action buttons switch(item.getItemId()) { case R.id.action_websearch: // create intent to perform web search for this planet Intent intent = new Intent(Intent.ACTION_WEB_SEARCH); intent.putExtra(SearchManager.QUERY, getActionBar().getTitle()); // catch event that there's no activity to handle intent if (intent.resolveActivity(getPackageManager()) != null) { startActivity(intent); } else { Toast.makeText(this, R.string.app_not_available, Toast.LENGTH_LONG).show(); } return true; default: return super.onOptionsItemSelected(item); } } /* The click listener for ListView in the navigation drawer */ private class DrawerItemClickListener implements ListView.OnItemClickListener { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { selectItem(position); Log.i("DrawerItemClickListener", "Position: " + position); } } private void selectItem(int position) { // update the main content by replacing fragments Fragment fragment = new ServicoFragment(); //Bundle args = new Bundle(); //args.putInt(ServicoFragment.ARG_PLANET_NUMBER, position); //fragment.setArguments(args); FragmentManager fragmentManager = getFragmentManager(); fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit(); Log.i("selectItem", "Servico: " + servicos.get(position).getNome()); EventBus.getDefault().postSticky(new ServicoActual(servicos.get(position))); // update selected item and title, then close the drawer mDrawerList.setItemChecked(position, true); setTitle(servicos.get(position).getNome()); mDrawerLayout.closeDrawer(mDrawerList); } @Override public void setTitle(CharSequence title) { mTitle = title; getActionBar().setTitle(mTitle); } /** * When using the ActionBarDrawerToggle, you must call it during * onPostCreate() and onConfigurationChanged()... */ @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); // Sync the toggle state after onRestoreInstanceState has occurred. mDrawerToggle.syncState(); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); // Pass any configuration change to the drawer toggls mDrawerToggle.onConfigurationChanged(newConfig); } /** * Fragment that appears in the "content_frame" */ public static class ServicoFragment extends Fragment { //public static final String ARG_PLANET_NUMBER = "planet_number"; private TextView mTestText; public ServicoFragment() { // Empty constructor required for fragment subclasses } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EventBus.getDefault().registerSticky(this); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_servico, container, false); //int i = getArguments().getInt(ARG_PLANET_NUMBER); //String planet = getResources().getStringArray(R.array.planets_array)[i]; //int imageId = getResources().getIdentifier(planet.toLowerCase(Locale.getDefault()), // "drawable", getActivity().getPackageName()); //((ImageView) rootView.findViewById(R.id.image)).setImageResource(imageId); //getActivity().setTitle(planet); mTestText = ((TextView) rootView.findViewById(R.id.test_text)); Log.i("onCreateView", "mTestText: " + mTestText.toString()); mTestText.setText("xpto"); return rootView; } public void onEvent(ServicoActual e){ Servico servico = e.getServico(); Log.i("onEvent", "Servico: " + servico.getNome()); getActivity().setTitle(servico.getNome()); mTestText.setText(servico.getNome()); } } } ``` So, when a Drawer list item is clicked, I'm trying to pass the corresponding `Servico` (inside the `ServicoActual` "event") to the `ServicoFragment`, which should write the `Servico`'s name to its `TextView`. This is what happens with a single click on the first item (0): ``` 07-13 00:50:35.388 26244-26244/net.pedromoreira.billper I/ViewRootImpl﹕ ViewRoot's Touch Event : Touch Down 07-13 00:50:35.628 26244-26244/net.pedromoreira.billper I/ViewRootImpl﹕ ViewRoot's Touch Event : Touch UP 07-13 00:50:36.308 26244-26244/net.pedromoreira.billper I/ViewRootImpl﹕ ViewRoot's Touch Event : Touch Down 07-13 00:50:36.358 26244-26244/net.pedromoreira.billper I/ViewRootImpl﹕ ViewRoot's Touch Event : Touch UP 07-13 00:50:36.428 26244-26244/net.pedromoreira.billper I/selectItem﹕ Servico: Luz 07-13 00:50:36.428 26244-26244/net.pedromoreira.billper I/onEvent﹕ Servico: Luz 07-13 00:50:36.458 26244-26244/net.pedromoreira.billper E/Event﹕ Could not dispatch event: class net.pedromoreira.billper.events.ServicoActual to subscribing class class net.pedromoreira.billper.MainActivity$ServicoFragment java.lang.NullPointerException at net.pedromoreira.billper.MainActivity$ServicoFragment.onEvent(MainActivity.java:235) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at de.greenrobot.event.EventBus.invokeSubscriber(EventBus.java:569) at de.greenrobot.event.EventBus.postToSubscription(EventBus.java:500) at de.greenrobot.event.EventBus.postSingleEvent(EventBus.java:475) at de.greenrobot.event.EventBus.post(EventBus.java:365) at de.greenrobot.event.EventBus.postSticky(EventBus.java:406) at net.pedromoreira.billper.MainActivity.selectItem(MainActivity.java:161) at net.pedromoreira.billper.MainActivity.access$300(MainActivity.java:35) at net.pedromoreira.billper.MainActivity$DrawerItemClickListener.onItemClick(MainActivity.java:146) at android.widget.AdapterView.performItemClick(AdapterView.java:299) at android.widget.AbsListView.performItemClick(AbsListView.java:1158) at android.widget.AbsListView$PerformClick.run(AbsListView.java:2957) at android.widget.AbsListView$3.run(AbsListView.java:3849) at android.os.Handler.handleCallback(Handler.java:733) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:136) at android.app.ActivityThread.main(ActivityThread.java:5105) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:792) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:608) at dalvik.system.NativeStart.main(Native Method) 07-13 00:50:36.458 26244-26244/net.pedromoreira.billper I/onEvent﹕ Servico: Luz 07-13 00:50:36.468 26244-26244/net.pedromoreira.billper D/Event﹕ No subscribers registered for event class de.greenrobot.event.SubscriberExceptionEvent 07-13 00:50:36.468 26244-26244/net.pedromoreira.billper I/DrawerItemClickListener﹕ Position: 0 07-13 00:50:36.498 26244-26244/net.pedromoreira.billper I/onEvent﹕ Servico: Luz 07-13 00:50:36.508 26244-26244/net.pedromoreira.billper E/Event﹕ Could not dispatch event: class net.pedromoreira.billper.events.ServicoActual to subscribing class class net.pedromoreira.billper.MainActivity$ServicoFragment java.lang.NullPointerException at net.pedromoreira.billper.MainActivity$ServicoFragment.onEvent(MainActivity.java:236) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at de.greenrobot.event.EventBus.invokeSubscriber(EventBus.java:569) at de.greenrobot.event.EventBus.postToSubscription(EventBus.java:500) at de.greenrobot.event.EventBus.subscribe(EventBus.java:288) at de.greenrobot.event.EventBus.register(EventBus.java:189) at de.greenrobot.event.EventBus.registerSticky(EventBus.java:166) at net.pedromoreira.billper.MainActivity$ServicoFragment.onCreate(MainActivity.java:209) at android.app.Fragment.performCreate(Fragment.java:1688) at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:860) at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1063) at android.app.BackStackRecord.run(BackStackRecord.java:684) at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1450) at android.app.FragmentManagerImpl$1.run(FragmentManager.java:444) at android.os.Handler.handleCallback(Handler.java:733) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:136) at android.app.ActivityThread.main(ActivityThread.java:5105) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:792) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:608) at dalvik.system.NativeStart.main(Native Method) 07-13 00:50:36.508 26244-26244/net.pedromoreira.billper D/Event﹕ No subscribers registered for event class de.greenrobot.event.SubscriberExceptionEvent 07-13 00:50:36.508 26244-26244/net.pedromoreira.billper I/onCreateView﹕ mTestText: android.widget.TextView{429216d0 V.ED.... ......ID 0,0-0,0 #7f090003 app:id/test_text} ``` What can I be doing wrong?

Original source