0

I am unable to display firebase items on my Recyclerview. DB connection is fine.

EDIT: I added startListening() method as linked question's answer suggested. But now my app crashes. It looks like this

  @Override
    protected void onStart() {
        super.onStart();

        FirebaseRecyclerOptions<Coupon> options =
                new FirebaseRecyclerOptions.Builder<Coupon>()
                        .setQuery(mDatabase, Coupon.class)
                        .build();

        FirebaseRecyclerAdapter<Coupon, CouponViewHolder> firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<Coupon, CouponsActivity.CouponViewHolder>
                (options) {

            @Override
            protected void onBindViewHolder(@NonNull CouponsActivity.CouponViewHolder holder, int position, @NonNull Coupon model) {

                holder.setTitle(model.getTitle());
                holder.setDesc(model.getDesc());

            }

            @Override
            public CouponsActivity.CouponViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
                View view = LayoutInflater.from(parent.getContext())
                        .inflate(R.layout.item_coupon_row, parent, false);

                return new CouponsActivity.CouponViewHolder(view);
            }
        };

        firebaseRecyclerAdapter.startListening();
        mRecyclerview.setAdapter(firebaseRecyclerAdapter);


    }

    @Override
    protected void onStop() {
        super.onStop();
        firebaseRecyclerAdapter.stopListening();
    }

And crash info in the Logcat: coupons.Coupon is the model.

01-15 15:16:26.381 16526-16526/com.myapp E/AndroidRuntime: FATAL EXCEPTION: main
                                                                          Process: com.myapp, PID: 16526
                                                                          com.google.firebase.database.DatabaseException: Can't convert object of type java.lang.String to type com.myapp.coupons.Coupon
                                                                              at com.google.android.gms.internal.zzelw.zzb(Unknown Source)
                                                                              at com.google.android.gms.internal.zzelw.zza(Unknown Source)
                                                                              at com.google.firebase.database.DataSnapshot.getValue(Unknown Source)
                                                                              at com.firebase.ui.database.ClassSnapshotParser.parseSnapshot(ClassSnapshotParser.java:29)
                                                                              at com.firebase.ui.database.ClassSnapshotParser.parseSnapshot(ClassSnapshotParser.java:15)
                                                                              at com.firebase.ui.common.BaseCachingSnapshotParser.parseSnapshot(BaseCachingSnapshotParser.java:35)
                                                                              at com.firebase.ui.common.BaseObservableSnapshotArray.get(BaseObservableSnapshotArray.java:52)
                                                                              at com.firebase.ui.database.FirebaseRecyclerAdapter.getItem(FirebaseRecyclerAdapter.java:106)
                                                                              at com.firebase.ui.database.FirebaseRecyclerAdapter.onBindViewHolder(FirebaseRecyclerAdapter.java:122)
                                                                              at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:6508)
                                                                              at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:6541)
                                                                              at android.support.v7.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:5484)
                                                                              at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5750)
                                                                              at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5589)
                                                                              at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5585)
                                                                              at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2231)
                                                                              at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1558)
                                                                              at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1518)
                                                                              at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:610)
                                                                              at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3719)
                                                                              at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3436)
                                                                              at android.support.v7.widget.RecyclerView.consumePendingUpdateOperations(RecyclerView.java:1742)
                                                                              at android.support.v7.widget.RecyclerView$1.run(RecyclerView.java:354)
                                                                              at android.view.Choreographer$CallbackRecord.run(Choreographer.java:874)
                                                                              at android.view.Choreographer.doCallbacks(Choreographer.java:686)
                                                                              at android.view.Choreographer.doFrame(Choreographer.java:618)
                                                                              at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:860)
                                                                              at android.os.Handler.handleCallback(Handler.java:751)
                                                                              at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                              at android.os.Looper.loop(Looper.java:154)
                                                                              at android.app.ActivityThread.main(ActivityThread.java:6119)
                                                                              at java.lang.reflect.Method.invoke(Native Method)
                                                                              at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
                                                                              at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

This is my build.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 27
    defaultConfig {
        applicationId "com.myapp"
        minSdkVersion 19
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:27.0.2'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'

    // firebase
    implementation 'com.google.firebase:firebase-core:11.8.0'
    implementation 'com.google.firebase:firebase-database:11.8.0'
    implementation 'com.firebaseui:firebase-ui-database:3.1.3'

    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'

    compile 'com.android.support:cardview-v7:27.0.2'
    compile 'com.android.support:recyclerview-v7:27.0.2'
    compile 'com.android.support:design:27.0.2'

}
apply plugin: 'com.google.gms.google-services'

This is my Activity:

