EventBus - класс подписчика и его суперклассы не имеют общедоступных методов с аннотацией @subscribe

Я создаю приложение для Android с помощью EventBus для публикации асинхронных передач другим классам, но во время выполнения я запускаю ошибку.

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);
        }

    }
}

LogCat показывает следующее:

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) 

Почему это происходит? Я что-то делаю неправильно?

Ответ 1

Я думаю, это потому, что onEvent внутри MapClass.java не имеет параметров. Не могли бы вы попытаться с ожидаемым параметром?

Ответ 2

Пожалуйста, убедитесь, что эти строки находятся в вашем конфигурационном файле proguard, если вы используете proguard для своих сборок.

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

Ответ 3

Я столкнулся с той же проблемой, и после долгого исследования было получено решение для каждого случая. Эта проблема возникает из-за отсутствия общедоступного метода @Subscribe onEvent() внутри класса, который вы пытаетесь зарегистрировать шину событий как   EventBus.getDefault().register(this). Присутствие этой функции является обязательным, если вы зарегистрируете класс с шиной событий

Это может быть в двух ситуациях

  • с помощью progruad: progruad может изменить имя метода onEvent(), из-за которого автобус события не может его найти. Поместите эти строки в свои правила progruad.

    -keepattributes Annotation

    -keepclassmembers class ** {

    @org.greenrobot.eventbus.Subscribe;

    }

    -keep enum org.greenrobot.eventbus.ThreadMode {*;

}

  1. Если вы не используете progruard, то определенно ваш класс не имеет метода onEvent() с аннотацией @Subscribe. Эта аннотация с методом обязательна для EventBus версии 3.0.0, поэтому дважды проверьте наличие этого метода внутри вашего класса.

Ответ 4

В моей ситуации я получил эту ошибку, потому что я не писал @Subscribe в классе, где регистрирую EventBus.

Ответ 5

На всякий случай ваш код похож на мой: p

Мне пришлось установить метод как public, потому что он в настоящее время private.

Ответ 6

ProGuard

ProGuard скрывает имена методов и может удалять методы, которые не называются (удаление мертвого кода). Поскольку методы подписчика не вызываются напрямую, ProGuard предполагает, что они не используются. Поэтому, если вы включите минификацию ProGuard, вы должны указать ProGuard оставить эти методы подписчика.

Используйте следующие правила в файле конфигурации ProGuard (proguard.cfg), чтобы предотвратить удаление подписчиков:

-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

В моем случае onEvent() был закрытым и помещался в дочерний класс.

Но register() и unregister() были вызваны в родительском классе.

Решение было сделать onEvent() публичным.

Ответ 8

На sidenote, я получил ту же ошибку после перехода от реализации EventBus Google к этому. Эта ошибка привела меня в бешенство, потому что Google EventBus также имеет аннотацию @Subscribe, и я использовал ее вместо той, что предоставлена greenrobot.

enter image description here

ОК, это очень глупая ошибка с моей стороны, но если я смогу помочь хотя бы одному человеку, как я, я счастлив.

Ответ 9

Просто если это кому-нибудь поможет, в моем случае я забыл передать аргументы получающему методу, все остальное было в порядке. Когда не передается аргумент получающей функции/методу, в этом случае выдается это исключение.

Ответ 10

Если вы используете proguard, вы не столкнетесь с этой проблемой в режиме отладки. Я столкнулся с этой проблемой в продакшен версии. После добавления этого кода в файлы proguard-rules.pro моя проблема решена.

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