Sruda Sruda - 3 years ago 161
Android Question

RecyclerView doesn't retrieve data from Firebase Datasnapshot

I'm trying to populate a recyclerView from Firebase. Adding items to the database and eventually the recyclerView works fine (I can see it through the console and also through tags on Android monitor). The RV gets populated and inside the listItems I've got two TextViews which should retrieve their text from the database.

My problem is that those two textViews don't appear. I did lots of research and I think my problem is deserialization.

From here I'm adding an item through a fragment:

public void addLanguage(){

//ADDING A LANGUAGE COLOR CAN BE DONE HERE THROUGH AN ARRAY ON MANUALLY

String mUserId= fUser.getUid();
final FirebaseDatabase database= FirebaseDatabase.getInstance();
final DatabaseReference fDatabase= FirebaseDatabase.getInstance().getReference();
//String key= database.getReference("languagesList").push().getKey();
String key= fDatabase.child("user").child(mUserId).child("languagesList").push().getKey();

Languages language= new Languages();
language.setSourceLanguage(sources_edit.getText().toString());
language.setTargetLanguage(target_edit.getText().toString());

Map<String, Object> childUpadate= new HashMap<>();
childUpadate.put(key, language.toFirbaseObject());
fDatabase.child(mUserId).child("languagesList").updateChildren(childUpadate, new DatabaseReference.CompletionListener() {
@Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
if (databaseError == null) {
dismiss();
}else{
Toast.makeText(getActivity(), databaseError.getMessage(), Toast.LENGTH_LONG).show();
}
}
});

}


here's my Activity where the RV is located

public void loadData(){
databaseRef.child(mUserId).child("languagesList").addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
languagesList.clear();

Log.w("langApp", "getUser:onCancelled " + dataSnapshot.toString());
Log.w("langApp", "count = " + String.valueOf(dataSnapshot.getChildrenCount()) + " values " + dataSnapshot.getKey());

for(DataSnapshot data : dataSnapshot.getChildren()){
// GenericTypeIndicator<Map<String, Languages >> languageMap= new GenericTypeIndicator<Map<String, Languages>>(){};
// Map<String, Languages> language= dataSnapshot.getValue(languageMap);
Languages languages= data.getValue(Languages.class);
languagesList.add(languages);
}
adapter.notifyDataSetChanged();
spinKitView.setVisibility(View.GONE);


}

@Override
public void onCancelled(DatabaseError databaseError) {
Log.w("langApp", "getUser:onCancelled", databaseError.toException());

}
});

}


and here is my Object class

public class Languages implements Serializable {

public String sourceLanguage, targetLanguage;

public Languages(){

}

public String getSourceLanguage() {
return sourceLanguage;
}

public void setSourceLanguage(String sourceLanguage) {
this.sourceLanguage = sourceLanguage;
}

public String getTargetLanguage() {
return targetLanguage;
}

public void setTargetLanguage(String targetLanguage) {
this.targetLanguage = targetLanguage;
}

public HashMap<String, String> toFirbaseObject(){
HashMap<String, String> language= new HashMap<String, String>();
language.put("source", sourceLanguage);
language.put("target", targetLanguage);

return language;
}
}


RV adapter which is an inner class inside the activity

public class RecyclerAdapter extends RecyclerView.Adapter{


@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v= LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
RecyclerAdapter.mViewHolder cVH= new mViewHolder(v);

return cVH;
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
mViewHolder mViewHolder= (mViewHolder)holder;
mViewHolder.position= position;
Languages languages= languagesList.get(position);
((mViewHolder) holder).sourceText.setText(languages.getSourceLanguage());
((mViewHolder) holder).targetText.setText(languages.getTargetLanguage());

}

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

public final class mViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{

TextView sourceText, targetText;
public int position;


public mViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);

sourceText= (TextView)itemView.findViewById(R.id.source_language);
targetText= (TextView)itemView.findViewById(R.id.target_language);
}

@Override
public void onClick(View v) {

}
}
}


json

{

{ "kVRxDib8SJdQWRc1TULthqY7S6e2" : {

"languagesList" : {

"-Kv2fKiiV5XAjo6lW9Eg" : {

"source" : "Kejan",
"target" : "Dachn"
},


"-Kv2hoV2eIEMcme6Akje" : {
"source" : "Se",
"target" : "Se"
},

"-Kv2iPJqEn7l6hP4gEzI" : {
"source" : "Ay ",
"target" : "Way"
},


"-Kv38J06mO8o1YudzXXY" : {
"source" : "Aaa",
"target" : "Zdsss"
},


"-Kv38d9b5ihF2sMADk3t" : {
"source" : "Madri ",
"target" : "Algomar"
}


}

}

}


Manifest: `


<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.READ_PROFILE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />

<activity android:name=".Authentication.SignupActivity" />
<activity android:name=".Authentication.ResetPasswordActivity" />
<activity android:name=".Authentication.LoginActivity" />
<activity android:name=".Authentication.ProfileSettings" />
<activity
android:name=".DrawerActivity"
android:label="@string/title_activity_drawer"
android:theme="@style/AppTheme" />
<activity
android:name=".LanguagesActivity"
android:label="@string/title_activity_languages"
android:theme="@style/AppTheme" />
<activity android:name=".Settings" />
<activity android:name=".Authentication.SignupActivityTwo"></activity>
</application>


`

enter image description here

enter image description here

Answer Source

According to Firebase Docs:

This method is used to marshall the data contained in this snapshot into a class of your choosing. The class must fit 2 simple constraints:

  1. The class must have a default constructor that takes no arguments
  2. The class must define public getters for the properties to be assigned. Properties without a public getter will be set to their default value when an instance is deserialized

You also need to name your fields and getters so that they match the JSON property names.

So you should have something like:

    private String source, target;

    public String getSource() { return source; }

    public String getTarget() { return target; }
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download