使用FirebaseUI RecyclerAdapter

时间:2017-01-12 14:59:34

标签: android firebase firebase-realtime-database firebaseui

我正在尝试使用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类(它是一个单独的类;因此不需要“static”)。

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'
}

这是我的progaurd规则:

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

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

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

到目前为止,我已经尝试过多次写作而没有运气。

请协助我找到解决方案。

3 个答案:

答案 0 :(得分:1)

您只需要替换

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

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

在你的app level 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

答案 1 :(得分:-1)

看来你的餐厅课是错的。 您必须提供完整的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 Class应该是这样的

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

使用字段

中的字段

答案 2 :(得分:-1)

ViewHolder类需要是public static

公共静态类RestaurantViewHolder扩展了RecyclerView.ViewHolder