【问题标题】:NoSuchMethodException while using FirebaseUI RecyclerAdapter使用 FirebaseUI RecyclerAdapter 时出现 NoSuchMethodException
【发布时间】:2017-03-21 08:11:38
【问题描述】:

我正在尝试使用 FirebaseUI 及其 recyclerAdapter 在 recyclerView 中显示以下 JSON 结构。

我正在按照我假设的 Firebase 团队所做的示例(在这里和那里进行我自己的更改),在此处找到 Firebase Quickstart - Database

JSON Firebase 结构:

{
    "restaurants": {
        "pushID": {
            "name": "string",
            "address": "string",
            "times": "string",
            "logo": "string",
            "phone": "string",
            "email": "string",
            "order": "true", //Boolean  
            "booking": "true",
            "delivery": "false"
        },
      ...
    }
}

我已经查看了有关在此处和其他站点(例如 GitHub)上接收“NoSuchMethodException”的当前帖子。

一般的答案似乎是有两个可能的原因:

1) 确保您的 viewHolder 类是公开的

2) 如果您的 TaskViewHolder 是一个内部类,例如你的活动,确保它是静态的

这里是相关代码。

型号:

@IgnoreExtraProperties
public class Restaurant {

    public String name, address,
            time, logo, phone;
    public String uid;
    public int favoriteCount = 0;
    public Map<String, Boolean> favorites = new HashMap<>();

    public Restaurant(){
        // Default constructor required for calls to DataSnapshot.getValue(Restaurant.class)
    }

    public Restaurant(String name, String address, String time,
                          String logo, String phone, String uid){
        this.name = name;
        this.address = address;
        this.time = time;
        this.logo = logo;
        this.phone = phone;
        this.uid = uid;
    }

    @Exclude
    public Map<String, Object> toMap() {
        HashMap<String, Object> result = new HashMap<>();
        result.put("uid", uid);
        result.put("name", name);
        result.put("time", time);
        result.put("logo", logo);
        result.put("favoriteCount", favoriteCount);
        result.put("favorites", favorites);

        return result;
    }
}

我的 viewHolder 类(这是一个单独的类;因此不需要“静态”)。

EllipsisUtil.class 是我使用的一种方法,可以将文本视图限制为单行。没什么特别的。

public class RestaurantViewHolder extends RecyclerView.ViewHolder {

public TextView restaurantName, restaurantAddress; //tvDate, tvTime, tvPeople;
public ImageView restaurantImageLogo, restaurantFavorite;
private final Activity activity;
private Locale locale = Locale.US;
//private SimpleDateFormat dateFormat = new SimpleDateFormat("EEEE, MMMM dd yyyy", locale);

public RestaurantViewHolder(Activity activity, View itemView){
    super(itemView);
    this.activity = activity;
    restaurantName = (TextView) itemView.findViewById(R.id.resName);
    restaurantAddress = (TextView) itemView.findViewById(R.id.resAddress);
    restaurantImageLogo = (ImageView) itemView.findViewById(R.id.RestaurantLogo);
    restaurantFavorite = (ImageButton) itemView.findViewById(R.id.rFavorite);
    //additional views for bookings activity
    /*
    tvDate = (TextView) itemView.findViewById(R.id.bookingDate);
    tvTime = (TextView) itemView.findViewById(R.id.bookingTime);
    tvPeople = (TextView) itemView.findViewById(R.id.numberPeople);
    */
}


public void bindToRestaurant(Restaurant restaurant, View.OnClickListener favoriteClickListener) {
    //final int peopleNum = Integer.parseInt(restaurantInfo.booking_people);
    restaurantName.setText(restaurant.name);
    singleLineText(restaurantName);
    restaurantAddress.setText(restaurant.address);
    singleLineText(restaurantAddress);
    restaurantFavorite.setOnClickListener(favoriteClickListener);
    // Create a storage reference from our app
    String dirName = "restaurantLogos/";
    String bucketUrl = "myFirebaseURL/";
    // Initialize Storage
    StorageReference mStorageRef = FirebaseStorage.getInstance().getReference();
    StorageReference storageRef = mStorageRef.getStorage().
            getReferenceFromUrl(bucketUrl+dirName+restaurant.logo+".png");
    String logoUrl = storageRef.getDownloadUrl().toString();
    Glide.with(activity).load(logoUrl).into(restaurantImageLogo);
    //additional views for bookings activity
    /*
    tvDate.setText(dateFormat.format(restaurantInfo.booking_date));
    tvTime.setText(restaurantInfo.booking_time);
    String people;
    if (peopleNum > 1){
        people = restaurantInfo.booking_people+" people";
    }else{
        people = restaurantInfo.booking_people+" person";
    }
    tvPeople.setText(people);
    */
}

public void singleLineText(TextView textView){
    EllipsisUtil ellipsisUtil = new EllipsisUtil(textView);
    ellipsisUtil.singleLineText();
}
}

