1

I am trying to display the following JSON structure in a recyclerView using FirebaseUI and its recyclerAdapter.

I am following the example (with my own changes here and there) made by the Firebase team I presume, found here Firebase Quickstart - Database

JSON Firebase structure:

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

I have already looked at the current posts about receiving "NoSuchMethodException" on here and other sites i.e. GitHub.

The general answer seems to be that there are two likely causes for this:

1) make sure that your viewHolder class is public

2) if your TaskViewHolder is an inner class of e.g. your activity, make sure it's static

Here are is the relevant code.

Model:

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

My viewHolder class (which is a separate class; therefore no need for "static").

The EllipsisUtil.class is a method I use keep the text view restricted to a single line. Nothing fancy.

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

My activity class that handles the Firebase adapter

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

My query method

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

The Logcat error I get:

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) 

This is my grandle dependencies:

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

This is my progaurd-rules:

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

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

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

I have tried writing it all several times with no luck thus far.

Please assist me in finding a solution.

AL.
  • 36,815
  • 10
  • 142
  • 281
SiyaNM
  • 13
  • 7
  • Possible duplicate of [What causing this exception java.lang.RuntimeException: java.lang.NoSuchMethodException: \[class android.view.View\]](http://stackoverflow.com/questions/36972335/what-causing-this-exception-java-lang-runtimeexception-java-lang-nosuchmethodex) – Harish Kamboj Jan 23 '17 at 14:57

3 Answers3

1

You just need to replace

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

to

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

in your app level build.gradle file.

You are using the 10.0.1 Firebase/Play Services Version which requires 1.0.1 FirebaseUI Version. So this will solve your problem.

Refer chart below:

> 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
Amit Upadhyay
  • 7,179
  • 4
  • 43
  • 57
-1

It seems your Restaurant class is wrong. You will have to Please provide complete JSON,

Restaurant class should be like this :

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 should be like this

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

The use the field in fields

kanduken
  • 86
  • 1
  • 9
  • Hi. PushID is generated by firebase by '.push();' method. I do not think I need a setter and getter for that. The example firebase database project that I linked to also does not use a model for the pushID. – SiyaNM Jan 12 '17 at 15:38
  • if you are getting, PushId from rest api, then you'll need the PushId – kanduken Jan 12 '17 at 15:47
  • How so? Please look through the example use of the Firebase API given by the developers of Firebase in their github project. I gave reference to it above. :) – SiyaNM Jan 12 '17 at 15:57
-1

ViewHolder classes need to be public static

public static class RestaurantViewHolder extends RecyclerView.ViewHolder