【问题标题】:EventBus - Subscriber class and its super classes have no public methods with the @subscribe annotationEventBus - 订阅者类及其超类没有带有 @subscribe 注释的公共方法
【发布时间】:2016-03-08 17:30:45
【问题描述】:

我正在创建一个使用 EventBus 将异步广播发布到其他类的 Android 应用程序,但我在执行过程中遇到了错误。

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) 

为什么会这样?我是不是做错了什么?

【问题讨论】:

  • 使用 R8 我们有同样的问题

标签: android event-bus greenrobot-eventbus


【解决方案1】:

如果您将 proguard 用于构建,请确保这些行在您的 proguard 配置文件中。

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

【讨论】:

  • 这拯救了我的一天
  • 传说,这是我的问题。
  • 我遇到了同样的问题,让我过得愉快,谢谢
  • 如果生产后出现问题,这就是答案
  • 第二行类后的双**在最近版本的工具中显示语法错误。语法有变化吗?双**到底是什么意思?
【解决方案2】:

我认为这是因为 MapClass.java 中的 onEvent 没有参数。您可以尝试使用预期的参数吗?

【讨论】:

  • 预期的参数是什么?实际上,我不想在 MapClass.java 中收到任何东西
  • 如果你不想在 MapClass.java 中收到任何东西,那你为什么要订阅(注册)?只需删除注册和取消注册,还有 onEvent。
  • 我只想将 LatLng 发送到 MainActivity。我认为即使您想使用 EventBus 发送事件,您也必须注册和取消注册。所以,你的意思是如果我不打算接收任何东西,我不需要注册和注销 EventBus?还有,反过来。只有当我需要接收事件时,我才需要注册和注销 EventBus,对吗?如果我的班级想要两者都做怎么办?如果这些问题看起来很幼稚,我很抱歉;我无法理解 EventBus 的概念。在此先感谢@elsennov! :)
  • 是的,你是对的。关键是“作为订阅者,您必须注册到事件总线以接收事件并在完成后取消注册。但是,如果您是发布者,则不必注册”
【解决方案3】:

我遇到了同样的问题,经过长时间的研究,每个案例都得到了解决方案。此问题是由于您尝试将事件总线注册为的类中缺少 @Subscribe 公共方法 onEvent() EventBus.getDefault().register(this)。如果您使用事件总线注册一个类,则此函数的存在是强制性的

这可能有两种情况

  1. 使用 progruad : progruad 可能会修改 onEvent() 方法的名称,因为事件总线无法找到它。 将这些行放入您的 progruad 规则中

    -keepattributes 注解

    -keepclassmembers 类** {

    @org.greenrobot.eventbus.Subscribe ;

    }

    -保持枚举 org.greenrobot.eventbus.ThreadMode { *;

}

  1. 如果您没有使用 progruard,那么您的类肯定缺少带有 @Subscribe 注释的 onEvent() 方法。对于 EventBus 版本 3.0.0,此方法注释是强制性的,因此请仔细检查您的类中是否存在此方法。

【讨论】:

    【解决方案4】:

    以防万一你的代码和我的一样:p

    我不得不将方法设置为public,因为它目前是private

    【讨论】:

      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

        在我的情况下,我收到了这个错误,因为我没有在我注册 EventBus 的类上写 @Subscribe。

        【讨论】:

          【解决方案7】:

          在我的例子中,onEvent()private 并放置在 child class 中。

          但是register()unregister()父类中被调用。

          解决方案是onEvent()public

          【讨论】:

          • 这里也一样。我有 private 的功能,然后必须使它成为 public 并且这有效。
          【解决方案8】:

          如果您使用 proguard,您将不会在调试模式下遇到此问题。我在发布版本中遇到了这个问题。在 proguard-rules.pro 文件中添加以下代码后,解决了我的问题。

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

          【讨论】:

            【解决方案9】:

            在旁注中,从 EventBus 的 Google's implementation 切换到这个后,我遇到了同样的错误。这个错误让我发疯了,因为 Google 的 EventBus 也有一个 @Subscribe 注释,而我使用的是那个而不是 greenrobot 提供的那个。

            好吧,这对我来说是一个非常愚蠢的错误,但如果我能帮助像我这样的人,我很高兴。

            【讨论】:

            • 这是我的情况。谢谢。
            【解决方案10】:

            可以帮助别人! 我的情况,我忘了在buildTypes下面添加一行

            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

            【讨论】:

              【解决方案11】:

              以防万一它对某人有帮助,在我的情况下,我忘记将参数传递给接收方法,其他一切都很好。 当没有参数传递给接收函数/方法时,会抛出此异常。

              【讨论】:

                【解决方案12】:

                只要从私人娱乐切换到公共娱乐,你就会看到魔法。

                【讨论】:

                  【解决方案13】:

                  从答案更新,因为 proguard 不再是默认值。它变成了R8。关闭 R8 以确保。在颤振中,这将是:

                  flutter build apk --no-shrink ...

                  【讨论】:

                    【解决方案14】:

                    1. 转到导入并删除此行:
                    import com.google.common.eventbus.Subscribe;
                    2. 并添加此行:
                    import org.greenrobot.eventbus.Subscribe;
                    3. 删除 @Subscribe 并重新添加。
                    4. 添加时请确保您使用的是 org.greenrobot .eventbus 导入@Subscribe。

                    【讨论】:

                      【解决方案15】:

                      我使用了来自错误包的订阅注解。

                      应该是 import org.greenrobot.eventbus.Subscribe

                      我正在使用 import com.squareup.otto.Subscribe

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2011-12-08
                        相关资源
                        最近更新 更多