0

I am populating a ListView of songs using Firebase database and Firebase-UI, all the dependencies are initialized correctly and the app is connected with the database but when it displays the list it doesn't display the text, just empty boxes like that:

List displayed

When an item is added to the database then a box is added but it doesn't show the text. Here is the code:

Song class:

package com.example.gloriadesideri.animas;

public class Song
{
    private String myName;
    private String myURL;
    private String myAuthor;

    public Song(){
        /*myName="";
        myURL="";
        myAuthor="";*/
    }

    public Song(String Author, String Song, String URL) {
        this.myName=Song;
        this.myURL=URL;
        this.myAuthor=Author;
    }
    public String getName()
    {
        return myName;
    }
    public String getURL()
    {
        return myURL;
    }
    public String getAuthor()
    {
        return myAuthor;
    }
    public void setName(String name)
    {
        this.myName=name;
    }
    public void setURL ( String URL)
    {
        this.myURL=URL;
    }
    public void setAuthor(String author)
    {
        this.myAuthor=author;
    }
}

Song Layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:layout_margin="20dp"
    android:padding="10dp">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/songName"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/author"/>
</LinearLayout>

Activity that should have the list view:

package com.example.gloriadesideri.animas;

import android.content.Intent;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;

import com.firebase.ui.database.FirebaseListAdapter;
import com.firebase.ui.database.FirebaseListOptions;
import com.google.firebase.database.ChildEventListener;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.Query;
import com.google.firebase.database.ValueEventListener;

import java.util.ArrayList;
import java.util.List;

public class Canzoni extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener
{
   //nav view parameters
    private DrawerLayout cDrawerLayout;
    private ActionBarDrawerToggle cToggle;

    //list view parameters
    private ListView mListView;