我处理 Firebase 适配器的活动类

// Set up FirebaseRecyclerAdapter with the Query
    Query restaurantQuery = getQuery(mDatabase);
    mAdapter = new FirebaseRecyclerAdapter<Restaurant, RestaurantViewHolder>(Restaurant.class, R.layout.list_row,
            RestaurantViewHolder.class, restaurantQuery) {

        @Override
        protected void populateViewHolder(final RestaurantViewHolder viewHolder, final Restaurant model, int position) {
            final DatabaseReference restaurantRef = getRef(position);

            final String restaurantKey = restaurantRef.getKey();
            //setting Strings data for intent data passing

            //final String time = model.restaurant_time;
            //final String phone = model.restaurant_phone;

            //Log.d(TAG, "2: "+time+" / "+phone);
            // Set click listener for the whole post view
            viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //starting a new intent from onClick action
                    Context context = v.getContext();
                    //RV = Restaurant View
                    Intent intentRV = new Intent(context, Restaurant.class);
                    intentRV.putExtra("rName", viewHolder.restaurantName.getText().toString());
                    intentRV.putExtra("rAddress", viewHolder.restaurantAddress.getText().toString());
                    //intentRV.putExtra("rTime",time);
                    //intentRV.putExtra("rPhone",phone);
                    //pass RID to next activity
                    intentRV.putExtra("resID", restaurantKey);
                    context.startActivity(intentRV);
                }
            });

            // Determine if the current user has liked this post and set UI accordingly
            if (model.favorites.containsKey(getUid())) {
                viewHolder.restaurantFavorite.setImageResource(R.drawable.ic_favorite_white_24dp);
            } else {
                viewHolder.restaurantFavorite.setImageResource(R.drawable.ic_favorite_border_white_24dp);
            }

            viewHolder.bindToRestaurant(model, new View.OnClickListener() {
                @Override
                public void onClick(View favoriteView) {
                    // Need to write to both places the post is stored
                    DatabaseReference globalRestaurantRef = mDatabase.child("favorites").child(restaurantRef.getKey());
                    DatabaseReference userRestaurantRef = mDatabase.child("user_favorites").child(model.uid).child(restaurantRef.getKey());
                    // Run two transactions
                    onFavoriteClicked(globalRestaurantRef);
                    onFavoriteClicked(userRestaurantRef);
                }
            });
        }
    };
    recyclerView.setAdapter(mAdapter);
}

我的查询方法

public Query getQuery(DatabaseReference databaseReference){
    // All the restaurants
    return databaseReference.child("restaurants");//restaurants
}

我得到的 Logcat 错误:

java.lang.RuntimeException: java.lang.NoSuchMethodException: <init> [class android.view.View]
                                                                               at com.firebase.ui.database.FirebaseRecyclerAdapter.onCreateViewHolder(FirebaseRecyclerAdapter.java:171)
                                                                               at android.support.v7.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:6290)
                                                                               at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5478)
                                                                               at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5363)
                                                                               at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5359)
                                                                               at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2141)
                                                                               at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1525)
                                                                               at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1488)
                                                                               at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:585)
                                                                               at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3506)
                                                                               at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3254)
                                                                               at android.support.v7.widget.RecyclerView.consumePendingUpdateOperations(RecyclerView.java:1623)
                                                                               at android.support.v7.widget.RecyclerView$1.run(RecyclerView.java:331)
                                                                               at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
                                                                               at android.view.Choreographer.doCallbacks(Choreographer.java:580)
                                                                               at android.view.Choreographer.doFrame(Choreographer.java:549)
                                                                               at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
                                                                               at android.os.Handler.handleCallback(Handler.java:739)
                                                                               at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                               at android.os.Looper.loop(Looper.java:135)
                                                                               at android.app.ActivityThread.main(ActivityThread.java:5221)
                                                                               at java.lang.reflect.Method.invoke(Native Method)
                                                                               at java.lang.reflect.Method.invoke(Method.java:372)
                                                                               at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
                                                                               at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
                                                                            Caused by: java.lang.NoSuchMethodException: <init> [class android.view.View]
                                                                               at java.lang.Class.getConstructor(Class.java:531)
                                                                               at java.lang.Class.getConstructor(Class.java:495)
                                                                               at com.firebase.ui.database.FirebaseRecyclerAdapter.onCreateViewHolder(FirebaseRecyclerAdapter.java:168)
                                                                               at android.support.v7.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:6290) 
                                                                               at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5478) 
                                                                               at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5363) 
                                                                               at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5359) 
                                                                               at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2141) 
                                                                               at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1525) 
                                                                               at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1488) 
                                                                               at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:585) 
                                                                               at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3506) 
                                                                               at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3254) 
                                                                               at android.support.v7.widget.RecyclerView.consumePendingUpdateOperations(RecyclerView.java:1623) 
                                                                               at android.support.v7.widget.RecyclerView$1.run(RecyclerView.java:331) 
                                                                               at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767) 
                                                                               at android.view.Choreographer.doCallbacks(Choreographer.java:580) 
                                                                               at android.view.Choreographer.doFrame(Choreographer.java:549) 
                                                                               at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753) 
                                                                               at android.os.Handler.handleCallback(Handler.java:739) 
                                                                               at android.os.Handler.dispatchMessage(Handler.java:95) 
                                                                               at android.os.Looper.loop(Looper.java:135) 
                                                                               at android.app.ActivityThread.main(ActivityThread.java:5221) 
                                                                               at java.lang.reflect.Method.invoke(Native Method) 
                                                                               at java.lang.reflect.Method.invoke(Method.java:372) 
                                                                               at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) 
                                                                               at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694) 

