How to fill the RecyclerView with nested object from firebase - java

This is the event object that I want to inflate with RecyclerView:
public class Event {
private String mName;
private String mId;
private String mDate;
private String mPlace;
private User mUser;
private Category mCat;
private String mDescription;
public void setmEventCat(Map<String, Category> mEventCat) {
this.mEventCat = mEventCat;
}
public Map<String, Category> getmEventCat() {
return mEventCat;
}
private Map<String,Category> mEventCat;
public String getmDescription() {
return mDescription;
}
public void setDescription(String mDescription) {
this.mDescription = mDescription;
}
public Category getCat() {
return mCat;
}
public void setCat(Category mCat) {
this.mCat = mCat;
}
public String getDate() {
return mDate;
}
public String getPlace() {
return mPlace;
}
private ArrayList<User> mList;
public Event() {
}
public String getName() {
return mName;
}
public void setName(String mName) {
this.mName = mName;
}
public void setDate(String mDate) {
this.mDate = mDate;
}
public void setPlace(String mPlace) {
this.mPlace = mPlace;
}
public String getId() {
return mId;
}
public void setId(String mId) {
this.mId = mId;
}
}
The nested Category object:
public class Category implements Serializable{
private String mCatName;
private String mCatID;
public Category() {
}
public Category(String mCatName) {
this.mCatName = mCatName;
}
public String getCatName() {
return mCatName;
}
public String getCatID() {
return mCatID;
}
public void setCatName(String mCatName) {
this.mCatName = mCatName;
}
public void setCatID(String mCatID) {
this.mCatID = mCatID;
}
}
How I retrieve the data from firebase:
mDataBase = FirebaseDatabase.getInstance().getReference("Event");
mEvents = new ArrayList<Event>();
mEvent=new Event();
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);
mDataBase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot != null && dataSnapshot.getValue() != null) {
try {
for (DataSnapshot eventSnapshot : dataSnapshot.getChildren()) {
Event event = eventSnapshot.getValue(Event.class);
String id = eventSnapshot.getKey();
mEvents.add(event);
mRecyclerView.scrollToPosition(mEvents.size() - 1);
mAdapter.notifyItemInserted(mEvents.size() - 1);
}
}
catch (Exception ex) {
Log.e("ERROR", ex.getMessage());
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
mAdapter = new EventAdapter(mContext, mEvents);
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.setLayoutManager(new LinearLayoutManager(mContext));
My EventAdapter:
#Override
public void onBindViewHolder(EventAdapter.ViewHolder holder, int position) {
mEvent = mEvents.get(position);
holder.mEventName.setText(mEvent.getName());
//Every time I tried to add this line to set category name
//the NullPointerException error occurs
holder.mEventCategory.setText(mEvent.getCat().getCatName());
holder.mEventDate.setText(mEvent.getDate());
}
The ViewHolder Class:
public class ViewHolder extends RecyclerView.ViewHolder {
private TextView mEventName, mEventDate,mEventCategory;
public ViewHolder(View itemView) {
super(itemView);
mEventName = itemView.findViewById(R.id.eventName_tv);
mEventDate = itemView.findViewById(R.id.date_tv);
mEventCategory = itemView.findViewById(R.id.categoryTv);
}
}
#Override
public EventAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.search_event, parent, false);
return new ViewHolder(view);
}
The problem is the Event is displayed as I expected, but I cannot get the category inside the event and bind it to my widget by simply calling the getCat(). I know this may caused by asynchronous Firebase API. How can I set up the TextView with the nested category object.
This is my FINAL piece of my application, any hints would be a great help.
Thanks in advance!