    //firebase parameters
     private FirebaseListAdapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_canzoni);
        //nav view code
        cDrawerLayout= (DrawerLayout) findViewById(R.id.draw_viewC);
        cToggle= new ActionBarDrawerToggle(this, cDrawerLayout,R.string.Open, R.string.Close);
        cDrawerLayout.addDrawerListener(cToggle);
        cToggle.syncState();


        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null)
            actionBar.setDisplayHomeAsUpEnabled(true);
        NavigationView cNavigationView = (NavigationView) findViewById(R.id.nav_viewC);
        if (cNavigationView != null)
        {
            cNavigationView.setNavigationItemSelectedListener(this);
        }

        Query mQuery= FirebaseDatabase.getInstance().getReference().child("songs");
        mListView= (ListView) findViewById(R.id.canzoni_list);
        FirebaseListOptions<Song>  mOptions= new FirebaseListOptions.Builder<Song>()
                .setLayout(R.layout.song_layout)
                .setQuery(mQuery, Song.class)
                .setLifecycleOwner(this)
                .build();

        mAdapter= new FirebaseListAdapter <Song>(mOptions){
            @Override
            protected void populateView(View v, Song model, int position) {
                TextView songName= v.findViewById(R.id.songName);
                TextView songAuthor=v.findViewById(R.id.author);


                songName.setText(model.getName());
                songAuthor.setText(model.getAuthor());
            }
        };
        mListView.setAdapter(mAdapter);

        }

    @Override
    protected void onStart() {
        super.onStart();
        mAdapter.startListening();
    }

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

    @Override

    public boolean onOptionsItemSelected(MenuItem Item)
    {
        if(cToggle.onOptionsItemSelected(Item))
        {
            return true;
        }
        return super.onOptionsItemSelected(Item);
    }
    @Override
    public boolean onNavigationItemSelected(MenuItem Item)
    {
        int id = Item.getItemId();
        Intent intent;
        if (id == R.id.preghiere)
        {
            intent= new Intent(this, Preghiere.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            this.startActivity(intent);
        }
        else if ( id== R.id.bans)
        {
            intent= new Intent(this, Bans.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            this.startActivity(intent);
        }
        else if (id== R.id.canzoni)
        {
            intent= new Intent(this, this.getClass());
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            this.startActivity(intent);
        }
        else if (id==R.id.calendario)
        {
            intent= new Intent(this, Calendario.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            this.startActivity(intent);
        }
        else if (id== R.id.per_riflettere)
        {
            intent= new Intent(this, perRiflettere.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            this.startActivity(intent);
        }
        else if( id== R.id.home)
        {
            intent= new Intent(this, MainActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            this.startActivity(intent);
        }
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.draw_viewC);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }

}

layout of the above activity

<android.support.v4.widget.DrawerLayout 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=".Canzoni"
    android:id="@+id/draw_viewC">


    <ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/canzoni_list">

    </ListView>

    <android.support.design.widget.NavigationView
        android:layout_width="239dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="@color/white"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/header"
        app:itemIconTint="@color/black"
        app:itemTextColor="@color/black"
        app:menu="@menu/drawem_menu"
        tools:layout_editor_absoluteX="0dp"
        tools:layout_editor_absoluteY="0dp"
        tools:ignore="MissingConstraints"
        android:id="@+id/nav_viewC"/>

</android.support.v4.widget.DrawerLayout>

Any suggestion on how to fix this?

Edit:
the database looks like this:

Database

both writing and reading rules are true

Edit

I have changed the private names in the Song class so they are the same as the database.

private String Author;

private String Song;

private String Url;

it starts working the problem is that now it displays just the author

Update 2

Gloria
  • 43
  • 7
  • 1
    you read data successfully from firebase database.because of i think you make code has some mistake for fetching data from firebase database. –  May 02 '18 at 05:50
  • 1
    yes they are read correctly it is just that they are not displayed and I don't know why. Database rule are both true for writing and reading – Gloria May 02 '18 at 05:55
  • Could you add null checks and add some dummy data if the db returns null – Venky May 02 '18 at 06:04
  • i have code for display data from firebase but it different to your code and also i am using recyclerview .if you want to provide my code. –  May 02 '18 at 06:04
  • @Venky I have adde some funny data, for example a song with just one field in it, it actually displays the new empty box but It doesn't trow any error or exception so this makes me think that is not actually reading any data under the songs. – Gloria May 02 '18 at 06:10
  • @AndroidTeam yes I would like to see your code – Gloria May 02 '18 at 06:10
  • i provide my code. –  May 02 '18 at 06:21

3 Answers3

0

I this code fetch the user data from firebase and show data into recycled view.

In layout i used constaraint layout you can change it..

display_data.xml

<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.v7.widget.RecyclerView
    android:id="@+id/rvData"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

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

<TextView
    android:id="@+id/dlTvEmpty"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="No Found"
    android:textSize="16dp"
    android:visibility="gone"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent" />
 </android.support.constraint.ConstraintLayout>

then after row_layout bind into recycler view..

row_layout.xml

<?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"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp">

<TextView
    android:id="@+id/rlTvName"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Name"
    android:textSize="20dp" />

<TextView
    android:id="@+id/rlTvEmail"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Email"
    android:textSize="20dp"
    app:layout_constraintTop_toBottomOf="@+id/rlTvName" />

<TextView
    android:id="@+id/rlTvPwd"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Password"
    android:textSize="20dp"
    app:layout_constraintTop_toBottomOf="@+id/rlTvEmail" />


 </android.support.constraint.ConstraintLayout>

then after make pojo class for user that insert into firebase..

User.java

public class User {

public String name;
public String email;
public String pwd;
// Default constructor required for calls to
// DataSnapshot.getValue(User.class)
public User() {
}

public User(String name, String email,String pwd) {
    this.name = name;
    this.email = email;
    this.pwd=pwd;
}

}

then after make adapter class.

DisplayAllData.java

public class DisplayAllData extends RecyclerView.Adapter<DisplayAllData.ItemViewHolder> {
private List<User> mUserLsit = new ArrayList<>();
private Context mContext;

@Override
public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_layout, parent, false);
    return new ItemViewHolder(view);
}

public DisplayAllData(Context mContext, List<User> mUserLsit) {
    this.mContext = mContext;
    this.mUserLsit = mUserLsit;
}

@Override
public void onBindViewHolder(ItemViewHolder holder, int position) {
    User user = mUserLsit.get(position);
    holder.mTvName.setText(user.name);
    holder.mTvEmail.setText(user.email);
    holder.mTvPwd.setText(user.pwd);
}

@Override
public int getItemCount() {
    return mUserLsit.size();
}

public class ItemViewHolder extends RecyclerView.ViewHolder {
    TextView mTvName, mTvEmail, mTvPwd;

    public ItemViewHolder(View itemView) {
        super(itemView);
        mTvEmail = itemView.findViewById(R.id.rlTvEmail);
        mTvName = itemView.findViewById(R.id.rlTvName);
        mTvPwd = itemView.findViewById(R.id.rlTvPwd);

    }
}

}

then after finally make display class to fetch user record from firebase and bind into recyclerview.

DisplayActivity.java

public class DisplayActivity extends AppCompatActivity {
private RecyclerView mRvData;
private DisplayAllData allDataAdapter;
private DatabaseReference mDatabase;
private TextView mTvEmpty;
private FirebaseDatabase mFirebaseInstance;
private List<User> mUserList = new ArrayList<>();

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.display_data);
    initView();
}