public class CouponsActivity extends AppCompatActivity {
    private DatabaseReference mDatabase;
    private RecyclerView mRecyclerview;


    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_coupons);

        mDatabase = FirebaseDatabase.getInstance().getReference().child("coupon");
        mDatabase.keepSynced(true);

        mRecyclerview = (RecyclerView) findViewById(R.id.coupon_recyclerView_list);
        mRecyclerview.setHasFixedSize(true);
        mRecyclerview.setLayoutManager(new LinearLayoutManager(this));
    }

    @Override
    protected void onStart() {
        super.onStart();


        FirebaseRecyclerOptions<Coupon> options =
                new FirebaseRecyclerOptions.Builder<Coupon>()
                        .setQuery(mDatabase, Coupon.class)
                        .build();

        FirebaseRecyclerAdapter<Coupon, CouponViewHolder> firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<Coupon, CouponsActivity.CouponViewHolder>
                (options) {

            @Override
            protected void onBindViewHolder(@NonNull CouponsActivity.CouponViewHolder holder, int position, @NonNull Coupon model) {

                holder.setTitle(model.getTitle());
                holder.setDesc(model.getDesc());

            }

            @Override
            public CouponsActivity.CouponViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
                View view = LayoutInflater.from(parent.getContext())
                        .inflate(R.layout.item_coupon_row, parent, false);

                return new CouponsActivity.CouponViewHolder(view);
            }
        };

        mRecyclerview.setAdapter(firebaseRecyclerAdapter);

    }

    public static class CouponViewHolder extends RecyclerView.ViewHolder{

        TextView postTitle;
        TextView postDescription;

        public CouponViewHolder(View itemView) {
            super(itemView);
            postTitle = (TextView)itemView.findViewById(R.id.post_title);
            postDescription = (TextView)itemView.findViewById(R.id.post_description);

        }

        public void setTitle(String title) {
            postTitle.setText(title);
        }

        public void setDesc(String desc) {
            postDescription.setText(desc);
        }
    }

}

This is how my Firebase DB looks like

Root
  |
  |__coupon
       |_____title: "This is title"
       |_____desc: "This is description"

This is activity's layout:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.myapp.coupons.CouponsActivity">


    <android.support.v7.widget.RecyclerView
        android:id="@+id/coupon_recyclerView_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/YELLOW">


    </android.support.v7.widget.RecyclerView>

</android.support.constraint.ConstraintLayout>

And this the Card Item layout:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_margin="8dp"
    android:orientation="vertical"
    android:background="@color/GREEN"
    app:cardCornerRadius="5dp"
    android:elevation="90dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">


        <TextView
            android:id="@+id/post_title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="10dp"

            />

        <TextView
            android:id="@+id/post_description"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingBottom="10dp"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            />

    </LinearLayout>


</android.support.v7.widget.CardView>
hullabaloon
  • 654
  • 2
  • 7
  • 17
  • check if the name of fields matches in your DB matches your fields in model class. – jitendra purohit Jan 15 '18 at 11:31
  • Possible duplicate of [Android ListView adapter not pushing individual items for chat app - Firebase-Ui 3.1](https://stackoverflow.com/questions/47228262/android-listview-adapter-not-pushing-individual-items-for-chat-app-firebase-ui) – Peter Haddad Jan 15 '18 at 11:33
  • @PeterHaddad No, It didn't solve. calling startListening() method on my adapter causes app to crash. – hullabaloon Jan 15 '18 at 11:47
  • "causes app to crash" ... There is no crash logs in your question. Please include them – OneCricketeer Jan 15 '18 at 11:53
  • @PeterHaddad They are at the same scope. I am calling startListening() at end of onStart(), after adapter. Do you mean initialising it as a global variable on top of the activity class? – hullabaloon Jan 15 '18 at 12:00
  • @cricket_007 after trying PeterHaddad's suggestion it crashed.. – hullabaloon Jan 15 '18 at 12:02
  • Please [edit] your post to include the new code that is crashing and the logs caused by the crash. We cannot guess why it is now crashing, regardless of where the variable is defined – OneCricketeer Jan 15 '18 at 12:16
  • @cricket_007 I added crash info. – hullabaloon Jan 15 '18 at 12:29
  • @PeterHaddad I updated the question as linked answer causes crash. – hullabaloon Jan 15 '18 at 12:30
  • 1) `firebaseRecyclerAdapter` is out of scope in `onStop`. You have a field and a local variable 2) You need to show us your Firebase JSON export because it says you are getting a string, not a Coupon – OneCricketeer Jan 15 '18 at 12:31

1 Answers1

1

That's because you have a single coupon object stored in your database and not a list.

If you want to create a list of coupons, I recommend adding a node with the key Coupons and store every coupon under it. So your structure would look like this:

Root
  |
  |__Coupons
       |____coupon
               |_____title: "This is title"
               |_____desc: "This is description"

And then your DatabaseReference would look be:

mDatabase = FirebaseDatabase.getInstance().getReference().child("Coupons");
  • 1
    Alternatively: If you're only willing to store coupons in your database and nothing else, then you might need to only change your DatabaseReference to `mDatabase = FirebaseDatabase.getInstance().getReference()` and no need to restructure your database. – Rosário Pereira Fernandes Jan 15 '18 at 12:36