I figure out the question that may be useful for other people. Before adding the event object to the list, I retrieve the nested object by key and assign it to category object. Finally, linking it with event...
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot != null && dataSnapshot.getValue() != null) {
try {
for (DataSnapshot eventSnapshot : dataSnapshot.getChildren()) {
Event event = eventSnapshot.getValue(Event.class);
String id = eventSnapshot.getKey();
mCategory = eventSnapshot.child(id).getValue(Category.class);
event.setCat(mCategory);
mEvents.add(event);
mRecyclerView.scrollToPosition(mEvents.size() - 1);
mAdapter.notifyItemInserted(mEvents.size() - 1);
}
}
catch (Exception ex) {
Log.e("ERROR", ex.getMessage());
}
}
}
Then binding the desired data with widget by calling the pojo getter method (nothing's changed here).
#Override
public void onBindViewHolder(EventAdapter.ViewHolder holder, int position) {
mEvent = mEvents.get(position);
holder.mEventName.setText(mEvent.getName());
holder.mEventCategory.setText(mEvent.getCat().getCatName());
holder.mEventDate.setText(mEvent.getDate());
}

Related

Failing to receive data when making call to an API with retrofit2

I'm making a simple app that has to make a call to an API that returns an object with some attributes and is shown in a RecyclerView.
The call is being made to https://jsonplaceholder.typicode.com/photos?_start=0&_limit=5
The app doesn't crash, the recyclerview is being generated but it is empty. I used the debugger and saw that the list in the adapter of the recyclerview is empty (the size is 0).
I believe the issue is with the structure of the java objects I made but I can't confirm it for sure and I can't seem to modify my object structure to match that of the returned object. I'm not seeing an object with other objects inside of like with other apis I've worked on (when I check the above link with a json online reader).
I usually make my object and another object container (which has a list of the first object). My suspicion is that the issue is there, please help me find the problem.
Below the main activity, object, object container, adapter, retrofit object, object dao and object controller.
Activity:
public class PhotoActivity extends AppCompatActivity implements AdapterPhotoRecyclerView.SelectedPhotoListener {
private AdapterPhotoRecyclerView adapterPhotoRecyclerView;
private RecyclerView recyclerView;
private ProgressBar progressBar;
private LinearLayoutManager linearLayoutManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_photo);
linearLayoutManager = new LinearLayoutManager(this, RecyclerView.VERTICAL, false);
progressBar = findViewById(R.id.photo_activity_progress_bar);
makeCall("photos?_start=0&_limit=5");
adapterPhotoRecyclerView = new AdapterPhotoRecyclerView(this);
recyclerView = findViewById(R.id.photo_activity_recyclerview);
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setAdapter(adapterPhotoRecyclerView);
}
public void makeCall(String fixedUrl) {
MyPhotoController myPhotoController = new MyPhotoController();
myPhotoController.getPhotos(fixedUrl, new ResultListener<MyPhotoContainer>() {
#Override
public void finish(MyPhotoContainer result) {
progressBar.setVisibility(View.VISIBLE);
adapterPhotoRecyclerView.setMyPhotoList(result.getmPhotoList());
progressBar.setVisibility(View.GONE);
}
});
}
#Override
public void selectePhoto(Integer position, List<MyPhoto> myPhotoList) {
MyPhoto clickedPhoto = myPhotoList.get(position);
Toast.makeText(this, clickedPhoto.getTitle(), Toast.LENGTH_SHORT).show();
}
}
Adapter of the RecyclerView
public class AdapterPhotoRecyclerView extends RecyclerView.Adapter<AdapterPhotoRecyclerView.PhotoViewHolder> {
private List<MyPhoto> myPhotoList;
private SelectedPhotoListener selectedPhotoListener;
public AdapterPhotoRecyclerView(SelectedPhotoListener selectedPhotoListener) {
myPhotoList = new ArrayList<>();
this.selectedPhotoListener = selectedPhotoListener;
}
public void setMyPhotoList(List<MyPhoto> myPhotoList) {
this.myPhotoList = myPhotoList;
notifyDataSetChanged();
}
public List<MyPhoto> getMyPhotoList() {
return myPhotoList;
}
#NonNull
#Override
public PhotoViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_cell_photo, parent, false);
PhotoViewHolder photoViewHolder = new PhotoViewHolder(view);
return photoViewHolder;
}
#Override
public void onBindViewHolder(#NonNull PhotoViewHolder holder, int position) {
MyPhoto myPhoto = myPhotoList.get(position);
holder.bindPhoto(myPhoto);
}
#Override
public int getItemCount() {
if (myPhotoList == null){
return 0;
} else {
return myPhotoList.size();
}
}
public class PhotoViewHolder extends RecyclerView.ViewHolder {
private ImageView thumbnail;
private TextView title;
public PhotoViewHolder(#NonNull View itemView) {
super(itemView);
this.thumbnail = itemView.findViewById(R.id.recyclerview_cell_photo_thumbnail);
this.title = itemView.findViewById(R.id.recyclerview_cell_photo_title);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
selectedPhotoListener.selectePhoto(getAdapterPosition(), myPhotoList);
}
});
}
public void bindPhoto(MyPhoto myPhoto) {
Glide.with(itemView).load(myPhoto.getThumbnailUrl()).placeholder(R.mipmap.ic_launcher).into(thumbnail);
title.setText(myPhoto.getTitle());
}
}
public interface SelectedPhotoListener {
public void selectePhoto(Integer position, List<MyPhoto> myPhotoList);
}
}
Object dao
public class MyPhotoDao extends MyRetrofit {
private JsonPlaceholderService service;
public MyPhotoDao() {
super("https://jsonplaceholder.typicode.com/");
service = retrofit.create(JsonPlaceholderService.class);
}
public void getPhotos(String fixedUrl, final ResultListener<MyPhotoContainer> listenerOfTheController) {
Call<MyPhotoContainer> call = service.jsonPlaceholderPhoto(fixedUrl);
call.enqueue(new Callback<MyPhotoContainer>() {
#Override
public void onResponse(Call<MyPhotoContainer> call, Response<MyPhotoContainer> response) {
MyPhotoContainer myPhotoContainer = response.body();
listenerOfTheController.finish(myPhotoContainer);
}
#Override
public void onFailure(Call<MyPhotoContainer> call, Throwable t) {
}
});
}
public void getAlbum(String fixedUrl, final ResultListener<List<Album>> listenerOfTheController){
Call<List<Album>> call = service.jsonPlaceholderAlbum(fixedUrl);
call.enqueue(new Callback<List<Album>>() {
#Override
public void onResponse(Call<List<Album>> call, Response<List<Album>> response) {
List<Album> albumList = response.body();
listenerOfTheController.finish(albumList);
}
#Override
public void onFailure(Call<List<Album>> call, Throwable t) {
}
});
}
}
Object controller
public class MyPhotoController {
public void getPhotos(String fixedUrl, final ResultListener<MyPhotoContainer> listenerOfTheView) {
MyPhotoDao myPhotoDao = new MyPhotoDao();
myPhotoDao.getPhotos(fixedUrl, new ResultListener<MyPhotoContainer>() {
#Override
public void finish(MyPhotoContainer result) {
listenerOfTheView.finish(result);
}
});
}
public void getAlbums(String fixedUrl, final ResultListener<List<Album>> listenerOfTheView){
MyPhotoDao myPhotoDao = new MyPhotoDao();
myPhotoDao.getAlbum(fixedUrl, new ResultListener<List<Album>>() {
#Override
public void finish(List<Album> result) {
listenerOfTheView.finish(result);
}
});
}
}
Retrofit object
public abstract class MyRetrofit {
protected Retrofit retrofit;
public MyRetrofit(String baseUrl) {
OkHttpClient.Builder okHttpClient = new OkHttpClient.Builder();
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl(baseUrl)
.client(okHttpClient.build())
.addConverterFactory(GsonConverterFactory.create());
retrofit = builder.build();
}
}
Object I'm trying to GET
public class MyPhoto implements Serializable {
#SerializedName("AlbumId")
private Integer albumNumber;
#SerializedName("id")
private Integer photoId;
private String title;
#SerializedName("url")
private String photoUrl;
private String thumbnailUrl;
public Integer getAlbumNumber() {
return albumNumber;
}
public Integer getPhotoId() {
return photoId;
}
public String getTitle() {
return title;
}
public String getPhotoUrl() {
return photoUrl;
}
public String getThumbnailUrl() {
return thumbnailUrl;
}
}
Object container
public class MyPhotoContainer implements Serializable {
#SerializedName("array")
private List<MyPhoto> mPhotoList;
public List<MyPhoto> getmPhotoList() {
return mPhotoList;
}
}
If there is anything missing please let me know.
Any help and comments are apreciated!
JSON payload does not fit to POJO classes. You do not need to use MyPhotoContainer class at all. Response JSON is a JSON Array with directly placed JSON Objects. getPhotos method should look similar to getAlbum method. Try:
public void getPhotos(String fixedUrl, final ResultListener<List<MyPhoto>> listenerOfTheView)

