EventBus - Subscriber class and its super classes

2020-05-24 19:45发布

I'm creating an Android application using EventBus for posting asynchronous broadcasts to other classes, but I'm running into an error during execution.

MainActivity.java

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import com.google.android.gms.maps.model.LatLng;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;


public class MainActivity extends AppCompatActivity {

    //Globals
    public String uname = null;
    public double lat = 0;
    public double lng = 0;

    //Get GUI handles
    public Button sendButton; //
    public EditText username;
    public Button MapButton; //
    public EditText LatBox;
    public EditText LngBox;


    protected void onDestroy() {
        super.onDestroy();
        EventBus.getDefault().unregister(this);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        //register EventBus
        EventBus.getDefault().register(this);

        super.onCreate(savedInstanceState);
        //set GUI for MainActivity
        setContentView(R.layout.activity_main);

        //get handlers
        LatBox = (EditText)findViewById(R.id.LatBox);
        LngBox = (EditText)findViewById(R.id.LngBox);

        MapButton = (Button)findViewById(R.id.locationButton);
        //Call the class which will handle finding coordinates
        MapButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent MapIntent = new Intent(getApplicationContext(), MapClass.class);
                startActivityForResult(MapIntent, 0);
            }
        });

        sendButton = (Button)findViewById(R.id.Submit);
        //Set action for Button
        sendButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                //Get username from user
                username  = (EditText)findViewById(R.id.UsernameText);
                uname = username.getText().toString();

                //Generate intent to start IntentService
                Intent i = new Intent(getApplicationContext(), Register.class);

                //Put the extra field of username
                i.putExtra("username", uname);
                i.putExtra("latitude", lat);
                i.putExtra("longitude", lng);
                i.putExtra("type", "meetup.be2015.gcm_meetup.MAIN_ACTIVITY");

                //Start the IntentService on a different thread
                startService(i);
            }
        });

    }


    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onEvent(LatLng currentPos){

        LatBox.setText(String.valueOf(currentPos.latitude));
        LngBox.setText(String.valueOf(currentPos.longitude));

        lat = currentPos.latitude;
        lng = currentPos.longitude;
    }
}

MapClass.java

import android.app.IntentService;
import android.content.Intent;
import android.location.Location;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import com.google.android.gms.appindexing.Action;
import com.google.android.gms.appindexing.AppIndex;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.model.LatLng;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;

public class MapClass extends AppCompatActivity implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {

    private GoogleApiClient mGoogleApiClient;
    private GoogleMap mgoogleMap;
    private LatLng latLng;
    private GoogleApiClient client;

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mgoogleMap = googleMap;
        mgoogleMap.setMyLocationEnabled(true);      //Sets location to current position
        buildGoogleApiClient();
        mGoogleApiClient.connect();
    }

    protected synchronized void buildGoogleApiClient() {
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().unregister(this);
        }
    }

    @Override
    public void onConnected(Bundle bundle) {
        Location MLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
        if (MLastLocation != null) {
            latLng = new LatLng(MLastLocation.getLatitude(), MLastLocation.getLongitude());

            //Post the LatLng to MainActivity
            EventBus.getDefault().post(latLng);

            //Send sticky event to Register and MyGcmListenerService
            EventBus.getDefault().postSticky(latLng);

        } else {
            Log.d("onConnected", "Value of LatLng is NULL");
            latLng = new LatLng(0, 0);   //equator
        }
    }

    @Override
    public void onConnectionSuspended(int i) {
        //Notify
        Log.d("ConnectionSuspended", "Connection Suspended. Status: " +   i);
        mgoogleMap.clear();
        mGoogleApiClient.disconnect();
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        //Notify
        Log.d("ConnectionFailed", "Connection Failed. Status: " + connectionResult.toString());
        mgoogleMap.clear();
        mGoogleApiClient.disconnect();
    }

    @Subscribe
    public void onEvent() {
        Log.d("EVENT", "EVENT");
    }

    @Override
    public void onStart() {
        super.onStart();
        if (!EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().register(this);
        }


    @Override
    public void onStop() {
        super.onStop();
        if (EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().unregister(this);
        }

    }
}