private void initView() {
    mFirebaseInstance = FirebaseDatabase.getInstance();
    mDatabase = mFirebaseInstance.getReference("usersDb/UserTable");
    mRvData = findViewById(R.id.rvData);
    mTvEmpty = findViewById(R.id.dlTvEmpty);
    mRvData.setLayoutManager(new LinearLayoutManager(this));
    mDatabase.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            mUserList.clear();
            for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
                User user = dataSnapshot1.getValue(User.class);
                mUserList.add(user);
            }
            allDataAdapter = new DisplayAllData(DisplayActivity.this, mUserList);
            mRvData.setAdapter(allDataAdapter);
            allDataAdapter.notifyDataSetChanged();
            if (mUserList.isEmpty())
                mTvEmpty.setVisibility(View.VISIBLE);
            else
                mTvEmpty.setVisibility(View.GONE);
        }


        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });
}

}

  • Just tried but not any better I think I am making mistakes in the database itself or in getting the references – Gloria May 02 '18 at 07:00
  • Above code is working for me also i hope you add internet permission into android manifest file.. you can refer this link for better idea https://www.simplifiedcoding.net/firebase-realtime-database-crud/ –  May 02 '18 at 07:03
0

In your database, you have a property under the name of the song called myAuthor but in the model class, you have the field named Author, both should be the same.

To solve this, you have two solutions. First one would be to delete all the record from your database and add fresh data according to your model class. Make sure that the properties in your database are added using the name od your field that exist in your model class: myName, myURL, myAuthor and NOT Author, Song, Url.

If you are not in testing mode, then just use annotation in your model class like this:

@PropertyName("Song")
private String myName;
@PropertyName("Url")
private String myURL;
@PropertyName("Author")
private String myAuthor;

According to your edited question, you fileds are incorrect. Please how you Song class should look like:

public class Song {
    private String author, song, url;

    public Song() {}

    public Song(String author, String song, String url) {
        this.author = author;
        this.song = song;
        this.url = url;
    }

    public String getAuthor() { return author; }
    public String getSong() { return song; }
    public String getUrl() { return url; }
}

See the fields? Are named with the first letter lower case.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
0

After few experiments with code like change this

songName.setText(model.getName());
songAuthor.setText(model.getAuthor());

to this

songName.setText(model.getURL());
    songAuthor.setText(model.getAuthor());

I have learned that the problem was really the names I gave to the privates and the names I gave to the get-methods in the Song class. The names of the privates should be the same as the database fields and the names of the methods should be getYourPrivateName().

Gloria
  • 43
  • 7