In paging library, PagedList value is null

I have tried to implement a user list with pagination using paging library. But despite being able to fetch all data from back-end, the PagedList is null while observing LiveData.
Here are the codes.
UserModel.java
class User{
#SerializedName("user_id")
public int user_id;
#SerializedName("username")
public String username;
#SerializedName("name")
public String name;
#SerializedName("familyname")
public String familyname;
#SerializedName("pp_dir")
public String pp_url; }
public class UserModel {
#SerializedName("users")
public List<User> list;
#SerializedName("last_page")
public boolean lastPage;
#SerializedName("total_page")
public int totalPage;
#SerializedName("total_user_count")
public int totalUserCount;}
UserSearchDataSource.java
public class UserSearchDataSource extends ItemKeyedDataSource<Integer, User> {
public static final int PAGE_SIZE = 15;
private static final int FIRST_PAGE = 1;
#Override
public void loadInitial(#NonNull LoadInitialParams<Integer> params, #NonNull LoadInitialCallback<User> callback) {
RetrofitClient.getInstance().getApi().getAllUsers(FIRST_PAGE, PAGE_SIZE).enqueue(new Callback<UserModel>() {
#Override
public void onResponse(Call<UserModel> call, Response<UserModel> response) {
if (response.body() != null) {
callback.onResult(response.body().list);
System.out.println(response.body().list);
}
else {
System.out.println(response.code());
System.out.println(response.message());
}
}
#Override
public void onFailure(Call<UserModel> call, Throwable t) {
System.out.println(t.getMessage());
}
});
}
#Override
public void loadAfter(#NonNull LoadParams<Integer> params, #NonNull LoadCallback<User> callback) {
RetrofitClient.getInstance().getApi().getAllUsers(FIRST_PAGE, PAGE_SIZE).enqueue(new Callback<UserModel>() {
#Override
public void onResponse(Call<UserModel> call, Response<UserModel> response) {
if (response.body() != null) {
//Integer key = response.body().lastPage ? null : params.key + 1;
callback.onResult(response.body().list);
}
}
#Override
public void onFailure(Call<UserModel> call, Throwable t) {
}
});
}
#Override
public void loadBefore(#NonNull LoadParams<Integer> params, #NonNull LoadCallback<User> callback) {
RetrofitClient.getInstance().getApi().getAllUsers(FIRST_PAGE, PAGE_SIZE).enqueue(new Callback<UserModel>() {
#Override
public void onResponse(Call<UserModel> call, Response<UserModel> response) {
if (response.body() != null) {
//Integer key = (params.key > 1) ? params.key - 1 : null;
callback.onResult(response.body().list);
}
else {
System.out.println(response.message());
}
}
#Override
public void onFailure(Call<UserModel> call, Throwable t) {
System.out.println(t.getMessage());
}
});
}
#NonNull
#Override
public Integer getKey(#NonNull User item) {
return item.user_id;
} }
UserSearchDataSourceFactory.java
public class UserSearchDataSourceFactory extends DataSource.Factory<Integer, User> {
private MutableLiveData<UserSearchDataSource> userLiveDataSource = new MutableLiveData<>();
public UserSearchDataSourceFactory() {
}
#NonNull
#Override
public DataSource<Integer, User> create() {
UserSearchDataSource dataSource = new UserSearchDataSource();
userLiveDataSource.postValue(dataSource);
return dataSource;
}
public MutableLiveData<UserSearchDataSource> getUserLiveDataSource() {
return userLiveDataSource;
} }
UserSearchAdapter.java
public class UserSearchAdapter extends PagedListAdapter<User, UserSearchAdapter.ViewHolder> {
private Context context;
UserSearchAdapter(Context context) {
super(DIFF_CALLBACK);
this.context = context;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.user_item, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
User model = getItem(position);
if (model != null) {
Picasso.get().load(model.pp_url).into(holder.userPp);
holder.tvUsername.setText(model.username);
holder.tvFullname.setText(model.name.concat(" ").concat(model.familyname));
}
else {
Toast.makeText(context, "Item is null", Toast.LENGTH_LONG).show();
}
}
private static DiffUtil.ItemCallback<User> DIFF_CALLBACK = new DiffUtil.ItemCallback<User>() {
#Override
public boolean areItemsTheSame(#NonNull User oldItem, #NonNull User newItem) {
return oldItem.user_id == newItem.user_id;
}
#SuppressLint("DiffUtilEquals")
#Override
public boolean areContentsTheSame(#NonNull User oldItem, #NonNull User newItem) {
return oldItem.equals(newItem);
}
};
public class ViewHolder extends RecyclerView.ViewHolder {
ImageView userPp;
TextView tvUsername, tvFullname;
public ViewHolder(#NonNull View itemView) {
super(itemView);
userPp = itemView.findViewById(R.id.image_user);
tvUsername = itemView.findViewById(R.id.tv_username);
tvFullname = itemView.findViewById(R.id.tv_fullname);
}
} }
UserSearchViewModel.java
public class UserSearchViewModel extends AndroidViewModel {
private LiveData<PagedList<User>> userPagedList;
LiveData<UserSearchDataSource> liveDataSource;
public UserSearchViewModel(Application application) {
super(application);
}
public LiveData<PagedList<User>> getUserPagedList() {
UserSearchDataSourceFactory userSearchDataSourceFactory = new UserSearchDataSourceFactory();
liveDataSource = userSearchDataSourceFactory.getUserLiveDataSource();
PagedList.Config config = (new PagedList.Config.Builder())
.setEnablePlaceholders(true)
.setPageSize(UserSearchDataSource.PAGE_SIZE)
.build();
userPagedList = new LivePagedListBuilder<>(userSearchDataSourceFactory, config).build();
return userPagedList;
} }
UserSearchFragment.java
mViewModel.getUserPagedList().observe(this, (PagedList<User> users) -> {
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setHasFixedSize(true);
adapter = new UserSearchAdapter(getContext());
adapter.submitList(users);
recyclerView.setAdapter(adapter);
//System.out.println(users.get(0).name);
});