The LogCat shows the following:

03-08 22:54:56.970 8570-8570/meetup.be2015.gcm_meetup E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{meetup.be2015.gcm_meetup/meetup.be2015.gcm_meetup.MapClass}:
org.greenrobot.eventbus.EventBusException: Subscriber class meetup.be2015.gcm_meetup.MapClass 
and its super classes have no public methods with the @Subscribe annotation
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2118)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2143)
at android.app.ActivityThread.access$700(ActivityThread.java:140)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1237)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:174)
at android.app.ActivityThread.main(ActivityThread.java:4952)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1027)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:794)
at dalvik.system.NativeStart.main(Native Method)
Caused by: org.greenrobot.eventbus.EventBusException: Subscriber class meetup.be2015.gcm_meetup.MapClass 
and its super classes have no public methods with the @Subscribe annotation
at org.greenrobot.eventbus.SubscriberMethodFinder.findSubscriberMethods(SubscriberMethodFinder.java:67)
at org.greenrobot.eventbus.EventBus.register(EventBus.java:136)
at meetup.be2015.gcm_meetup.MapClass.onStart(MapClass.java:91)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1178)
at android.app.Activity.performStart(Activity.java:5198)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2091)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2143) 
at android.app.ActivityThread.access$700(ActivityThread.java:140) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1237) 
at android.os.Handler.dispatchMessage(Handler.java:99) 
at android.os.Looper.loop(Looper.java:174) 
at android.app.ActivityThread.main(ActivityThread.java:4952) 
at java.lang.reflect.Method.invokeNative(Native Method) 
at java.lang.reflect.Method.invoke(Method.java:511) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1027) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:794) 
at dalvik.system.NativeStart.main(Native Method) 

Why is this happening? Am I doing something wrong?

12条回答
甜甜的少女心
2楼-- · 2020-05-24 20:24

In my case onEvent() was private and placed in child class.

But register() and unregister() were called in parent class.

Solution was to made onEvent() public.

查看更多
Juvenile、少年°
3楼-- · 2020-05-24 20:24

On a sidenote, I got the same error after switching from Google's implementation of the EventBus to this one. This error drove me crazy, because Google's EventBus also has a @Subscribe annotation and I was using that one instead of the one provided by greenrobot.

enter image description here

OK, it's a very silly error on my part, but if I can help even 1 person like me, I'm happy.

查看更多
地球回转人心会变
4楼-- · 2020-05-24 20:26

If you are using proguard, You will not face this problem in debug mode. I faced this problem in release version. after adding this below code in proguard-rules.pro files, solved my problem.

-keepattributes *Annotation*
-keepclassmembers class ** {
    @org.greenrobot.eventbus.Subscribe <methods>;
 }
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
查看更多
做自己的国王
5楼-- · 2020-05-24 20:35

i think it is because onEvent inside MapClass.java has no parameter. Could you try with the expected parameter?

查看更多
淡お忘
6楼-- · 2020-05-24 20:35

ProGuard

ProGuard obfuscates method names and may remove methods, which are not called (dead code removal). Because Subscriber methods are not directly called, ProGuard assumes them to be unused. So if you enable ProGuard minification, you must tell ProGuard to keep those Subscriber methods.

Use the following rules in your ProGuard configuration file (proguard.cfg) to prevent Subscribers from being removed:

-keepattributes *Annotation*
-keepclassmembers class * {
   @org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }

# Only required if you usenter code heree AsyncExecutor
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
    <init>(java.lang.Throwable);
}
查看更多
霸刀☆藐视天下
7楼-- · 2020-05-24 20:36

I was using Subscribe annotation from wrong package.

It should be import org.greenrobot.eventbus.Subscribe

I was using import com.squareup.otto.Subscribe

查看更多
登录 后发表回答