java.lang.RuntimeException: java.lang.NoSuchMethodException: <init> [class android.view.View]
                                                                            at com.firebase.ui.database.FirebaseRecyclerAdapter.onCreateViewHolder(FirebaseRecyclerAdapter.java:171)
                                                                            at android.support.v7.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:6290)
                                                                            at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5478)
                                                                            at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5363)
                                                                            at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5359)
                                                                            at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2141)
                                                                            at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1525)
                                                                            at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1488)
                                                                            at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:585)
                                                                            at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3506)
                                                                            at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3254)
                                                                            at android.support.v7.widget.RecyclerView.consumePendingUpdateOperations(RecyclerView.java:1623)
                                                                            at android.support.v7.widget.RecyclerView$1.run(RecyclerView.java:331)
                                                                            at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
                                                                            at android.view.Choreographer.doCallbacks(Choreographer.java:580)
                                                                            at android.view.Choreographer.doFrame(Choreographer.java:549)
                                                                            at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
                                                                            at android.os.Handler.handleCallback(Handler.java:739)
                                                                            at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                            at android.os.Looper.loop(Looper.java:135)
                                                                            at android.app.ActivityThread.main(ActivityThread.java:5221)
                                                                            at java.lang.reflect.Method.invoke(Native Method)
                                                                            at java.lang.reflect.Method.invoke(Method.java:372)
                                                                            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
                                                                            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
                                                                         Caused by: java.lang.NoSuchMethodException: <init> [class android.view.View]
                                                                            at java.lang.Class.getConstructor(Class.java:531)
                                                                            at java.lang.Class.getConstructor(Class.java:495)
                                                                            at com.firebase.ui.database.FirebaseRecyclerAdapter.onCreateViewHolder(FirebaseRecyclerAdapter.java:168)
                                                                            at android.support.v7.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:6290) 
                                                                            at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5478) 
                                                                            at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5363) 
                                                                            at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5359) 
                                                                            at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2141) 
                                                                            at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1525) 
                                                                            at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1488) 
                                                                            at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:585) 
                                                                            at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3506) 
                                                                            at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3254) 
                                                                            at android.support.v7.widget.RecyclerView.consumePendingUpdateOperations(RecyclerView.java:1623) 
                                                                            at android.support.v7.widget.RecyclerView$1.run(RecyclerView.java:331) 
                                                                            at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767) 
                                                                            at android.view.Choreographer.doCallbacks(Choreographer.java:580) 
                                                                            at android.view.Choreographer.doFrame(Choreographer.java:549) 
                                                                            at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753) 
                                                                            at android.os.Handler.handleCallback(Handler.java:739) 
                                                                            at android.os.Handler.dispatchMessage(Handler.java:95) 
                                                                            at android.os.Looper.loop(Looper.java:135) 
                                                                            at android.app.ActivityThread.main(ActivityThread.java:5221) 
                                                                            at java.lang.reflect.Method.invoke(Native Method) 
                                                                            at java.lang.reflect.Method.invoke(Method.java:372) 
                                                                            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) 
                                                                            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694) 

这是我的主要依赖项:

dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:25.1.0'
compile 'com.android.support:design:25.1.0'
compile 'com.android.support:recyclerview-v7:25.1.0'
compile 'com.github.bumptech.glide:glide:3.7.0'
compile 'com.android.volley:volley:1.0.0'
compile 'com.firebaseui:firebase-ui-database:1.0.0'
compile 'com.google.firebase:firebase-database:10.0.1'
compile 'com.google.firebase:firebase-storage:10.0.1'
compile 'com.google.firebase:firebase-crash:10.0.1'
compile 'com.google.firebase:firebase-auth:10.0.1'
compile 'com.google.firebase:firebase-ads:10.0.1'
compile 'com.google.firebase:firebase-invites:10.0.1'
compile 'com.google.firebase:firebase-core:10.0.1'
compile 'com.android.support:support-v4:25.1.0'
compile 'com.google.firebase:firebase-appindexing:10.0.1'
}

这是我的程序规则:

-keepattributes Signature
-keepattributes *Annotation*
-keepattributes EnclosingMethod
-keepattributes InnerClasses

-keep class package.ViewHolder.** {
    *;
}

-keepclassmembers class package.Models.** {
    *;
}

到目前为止,我已经尝试了好几次都没有运气。

请帮助我找到解决方案。

【问题讨论】:

标签: android firebase firebase-realtime-database firebaseui


【解决方案1】:

你只需要替换

compile 'com.firebaseui:firebase-ui-database:1.0.0'

compile 'com.firebaseui:firebase-ui-database:1.0.1'

在您的应用级 build.gradle 文件中。

您正在使用10.0.1 Firebase/Play 服务版本,它需要1.0.1 FirebaseUI 版本。所以这会解决你的问题。

参考下图:

> FirebaseUI Version    Firebase/Play Services Version
> 1.0.1             10.0.0 or 10.0.1
> 1.0.0             9.8.0
> 0.6.2             9.8.0
> 0.6.1             9.6.1
> 0.6.0             9.6.0
> 0.5.3             9.4.0
> 0.4.4             9.4.0
> 0.4.3             9.2.1
> 0.4.2             9.2.0
> 0.4.1             9.0.2
> 0.4.0             9.0.0

【讨论】:

  • 嗨。我现在就试一试,然后告诉你。
  • @SiyaLab :我不知道为什么这对您的情况不起作用。但就在几天前,我遇到了同样的异常,只是升级我的依赖解决了我的问题。
  • 联系了 Firebase 支持团队,发现这只是一个 bug。不过感谢您的帮助。 :)
  • 误报。好像问题还在继续。 :(
  • @SiyaNM 有什么解决办法吗?
【解决方案2】:

看来你的餐厅课是错误的。 您必须提供完整的 JSON,

餐厅类应该是这样的:

public class Restaurant {
    public PushID pushId;

    //Constructor

    //getter and setters for PushId
    public void setPushId(PushId pushId) {
        this.pushId = pushId;
    }

    public PushId getPushId() {
        return  pushId;
    }
}

PushId 类应该是这样的

public class PushId {

    public String name, address,
            time, logo, phone;
    public String uid;
    public int favoriteCount = 0;
    public Map<String, Boolean> favorites = new HashMap<>();

    public Restaurant() {
    }

    public Restaurant(String name, String address, String time,
                      String logo, String phone, String uid) {
        this.name = name;
        this.address = address;
        this.time = time;
        this.logo = logo;
        this.phone = phone;
        this.uid = uid;
    }

    @Exclude
    public Map<String, Object> toMap() {
        HashMap<String, Object> result = new HashMap<>();
        result.put("uid", uid);
        result.put("name", name);
        result.put("time", time);
        result.put("logo", logo);
        result.put("favoriteCount", favoriteCount);
        result.put("favorites", favorites);

        return result;
    }

在字段中使用字段

【讨论】:

  • 嗨。 PushID 由 firebase 通过 '.push();' 生成方法。我不认为我需要一个 setter 和 getter。我链接到的示例 firebase 数据库项目也没有使用 pushID 的模型。
  • 如果你从 rest api 获取 PushId,那么你需要 PushId
  • 怎么样?请查看 Firebase 开发人员在其 github 项目中提供的 Firebase API 使用示例。我在上面给出了参考。 :)
【解决方案3】:

ViewHolder 类必须是 public static

公共静态类 RestaurantViewHolder 扩展 RecyclerView.ViewHolder

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-30
    • 2012-09-16
    • 2017-11-05
    • 2014-07-02
    • 1970-01-01
    • 2012-09-17
    相关资源
    最近更新 更多