Why I can't get some data from Firebase when I use dataSnapshot

I struggle to get data from Firebase for Android.
Please see my code.
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
Logger.log("onChildAdded:" + previousChildName);
// Logger.log( dataSnapshot.child("topicid").getValue(String.class));
//dataSnapshot.child("topicid").getValue();
mComment = new ArticleComment();
mComment = dataSnapshot.getValue(ArticleComment.class);
}
Here is ArticleComment class
public class ArticleComment {
private Date mCommentTime;
private String mComment;
private String mUID;
private String mName;
private int mColorRed;
private int mColorGreen;
private int mColorBlue;
public ArticleComment(){
}
public ArticleComment(Date time, String comment,String name,String uid,int[] color){
this.mCommentTime = time;
this.mComment = comment;
this.mName = name;
this.mUID = uid;
this.mColorRed=color[0];
this.mColorGreen=color[1];
this.mColorBlue=color[2];
}
public Date getTime(){
return mCommentTime;
}
public void setTime(Date time){
mCommentTime =time;
}
public String getComment(){
return mComment;
}
public void setComment(String comment){
mComment =comment;
}
public String getName(){
return mName;
}
public void setName(String name){
mName=name;
}
public String getUID(){
return mUID;
}
public void setUID(String uid){
mUID=uid;
}
public int getColorRed(){
return mColorRed;
}
public int getColorGreen(){
return mColorGreen;
}
public int getColorBlue(){
return mColorBlue;
}
public void setColor(int red,int green, int blue)
{
mColorRed=red;
mColorGreen=green;
mColorBlue=blue;
}
#Exclude
public Map<String, Object> toMap(){
HashMap<String, Object> hashmap = new HashMap<>();
hashmap.put("time", mCommentTime);
hashmap.put("UID", mUID);
hashmap.put("name", mName);
hashmap.put("comment", mComment);
hashmap.put("colorRed", mColorRed);
hashmap.put("colorBlue", mColorBlue);
hashmap.put("colorGreen", mColorGreen);
return hashmap;
}
}
And here is my DB information.
I could get only
mCommentTime;
mComment;
mName;
But I can't get
mUID;
mColorRed;
mColorGreen;
mColorBlue;
Is there something wrong with my code?
Actually datasnapshot has data but it didn't copy to mComment
Hi! Thank you, friends, gave me feedback here is all code.
public class CommentsActivity extends AppCompatActivity {
private DatabaseReference myRef;
private DatabaseReference mTopicRef;
private RecyclerView mRecyclerView;
private RecyclerArticleAdapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
private List<ArticleComment> myDataset = new ArrayList<ArticleComment>();
private ArticleComment mComment;
private Topic mTopic;
private EditText mTitleEditText;
private String mUserName;
private String mUid;
private int mRedColor=100;
private int mBlueColor=100;
private int mGreenolor=100;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_comments);
//Add action button
Intent intent =getIntent();
String id = intent.getStringExtra("ID");
String date = intent.getStringExtra("Date");
String title = intent.getStringExtra("Title");
String topic = intent.getStringExtra("Topic");
mUserName = intent.getStringExtra("UserName");
mUid = intent.getStringExtra("UID");
SharedPreferences pref=PreferenceManager.getDefaultSharedPreferences(this);
mRedColor= pref.getInt("ColorRed",255);
mGreenolor=pref.getInt("ColorGreen",255);
mBlueColor=pref.getInt("ColorBlue",255);
mRecyclerView = findViewById(R.id.recyclerView_article);
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
//Reference DB
FirebaseDatabase database = FirebaseDatabase.getInstance();
myRef = database.getReference("Main").child("Comments").child(id);
mTopicRef = database.getReference("Main").child("Topics").child(id);
List<String> topicinfo=new ArrayList<String >();
topicinfo.add(date);
topicinfo.add(title);
topicinfo.add(topic);
// Set TestAdapter as the adapter for RecyclerView.
mRecyclerView.setAdapter(mAdapter);
mAdapter = new RecyclerArticleAdapter(myDataset,topicinfo){
/* #Override
protected void onCheckedChangedRecycle(CompoundButton comButton, final boolean isChecked){
mTopicRef.runTransaction(new Transaction.Handler() {
#Override
public Transaction.Result doTransaction(MutableData mutableData) {
Topic t = mutableData.getValue(Topic.class);
String id = mutableData.child("topicid").getValue(String.class);
t.setTopicID(id);
if (t == null) {
return Transaction.success(mutableData);
}
if (isChecked==true) {
// Unstar the post and remove self from stars
t.setRate(t.getRate()+1);
} else {
// Star the post and add self to stars
t.setRate(t.getRate()-1);
}
// Set value and report transaction success
mutableData.setValue(t);
return Transaction.success(mutableData);
}
#Override
public void onComplete(DatabaseError databaseError, boolean b,
DataSnapshot dataSnapshot) {
// Transaction completed
}
});
} */
};
mRecyclerView.setAdapter(mAdapter);
findViewById(R.id.button2).setOnClickListener(button1ClickListener);
mTitleEditText = findViewById(R.id.editText2);
ChildEventListener childEventListener = new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
mComment = new ArticleComment();
mComment = dataSnapshot.getValue(ArticleComment.class);
Logger.log("onChildAdded:addItem" + previousChildName);
mAdapter.addItem(mAdapter.getItemCount()-1, mComment);
Logger.log("onChildAdded:scrollToPosition" + previousChildName);
mAdapter.updateItem(mAdapter.getItemCount()-1,mComment);
mLayoutManager.scrollToPosition(mAdapter.getItemCount()-1);
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String previousChildName) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String previousChildName) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
};
myRef.addChildEventListener(childEventListener);
}
View.OnClickListener button1ClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
// finish();
Logger.log("onClick");
if(mTitleEditText.getText().toString().equals("")){
return;
}
//setting color
int color[]=new int[3];
color[0]= mRedColor;
color[1]=mGreenolor;
color[2]=mBlueColor;
mComment = new ArticleComment(new Date(),mTitleEditText.getText().toString(),mUserName,mUid,color);
sendTopic(mComment,myRef);
//Delete all text
mTitleEditText.setText("");
}
};
// Sending topic to DB
public void sendTopic(ArticleComment test,DatabaseReference ref) {
String key = ref.push().getKey();
Map<String, Object> map = new HashMap<>();
map.put(key, test.toMap());
ref.updateChildren(map);
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
finish();
return true;
}
return true;
}
Is it enough information?
Firebase follows JavaBean naming conventions to determine the name of the JSON property from the Java code. And in that convention getUID and setUID map to a property uID with a lowercase u.
To make the Firebase client adopt your naming convention, annotate the getter and setter with a #PropertyName:
#PropertyName("UID")
public String getUID(){
return mUID;
}
#PropertyName("UID")
public void setUID(String uid){
mUID=uid;
}
I'm not immediately sure why the other properties don't work. When this happens, I find it most useful to write an object of the type of Firebase, to see what it generates.
**
If you want to store values in a model .Then your variable name should
be same as Firebase node or else you need to typeConvert it .
**
private Date mCommentTime;
private String mComment;
private String mUID;
private String mName;
private int mColorRed;
private int mColorGreen;
private int mColorBlue;
Replace above with
private int time;
private String comment;
private String UID;
private String name;
private int colorRed;
private int colorBlue;
private int colorGreen;
now make getters,setters,constructor etc. using above nodes. (Now you will be able to get all the values ) .
Hope its gonna help you :)

How to display a variable 'name' and 'value' of firebase database in a RecyclerView

Fetching Data:
private void fetchResults() {
mDatabaseReference.child("Users").child(id).child("Quiz").child("Results").child(id).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot resultSnapshot: dataSnapshot.getChildren()) {
String user = resultSnapshot.getKey();
String score = resultSnapshot.getValue(String.class);
Results results = new Results(user, score);
resultsList.add(results);
}
mAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
});
}
Saving Data:
String name = RecieversName;
HashMap<String, String> userMap = new HashMap<>();
userMap.put(name, String.valueOf(mScore));
mRef.child("Users").child(RecieversId).child("Quiz").child("Results").child(UID).setValue(userMap).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Intent intent = new Intent(TakingQuiz.this, TakingQuizDone.class);
intent.putExtra("RecieversId",RecieversId);
intent.putExtra("Score", mScore.toString());
startActivity(intent);
finish();
}
}
});
Adapter:
public class AdapterQuiz extends RecyclerView.Adapter<AdapterQuiz.ResultViewHolder>{
private FirebaseAuth mAuth;
private List<Results> mResultsList;
public AdapterQuiz(List<Results>mResultsList)
{
this.mResultsList = mResultsList;
}
public class ResultViewHolder extends RecyclerView.ViewHolder{
public TextView name;
public TextView score;
public ResultViewHolder(View view)
{
super(view);
name = (TextView)view.findViewById(R.id.name);
score = (TextView)view.findViewById(R.id.score);
}
}
#Override
public ResultViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
View V = LayoutInflater.from(parent.getContext()).inflate(R.layout.custom_activity_results,parent,false);
mAuth = FirebaseAuth.getInstance();
return new ResultViewHolder(V);
}
#Override
public void onBindViewHolder(ResultViewHolder holder, int position) {
Results results = mResultsList.get(position);
holder.name.setText(results.getName());
holder.score.setText(results.getScore());
}
#Override
public int getItemCount() {
return mResultsList.size();
}
}
Results Class
public class Results {
private String Name;
private String Score;
public Results() {
}
public Results(String Name, String Score) {
this.Name = Name;
this.Score = Score;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public String getScore() {
return Score;
}
public void setScore(String score) {
Score = score;
}
}
I have worked quite sometime on RecyclerView and Firebase but usually I would display a constant 'name' and a variable 'value' but here both name and variable is not decided by me... when the user finishes the quiz and his score will be displayed in the recyclerview but its just showing blank without any error... I'm not sure if this is the right way of fetching this kind of data... can anyone help me out please
Database - https://ibb.co/eMWkFJ
Results results;
String name, score;
private void fetchResults() {
mDatabaseReference.child("Users").child(id).child("Quiz").child("Results").child(id).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot childDataSnapshot : dataSnapshot.getChildren()) {
name = childDataSnapshot.getKey().toString();
score = childDataSnapshot.child(name).getValue());
results = new Results(user, score);
resultsList.add(results);
mAdapter.notifyDataSetChanged();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
});
}
I hope this will do your job.
To solve this, you first need to set the adapter before notifying it for changes. So please use the following line of code:
mRecyclerView.setAdapter(mAdapter);
Instead of this:
mAdapter.notifyDataSetChanged();
This last line of code should be used only when some changes take place in your database and in order to notify the adapter, this must be set in the fist place.

Firebase getKey returning long, Failed to convert a value of type java.lang.String to long

I'm trying to retrieve values from the database to display on views but im getting this crash right here
FATAL EXCEPTION: main
Process: com.example.ahmad.carrental, PID: 15975
com.google.firebase.database.DatabaseException: Failed to convert a value of type java.lang.String to long
at com.google.android.gms.internal.zzear.zzb(Unknown Source)
at com.google.android.gms.internal.zzear.zza(Unknown Source)
at com.google.android.gms.internal.zzear.zzb(Unknown Source)
at com.google.android.gms.internal.zzeas.zze(Unknown Source)
at com.google.android.gms.internal.zzear.zzb(Unknown Source)
at com.google.android.gms.internal.zzear.zza(Unknown Source)
at com.google.firebase.database.DataSnapshot.getValue(Unknown Source)
at com.example.ahmad.carrental.Utilities.FirebaseUtilities.getCarData(FirebaseUtilities.java:178)
at com.example.ahmad.carrental.CarPost.CreatePostActivity$1$1.onDataChange(CreatePostActivity.java:100)
at com.google.android.gms.internal.zzduz.zza(Unknown Source)
at com.google.android.gms.internal.zzdwu.zzbvb(Unknown Source)
at com.google.android.gms.internal.zzdxa.run(Unknown Source)
at android.os.Handler.handleCallback(Handler.java:761)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:156)
at android.app.ActivityThread.main(ActivityThread.java:6605)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:999)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:889)
The classes are as follows
Car Model
public class Car {
private String brand;
private String id;
private int price;
private String model;
private long distance;
private String status;
private String picture;
private String location;
private String description;
public Car() {
}
public Car(String brand, String id, int price, String model, long distance, String status, String picture, String location, String description) {
this.brand = brand;
this.id = id;
this.price = price;
this.model = model;
this.distance = distance;
this.status = status;
this.picture = picture;
this.location = location;
this.description = description;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public long getDistance() {
return distance;
}
public void setDistance(long distance) {
this.distance = distance;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getPicture() {
return picture;
}
public void setPicture(String picture) {
this.picture = picture;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
User Model
public class User {
private String email;
private String id;
private String name;
private int phonenumber;
public User(String email, String id, String name,int phonenumber) {
this.email = email;
this.id = id;
this.name = name;
this.phonenumber = phonenumber;
}
public User(){
}
public int getPhonenumber() {
return phonenumber;
}
public void setPhonenumber(int phonenumber) {
this.phonenumber = phonenumber;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Database Querying Function
public Car getCarData(DataSnapshot dataSnapshot) {
Log.i(TAG,"getCardData: Getting car data from database");
Car data = new Car();
for(DataSnapshot ds :dataSnapshot.getChildren()){
if(ds.getKey().equals(context.getString(R.string.dbname_car_post))){
try{
data.setId(ds.child(userID).getValue(Car.class).getId());
data.setBrand(ds.child(userID).getValue(Car.class).getBrand());
data.setDescription(ds.child(userID).getValue(Car.class).getDescription());
data.setModel(ds.child(userID).getValue(Car.class).getModel());
data.setDistance(ds.child(userID).getValue(Car.class).getDistance());
data.setPicture(ds.child(userID).getValue(Car.class).getPicture());
data.setStatus(ds.child(userID).getValue(Car.class).getStatus());
data.setLocation(ds.child(userID).getValue(Car.class).getLocation());
data.setPrice(ds.child(userID).getValue(Car.class).getPrice());
}catch (NullPointerException e){
Log.d(TAG, "getCarData: NullPointerException : " + e.getMessage());
}
}
}
return data;
}
Activity that im retrieving the data from
CreateCarPost Activity
public class CreatePostActivity extends AppCompatActivity implements CreatePostView,AdapterView.OnItemSelectedListener{
//Activity Tag
private static final String TAG ="CreateCarPost";
//Spinners
Spinner statusSpinner;
Spinner brandSpinner;
//Adapter of spinners
ArrayAdapter mArrayAdapter;
ArrayAdapter mArrayAdapter2;
//views
private TextView tvDistance;
private EditText etDistance;
private AutoCompleteTextView etCarLocation;
private CircleImageView civPicture;
private EditText etPrice;
private EditText etDescription;
private EditText etModel;
private ImageView checkButton;
//Strings
private String carLoactionStr;
private String carBrandStr;
private String carStatusStr;
//layout containg the views
private LinearLayout layoutContainer;
//To adjust dynamic views margins
LinearLayout.LayoutParams layoutParamsTv,layoutParamsEt;
//Firebase
private FirebaseAuth mAuth;
private FirebaseAuth.AuthStateListener mAuthStateListener;
private FirebaseDatabase mFirebaseDatabase;
private DatabaseReference mDatabaseReference;
private ValueEventListener singleValueEventListener;
private FirebaseUtilities mFirebaseUtilities;
Context mContext;
CreatePostPresenter createPostPresenter;
private Car car;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_create_post);
initialization();
setupFirebaseAuth();
setUpLocationSpinner();
//Assigning Car object with its data from database.
io.reactivex.Observable.create(new ObservableOnSubscribe() {
#Override
public void subscribe(ObservableEmitter emitter) throws Exception {
singleValueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
car = mFirebaseUtilities.getCarData(dataSnapshot);
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.e(TAG, "CANCELLED.");
}
};
mDatabaseReference.addValueEventListener(singleValueEventListener);
}
}).unsubscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe();
checkButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
createPostPresenter.onSaveChanges(car);
}
});
}
//initalizing everything necessary here
public void initialization(){
mContext = getApplicationContext();
createPostPresenter = new CreatePostPresenter(this,this);
//Adapter set up for spinners
mArrayAdapter2 = ArrayAdapter.createFromResource(this,R.array.car_brands,android.R.layout.simple_spinner_item);
mArrayAdapter = ArrayAdapter.createFromResource(this,R.array.car_status_array,android.R.layout.simple_spinner_item);
//Status spinner set up
statusSpinner = findViewById(R.id.createPostCarStatusSpinner_ID);
statusSpinner.setAdapter(mArrayAdapter);
statusSpinner.setOnItemSelectedListener(this);
//Brand spinner set up
brandSpinner = findViewById(R.id.createPostCarBrandSpinner_ID);
brandSpinner.setAdapter(mArrayAdapter2);
brandSpinner.setOnItemSelectedListener(this);
layoutContainer = findViewById(R.id.createPostLinearLayout_ID);
tvDistance = new TextView(this);
tvDistance.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
tvDistance.setText("Distance Travelled");
etDistance = new EditText(this);
etDistance.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
//margin settings editText
layoutParamsEt = (LinearLayout.LayoutParams)etDistance.getLayoutParams();
layoutParamsEt.setMargins(0,10,0,0);
etDistance.setLayoutParams(layoutParamsEt);
//margin settings textView
layoutParamsTv = (LinearLayout.LayoutParams)tvDistance.getLayoutParams();
layoutParamsTv.setMargins(0,10,0,0);
tvDistance.setLayoutParams(layoutParamsTv);
etCarLocation = findViewById(R.id.createPostCarLocation_ID);
etDescription = findViewById(R.id.createPostCarDes_ID);
etPrice = findViewById(R.id.createPostCarPrice_ID);
etModel = findViewById(R.id.createPostCarModel_ID);
checkButton = findViewById(R.id.check_ID);
mFirebaseUtilities = new FirebaseUtilities(this);
}
private void setUpLocationSpinner() {
ArrayAdapter<String> listOfCities = new ArrayAdapter<>(getBaseContext(),
android.R.layout.simple_list_item_1, getResources().getStringArray(R.array.TR_cities));
//--- to ensure user is restricted to selections from drop-down menu
etCarLocation.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
carLoactionStr = etCarLocation.getAdapter().getItem(position).toString();
}
});
etCarLocation.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
for (int i = 0; i < etCarLocation.getAdapter().getCount(); i++) {
if (etCarLocation.getText().toString().equals(etCarLocation.getAdapter().getItem(i))) {
carLoactionStr = etCarLocation.getAdapter().getItem(i).toString();
} else
carLoactionStr = null;
}
}
#Override
public void afterTextChanged(Editable s) {
}
});
//start autocomplete after 1 letter
etCarLocation.setThreshold(1);
etCarLocation.performCompletion();
etCarLocation.setAdapter(listOfCities);
}
/**
* Listener for car status spinner
* #param parent
* #param view
* #param position
* #param id
*/
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
Spinner spinner = (Spinner)parent;
if(spinner.getId() == R.id.createPostCarStatusSpinner_ID){
TextView textView = (TextView) view;
carStatusStr = textView.getText().toString();
addDynamicViews(position);
}
else if(spinner.getId() == R.id.createPostCarBrandSpinner_ID){
TextView textView = (TextView) view;
carBrandStr = textView.getText().toString();
}
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
/**
* Dynamic views creation done by handling user spinner selection for first hand or second hand car status.
*#param position: position of selected value from spinner
*/
public void addDynamicViews(int position){
if(position == 1){
layoutContainer.addView(tvDistance);
layoutContainer.addView(etDistance);
}
else if(position == 0){
mFirebaseUtilities.removeNodeDynamically();
layoutContainer.removeView(tvDistance);
layoutContainer.removeView(etDistance);
}
}
#Override
public void setBrand(String brand) {
}
#Override
public void setPrice(int price) {
}
#Override
public void setLocation(String location) {
}
#Override
public void setDescription(String description) {
}
#Override
public void setModel(String model) {
}
#Override
public void setDistance(long distance) {
}
#Override
public void setStatus(String status) {
}
#Override
public void setPicture(String picture) {
}
#Override
public String getBrand() {
return carBrandStr;
}
#Override
public String getDescription() {
return etDescription.getText().toString();
}
#Override
public String getLocation() {
return carLoactionStr;
}
#Override
public String getModel() {
return etModel.getText().toString();
}
#Override
public String getStatus() {
return carStatusStr;
}
#Override
public String getPicture() {
return null;
}
#Override
public int getPrice() {
String priceViewTemp = etPrice.getText().toString();
if (priceViewTemp.equals("")) {
return 0;
} else {
return Integer.valueOf(etPrice.getText().toString());
}
}
#Override
public long getDistance() {
String distanceViewTemp = etDistance.getText().toString();
if (distanceViewTemp.equals("")) {
return 0;
} else {
return Integer.valueOf(etDistance.getText().toString());
}
}
/*************************************** Firebase *******************************************/
private void setupFirebaseAuth() {
mAuth = FirebaseAuth.getInstance();
mFirebaseDatabase = FirebaseDatabase.getInstance();
mDatabaseReference = mFirebaseDatabase.getReference();
mAuthStateListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
FirebaseUser user = firebaseAuth.getCurrentUser();
if (user != null) {
//User is signed in
Log.d(TAG, "onAuthStateChanged: user signed in : " + user.getUid());
} else {
//User is signed out
Log.d(TAG, "onAuthStateChanged: user signed out");
}
}
};
mDatabaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
#Override
public void onPause() {
super.onPause();
if (singleValueEventListener != null) {
mDatabaseReference.removeEventListener(singleValueEventListener);
}
}
#Override
public void onResume(){
super.onResume();
mDatabaseReference.addListenerForSingleValueEvent(singleValueEventListener);
}
}
Firebase Structure
Firebase Structure
Haven't read if much, but i first noticed something here.
for(DataSnapshot ds :dataSnapshot.getChildren()){
if(ds.getKey().equals(context.getString(R.string.dbname_car_post))){
try{ }
The key you're trying to retrieve is an Object. So i would propose we convert it string first, sample down here.
for(DataSnapshot ds :dataSnapshot.getChildren()){
Object myKey=ds.getKey;
if(myKey.toString().equals(context.getString(R.string.dbname_car_post))){
try{ }
}}
Let me know what happens next!

Categories

Resources