Basically, what I am trying to do is use a FirebaseRecyclerAdapter and populate the RecyclerView with my custom designed CardView. The code for newer versions has been changed and therefore, I tried implementing it but didn't work.
This is the code I use to write a year ago, which worked fine and populated my RecyclerView:
FirebaseRecyclerAdapter<DataClass,DataViewHolder> FBRA= new FirebaseRecyclerAdapter<DataClass, DataViewHolder>(
DataClass,
R.layout.myCardView,
DataViewHolder.class,
databaseReference
) {
#Override
protected void populateViewHolder(DataViewHolder viewHolder, DataClass model, int position) {
viewHolder.setTitle(model.gettitle());
viewHolder.setDate(model.getDate());
}
};
myRecyclerView.setAdapter(FBRA);
And now we have to use something like this,
but the problem is this code is not populating my recyclerView (What changes do I need to make here to populate my recyclerView with my cardView?)
#Override
protected void onStart() {
super.onStart();
Query query = FirebaseDatabase.getInstance()
.getReference()
.child("Official_Services");
FirebaseRecyclerOptions<ServiceClass> options = new FirebaseRecyclerOptions.Builder<ServiceClass>()
.setQuery(query, ServiceClass.class)
.build();
FirebaseRecyclerAdapter<ServiceClass, ServiceViewHolder> FBRA = new FirebaseRecyclerAdapter<ServiceClass, ServiceViewHolder>(options) {
#NonNull
#Override
public ServiceViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int i) {
View view = LayoutInflater.from(HomeActivity.this).inflate(R.layout.service_card, parent, false);
return new ServiceViewHolder(view);
}
#Override
protected void onBindViewHolder(#NonNull ServiceViewHolder holder, int position, #NonNull ServiceClass model) {
holder.setServiceName(model.getServiceName());
holder.setServiceCaption(model.getServiceCaption());
}
};
mServiceList.setAdapter(FBRA);
}
Here is my ViewHolder class:
public static class ServiceViewHolder extends RecyclerView.ViewHolder {
public ServiceViewHolder(View itemView) {
super(itemView);
View mView = itemView;
}
public void setServiceName(String serviceName) {
TextView sName = itemView.findViewById(R.id.serviceName);
sName.setText(serviceName);
}
public void setServiceCaption(String serviceCaption) {
TextView sCaption = itemView.findViewById(R.id.serviceCap);
sCaption.setText(serviceCaption);
}
}
And this is my Model class of getters and setters:
public class ServiceClass {
private String serviceName;
private String serviceCode;
private String serviceCaption;
private String serviceIconUrl;
public ServiceClass() {
}
public ServiceClass(String serviceName, String serviceCode, String serviceCaption, String serviceIconUrl) {
this.serviceName = serviceName;
this.serviceCode = serviceCode;
this.serviceCaption = serviceCaption;
this.serviceIconUrl = serviceIconUrl;
}
public String getServiceName() {
return serviceName;
}
public String getServiceCode() {
return serviceCode;
}
public String getServiceCaption() {
return serviceCaption;
}
public String getServiceIconUrl() {
return serviceIconUrl;
}
public void setServiceName(String serviceName) {
this.serviceName = serviceName;
}
public void setServiceCode(String serviceCode) {
this.serviceCode = serviceCode;
}
public void setServiceCaption(String serviceCaption) {
this.serviceCaption = serviceCaption;
}
public void setServiceIconUrl(String serviceIconUrl) {
this.serviceIconUrl = serviceIconUrl;
}
#Override
public String toString() {
return "ServiceClass{" +
"serviceName='" + serviceName + '\'' +
", serviceCode='" + serviceCode + '\'' +
", serviceCaption='" + serviceCaption + '\'' +
", serviceIconUrl='" + serviceIconUrl + '\'' +
'}';
}
}
Now what changes do I need to do?
Here is my entire java file:
public class HomeActivity extends AppCompatActivity {
private RecyclerView mServiceList;
private FirebaseDatabase mDatabase;
private DatabaseReference myRef;
FirebaseRecyclerAdapter<ServiceClass, ServiceViewHolder> FBRA;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
BottomNavigationViewEx bottomNavigationViewEx = findViewById(R.id.navViewBar);
bottomNavigationViewEx.enableAnimation(false);
bottomNavigationViewEx.enableShiftingMode(false);
bottomNavigationViewEx.setTextVisibility(false);
Calligrapher calligrapher = new Calligrapher(this);
calligrapher.setFont(this, "Helvetica.ttf", true);
mServiceList = findViewById(R.id.serviceRV);
mServiceList.setHasFixedSize(true);
mServiceList.setLayoutManager(new LinearLayoutManager(this));
mDatabase = FirebaseDatabase.getInstance();
myRef = mDatabase.getReference().child("Official_Services");
}
#Override
protected void onStart() {
super.onStart();
FBRA.startListening();
Query query = myRef;
FirebaseRecyclerOptions<ServiceClass> options = new FirebaseRecyclerOptions.Builder<ServiceClass>()
.setQuery(query, ServiceClass.class)
.build();
FBRA = new FirebaseRecyclerAdapter<ServiceClass, ServiceViewHolder>(options) {
#NonNull
#Override
public ServiceViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int i) {
View view = LayoutInflater.from(HomeActivity.this).inflate(R.layout.service_card, parent, false);
return new ServiceViewHolder(view);
}
#Override
protected void onBindViewHolder(#NonNull ServiceViewHolder holder, int position, #NonNull ServiceClass model) {
holder.setServiceName(model.getServiceName());
holder.setServiceCaption(model.getServiceCaption());
}
};
mServiceList.setAdapter(FBRA);
}
public static class ServiceViewHolder extends RecyclerView.ViewHolder {
public ServiceViewHolder(View itemView) {
super(itemView);
View mView = itemView;
}
public void setServiceName(String serviceName) {
TextView sName = itemView.findViewById(R.id.serviceName);
sName.setText(serviceName);
}
public void setServiceCaption(String serviceCaption) {
TextView sCaption = itemView.findViewById(R.id.serviceCap);
sCaption.setText(serviceCaption);
}
}
}
In order to be able to display data from the Firebase realtime database you need to start listening for changes and for that you should add the following line of code in the onStart() method:
#Override
protected void onStart() {
super.onStart();
FBRA.startListening();
}
To stop listening foir changes you need add the following line of code in the onStop() method like this:
#Override
protected void onStop() {
super.onStop();
if(FBRA != null) {
FBRA.stopListening();
}
}
Please see my answer from this post where I have explained why you should remove the listener.
P.S. Please also don't forget to make the FBRA a global variable and remove FirebaseRecyclerAdapter<ServiceClass, ServiceViewHolder> from the declaration of the object.
This is more of an advice. If you want to continue using the old method to populate your
recyclerview ie The "populateViewHolder" method instead of the new "onBindViewHolder" method just use this;
implementation 'com.firebaseui:firebase-ui:1.0.1'
instead of upgraded firebase-ui versions
Related
everyone, I was trying to make a music app, and for this, I Created a Horizontal RecyclerView in my HomeFragment and my horizontal RecyclerView is getting an image with artist name.
But after clicking I load another Activity. In my other activity, I was trying to load SongsData from firebase in a listView with RecyclerView.
But the problem is I am not getting data from Firebase and it is returning null data. I provided my code below and here is the screenshot of my Firebase database:- ScreenShot
My List Class:-
public class TestUploads
{
private String songName;
private String songImageUri;
private String songUrl;
private String artistName;
public TestUploads() {
}
public String getSongName() {
return songName;
}
public void setSongName(String SongName) {
this.songName = SongName;
}
public String getSongImageUri() {
return songImageUri;
}
public void setSongImageUri(String SongImageUri) {
this.songImageUri = SongImageUri;
}
public String getSongUrl() {
return songUrl;
}
public void setSongUrl(String SongUrl) {
this.songUrl = songUrl;
}
public TestUploads(String SongImageUri, String SongName, String SongUrl ) {
this.songName = SongName;
this.artistName = SongImageUri;
this.songUrl = SongUrl;
}
}
My Adapter Class:-
public class TestAdapter extends RecyclerView.Adapter<TestAdapter.TestViewHolder>{
private Context mContext;
private List<TestUploads> mUploads;
public TestAdapter(Context context , List<TestUploads> uploads) {
mContext = context;
mUploads = uploads;
}
#NonNull
#Override
public TestViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(mContext).inflate(R.layout.test_package_layout , parent ,false);
return new TestViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull TestViewHolder holder, int position) {
TestUploads uploadcurrent = mUploads.get(position);
holder.name.setText(uploadcurrent.getSongName());
Glide.with(mContext)
.load(uploadcurrent.getSongImageUri())
.into(holder.image_view);
}
#Override
public int getItemCount() {
return mUploads
.size();
}
public class TestViewHolder extends RecyclerView.ViewHolder {
public TextView name;
public TextView artist_name;
public CircleImageView image_view;
public TestViewHolder(#NonNull View itemView) {
super(itemView);
name = itemView.findViewById(R.id.test_package_song_name);
artist_name = itemView.findViewById(R.id.test_package_artist_name);
image_view = itemView.findViewById(R.id.test_package_image_name);
}
}
}
My Activity:-
public class TestActivity extends AppCompatActivity {
private ValueEventListener listener;
private DatabaseReference reference;
private List<TestUploads> mUploads;
private RecyclerView mRecyclerView;
private TestAdapter adapter;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_package_activity);
reference = FirebaseDatabase.getInstance().getReference("ArtistView").child(getIntent().getStringExtra("Artist"))
.child("Songs");
Toast.makeText(this, "" + getIntent().getStringExtra("Artist"), Toast.LENGTH_SHORT).show();
mUploads = new ArrayList<>();
mRecyclerView = findViewById(R.id.test_pacakge_recyclerView);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mRecyclerView.smoothScrollToPosition(0);
adapter = new TestAdapter(this , mUploads);
mRecyclerView.setAdapter(adapter);
listener = reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
mUploads.clear();
for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
TestUploads uploads =postSnapshot.getValue(TestUploads.class);
mUploads.add(uploads);
}
adapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
Sorry for so much code but this is not hard to solve. If you find the solution please reply to me. Thanks for reading this.
The problem in your code lies in the fact that the names of the fields in your TestUploads class are different than the name of the properties in your database. You have in your TestUploads class a field named songName but in your database, I see it as SongName and this is not correct. The names must match. When you are using a getter named getSongName(), Firebase is looking in the database for a field named songName and not SongName. See the lowercase s letter vs. capital letter S?
There are two ways in which you can solve this problem. The first one would be to remove the data in your database and add it again using field names that start with lowercase, as exist in your TestUploads class.
If you are not allowed to use the first solution, then the second approach will be to use annotations. So you should use the PropertyName annotation in front of the getters. So in your TestUploads class, a getter should look like this:
#PropertyName("SongName")
public String getSongName() {
return songName;
}
I'm using a Cloud Firestore database to populate a RecyclerView in an Android app. I'm getting the data by using a Task in the onAttach method of a Fragment. I need to be able to update the UI, the RecyclerView with data from the Cloud Firestore.
I populated the RecyclerView with dummy data in the onAttach method of the Fragment and that worked, but when I put the same loop that inserts dummy data in the onComplete method of a OnCompleteListener that's used in the Task that pulls data from the Cloud Firestore, the RecyclerView doesn't update and the list stays blank. I need to do it there to eventually insert data from the Cloud Firestore.
Within the Fragment. The data coming back from the Firestore database is correct and I see all of the Log statements in the onComplete method in the Logcat.
ChatListFragment:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mColumnCount = getArguments().getInt(ARG_COLUMN_COUNT);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_chat_list, container, false);
// Set the adapter
if (view instanceof RecyclerView) {
Context context = view.getContext();
RecyclerView recyclerView = (RecyclerView) view;
if (mColumnCount <= 1) {
recyclerView.setLayoutManager(new LinearLayoutManager(context));
} else {
recyclerView.setLayoutManager(new GridLayoutManager(context, mColumnCount));
}
chatRecyclerViewAdapter = new ChatRecyclerViewAdapter(ChatList.ITEMS, mListener);
recyclerView.setAdapter(chatRecyclerViewAdapter);
}
return view;
}
...
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnListFragmentInteractionListener) {
mListener = (OnListFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnListFragmentInteractionListener");
}
Log.d(LOG_TAG, "activity attached, creating Firestore instance");
FirebaseFirestore db = FirebaseFirestore.getInstance();
//Worked, but doesn't in OnCompleteListener
/*for (int i = 1; i <= 10; i++) {
ChatList.addItem(ChatList.createDummyItem(i));
}*/
Task<QuerySnapshot> task = db.collection("chats").get();
task.addOnCompleteListener(getActivity(), new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
Log.d(LOG_TAG, "ID = " + document.getId() + " => " + document.getData());
ChatListMessage chatListMessage = document.toObject(ChatListMessage.class);
for (int i = 1; i <= 10; i++) {
Log.d(LOG_TAG, "adding message");
ChatList.addItem(ChatList.createDummyItem(i));
}
Log.d(LOG_TAG, "ChatListMessage members " + chatListMessage.getLastMessage());
}
} else {
Log.w(LOG_TAG, "Error getting documents.", task.getException());
}
}
});
}
Within the ChatList class
public static void addItem(ChatListItem item) {
ITEMS.add(item);
ITEM_MAP.put(item.userId, item);
}
public static ChatListItem createDummyItem(int position) {
return new ChatListItem(String.valueOf(position), R.drawable.profile_circle, makeDetails(position),
new Timestamp(System.currentTimeMillis()));
}
public static class ChatListItem {
public final String userId;
public final int pictureUrl;
public final String lastMessage;
public final Timestamp timeStamp;
public ChatListItem(String userId, int pictureUrl, String details, Timestamp timeStamp) {
this.userId = userId;
this.pictureUrl = pictureUrl;
this.lastMessage = details;
this.timeStamp = timeStamp;
}
#Override
public String toString() {
return userId;
}
public Timestamp getTimeStamp() {
return timeStamp;
}
public String getTLastMessage() {
return lastMessage;
}
}
The custom RecyclerViewAdapter
public class ChatRecyclerViewAdapter extends RecyclerView.Adapter<ChatRecyclerViewAdapter.ViewHolder> {
private final List<ChatListItem> mValues;
private final OnListFragmentInteractionListener mListener;
public ChatRecyclerViewAdapter(List<ChatListItem> items, OnListFragmentInteractionListener listener) {
mValues = items;
mListener = listener;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.fragment_chat, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.mItem = mValues.get(position);
holder.contactImageView.setImageResource(mValues.get(position).pictureUrl);
holder.contactImageView.setScaleType(ImageView.ScaleType.FIT_XY);
holder.mContentView.setText(mValues.get(position).lastMessage);
holder.mView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (null != mListener) {
// Notify the active callbacks interface (the activity, if the
// fragment is attached to one) that an item has been selected.
mListener.onListFragmentInteraction(holder.mItem);
}
}
});
}
#Override
public int getItemCount() {
return mValues.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public final View mView;
public final ImageView contactImageView;
public final TextView messageMembersTextView;
public final TextView mContentView;
public final TextView timestampView;
public ChatListItem mItem;
public ViewHolder(View view) {
super(view);
mView = view;
messageMembersTextView = view.findViewById(R.id.message_members);
contactImageView = view.findViewById(R.id.contact_imageView);
mContentView = view.findViewById(R.id.content_textView);
timestampView = view.findViewById(R.id.timestamp_textView);
}
#Override
public String toString() {
return super.toString() + " '" + mContentView.getText() + "'";
}
}
}
How can I get the UI to be updated with the onComplete method of the OnCompleteListener?
For this, chatRecyclerViewAdapter.notifyDataSetChanged() needs to be called in the onComplete method of the OnCompleteListener. I forgot to do this outside of the listener since it looks like the list items are pulled in after the onAttach method is called.
I tried to have in my model the id of the document but when I access it the value of the id is null.
In fragment/activity:
public class MyEventsFragment extends Fragment {
private OnFragmentInteractionListener mListener;
private FirestorePagingAdapter mAdapter;
private FirebaseFirestore mFirebaseFirestore;
public MyEventsFragment() {
// Required empty public constructor
}
public static MyEventsFragment newInstance() {
return new MyEventsFragment();
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mFirebaseFirestore = FirebaseFirestore.getInstance();
Query query = mFirebaseFirestore.collection("events");
PagedList.Config config = new PagedList.Config.Builder()
.setEnablePlaceholders(false)
.setPrefetchDistance(10)
.setPageSize(20)
.build();
FirestorePagingOptions<Event> options = new FirestorePagingOptions.Builder<Event>()
.setLifecycleOwner(this)
.setQuery(query, config, new SnapshotParser<Event>() {
#NonNull
#Override
public Event parseSnapshot(#NonNull DocumentSnapshot snapshot) {
Event evt = new Event(
snapshot.getId(),
snapshot.getString("titre"),
snapshot.getString("sport"),
snapshot.getString("lieu"),
snapshot.get("date", Timestamp.class),
snapshot.get("dateLimit", Timestamp.class));
Log.i("TEST", evt.toString());
return evt;
}
})
.build();
mAdapter = new EventFirestorePagingAdapter(options, getContext());
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_list_events, container, false);
RecyclerView mRecyclerView = view.findViewById(R.id.recyclerViewListEvent);
LinearLayoutManager mLayoutManager = new LinearLayoutManager(getContext());
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mAdapter);
return view;
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
#Override
public void onStart() {
super.onStart();
mAdapter.startListening();
}
#Override
public void onStop() {
super.onStop();
mAdapter.stopListening();
}
public interface OnFragmentInteractionListener {
void onFragmentInteraction(Uri uri);
}
}
EventFirestorePagingAdapter (extends FirestorePagingAdapter):
public class EventFirestorePagingAdapter extends FirestorePagingAdapter<Event, EventFirestorePagingAdapter.EventViewHolder> {
private Context mContext;
public EventFirestorePagingAdapter(#NonNull FirestorePagingOptions<Event> options, Context context) {
super(options);
this.mContext = context;
}
public class EventViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView titre, sport, lieu, date;
public EventViewHolder(#NonNull View itemView) {
super(itemView);
titre = itemView.findViewById(R.id.titreRecyclerView);
sport = itemView.findViewById(R.id.sportRecyclerView);
lieu = itemView.findViewById(R.id.lieuRecyclerView);
date = itemView.findViewById(R.id.dateRecyclerView);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
/*for(Map.Entry<String, Object> map: getItem(getAdapterPosition()).getData().entrySet()){
Log.i("TEST", map.getKey());
}*/
Event event = getItem(getAdapterPosition()).toObject(Event.class);
Log.i("TEST", "id = " + event.getId());
Toast.makeText(mContext, "OnClick on position : " + getAdapterPosition() + " \nTest : " + event.getTitre() + "\nId : " + event.getId(), Toast.LENGTH_LONG).show();
}
}
#Override
protected void onBindViewHolder(#NonNull EventViewHolder holder, int position, #NonNull Event model) {
holder.titre.setText(model.getTitre());
holder.sport.setText(model.getSport());
holder.lieu.setText(model.getLieu());
holder.date.setText(model.getDate().toDate().toString());
}
#NonNull
#Override
public EventViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(mContext).inflate(R.layout.recyclerview_card_row, viewGroup, false);
return new EventViewHolder(view);
}
}
Event class :
public class Event {
private String id;
private String titre;
private String sport;
private String lieu;
private Timestamp date;
private Timestamp dateLimit;
public Event(){ } // Needed for Firebase
public Event(String id, String titre, String sport, String lieu, Timestamp date, Timestamp dateLimit) {
this.id = id;
this.titre = titre;
this.sport = sport;
this.lieu = lieu;
this.date = date;
this.dateLimit = dateLimit;
}
// ... getters & setters
}
Debug :
1) TEST: Event{id='c5jUGQc4c7SHzbpT6N01', titre='Final PSG/MARSEILLE', sport='Football', lieu='Bercy', date=Timestamp(seconds=1550844000, nanoseconds=0), dateLimit=Timestamp(seconds=1551009600, nanoseconds=0)}
2) TEST: id = null
Firestore database:
Firestore Database
Gist with the same issue
Answer :
SnapshotParser did not work as i expected but i find out how to access to the id of the document in the onClick(). I replaced this line by this following code :
DocumentSnapshot documentSnapshot = getCurrentList().get(getAdapterPosition());
Chat chat = documentSnapshot.toObject(Chat.class);
chat.setId(documentSnapshot.getId());
According to your comment:
yes, but i need to retrieve it later when i click on an item from my recyclerview
Because you are using a FirestorePagingAdapter and you aren't able to use something like this:
String id = getSnapshots().getSnapshot(position).getId(); //Works only with FirestoreRecyclerAdapter
You need to store the id of the document as property of your document. As I see in your Event class, the property id exists but in the database there is no id property that holds the document id. To solve this, you need to pass the id of the document to the Event constructor when you are creating a new object like this:
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
CollectionReference eventsRef = rootRef.collection("events");
String id = eventsRef.document().getId();
Event event = new Event(id, titre, sport, lieu, date, dateLimit);
eventsRef.document(id).set(event);
Can anyone help me to retrieve data from the node "foods" and put it in the RecyclerView. These are the file I've been working on but it turns out to be an empty list. I have viewed a tutorial on Internet but most of them were with an older version of Firebase. Recently, Firebase UI has been updated and the data binding process has changed to their new FirebaseRecyclerAdapter structure
This is my database structure:
"foods" : {
"AntipastoSalad" : {
"duration" : "30",
"img" : "https://firebasestorage.googleapis.com/v0/b/mealplanner-ec8ca.appspot.com/o/res%2Fsalad.jpg?alt=media&token=257d4392-8a1f-4fb7-84b5-b63abb4643f4",
"name" : "Antipasto salad",
"type" : "Salad"
},
This is my activity:
private RecyclerView mRecycleView;
private Query query;
private FirebaseRecyclerOptions<Meal> options;
private DatabaseReference mDatabase;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_food_list_row);
mDatabase = FirebaseDatabase.getInstance().getReference().child("foods");
//Recycle View
mRecycleView = (RecyclerView) findViewById(R.id.meal_items);
mRecycleView.setHasFixedSize(true);
mRecycleView.setLayoutManager(new LinearLayoutManager(this));
}
#Override
protected void onStart() {
super.onStart();
query = FirebaseDatabase.getInstance().getReferenceFromUrl("https://mealplanner-ec8ca.firebaseio.com/foods/AntipastoSalad");
options = new FirebaseRecyclerOptions.Builder<Meal>()
.setQuery(query, Meal.class)
.build();
FirebaseRecyclerAdapter<Meal, FoodListRowActivity.MealRowHolder> firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<Meal, FoodListRowActivity.MealRowHolder>(
options) {
#Override
public FoodListRowActivity.MealRowHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.food_row, parent, false);
return new FoodListRowActivity.MealRowHolder(v);
}
#Override
protected void onBindViewHolder(FoodListRowActivity.MealRowHolder holder, int position, Meal current) {
holder.setTitle(current.getName());
String duration = current.getDuration() + "min";
holder.setDuration(duration);
}
};
//Populate Item into Adapter
mRecycleView.setAdapter(firebaseRecyclerAdapter);
mRecycleView.addOnItemTouchListener(new RecycleViewItemClickListener(this, mRecycleView, new RecycleViewItemClickListener.OnItemClickListener() {
#Override
public void onItemClick(View view, int position) {
Intent viewMeal = new Intent(FoodListRowActivity.this, CookingInstructionActivity.class);
startActivity(viewMeal);
}
#Override
public void onLongItemClick(View view, int position) {
//TODO: DELETE
}
}));
}
public static class MealRowHolder extends RecyclerView.ViewHolder {
View mView;
public MealRowHolder(View itemView) {
super(itemView);
mView = itemView;
}
public void setTitle(String title) {
TextView foodTitle = (TextView) mView.findViewById(R.id.list_item_foodList_name);
foodTitle.setText(title);
}
public void setDuration(String title) {
TextView foodDuration = (TextView) mView.findViewById(R.id.list_item_foodList_calories);
foodDuration.setText(title);
}
}
}
and class structure:
public class Meal{
private String img;
private String duration;
private String name;
private String instruction;
public Meal(){
}
public Meal (String img, String duration, String name, String instruction){
this.img = img;
this.name = name;
this.duration = duration;
this.instruction = instruction;
}
public void update(String duration, String name, String instruction)
{
this.name = name;
this.duration = duration;
this.instruction = instruction;
}
public String getName(){
return name;
}
public String getDuration() {
return duration;
}
public String getInstruction() {
return instruction;
}
public String getImg(){return img;}
The query specified in the setQuery() method should be a reference to the root of the list you want to show in the RecyclerView, so like this:
query = FirebaseDatabase.getInstance().getReference().child("foods");
You also need to call startListening() on the adapter to instruct it to start retrieving data from the database.
From the FirebaseRecyclerAdapter lifecycle documentation:
The FirebaseRecyclerAdapter uses an event listener to monitor changes to the Firebase query. To begin listening for data, call the startListening() method. You may want to call this in your onStart() method. Make sure you have finished any authentication necessary to read the data before calling startListening() or your query will fail.
#Override protected void onStart() {
super.onStart();
adapter.startListening();
}
Similarly, the stopListening() call removes the event listener and all data in the adapter. Call this method when the containing Activity or Fragment stops:
#Override protected void onStop() {
super.onStop();
adapter.stopListening();
}
Please override getItemCount() method of FirebaseRecyclerAdapter.
#Override
public int getItemCount() {
return 1;
}
Reference.
This is how I'm retrieving my data in recyclerview using Firebase UI:
private FirebaseRecyclerAdapter<TaskPOJO, TaskViewHolder> adapter;
private void loadTasks() {
database = FirebaseDatabase.getInstance();
tasks = database.getReference("Tasks");
adapter = new FirebaseRecyclerAdapter<TaskPOJO, TaskViewHolder>(TaskPOJO.class, R.layout.task_item, TaskViewHolder.class, tasks) {
#Override
protected void populateViewHolder(TaskViewHolder viewHolder, final TaskPOJO model, int position) {
Log.wtf("valueTEst", "populateViewHolder: "+model.toString() );
Log.wtf("TEstScript1", "populateViewHolder: "+model.getTitle() );
viewHolder.title.setText(model.getTitle());
viewHolder.desc.setText(model.getDescripttion()+"\n");
viewHolder.remaining.setText(model.getRemaining()+"/"+model.getPoint());
viewHolder.points.setText("Points "+model.getRemaining());
Glide.with(viewHolder.title.getContext())
.load(model.getImage())
.into(viewHolder.image);
viewHolder.setClickListener(new ItemClickListener() {
#Override
public void onClick(View view, int position, boolean isLongClick) {
Toast.makeText(getActivity(), "" /*+ model.getTitle()*/, Toast.LENGTH_SHORT).show();
Intent TaskPOJODetail = new Intent(getActivity(), Main.class);
TaskPOJODetail.putExtra("value","detail");
TaskPOJODetail.putExtra("taskId",adapter.getRef(position).getKey());
startActivity(TaskPOJODetail);
}
});
}
};
progressBar.setVisibility(View.GONE);
recyclerViewTasks.setAdapter(adapter);
}
this is my firebase structure :
hope this will help you.
I'm trying to add a Button which when clicked should open a new Activity. Despite spending a long time on this, my efforts have been unsuccessful. If I add the OnClickListener and click the Button it gives me an error. Thank you for your help.
Listele.Java
package com.example.hp.myapplication;
import android.view.View;
import android.widget.Button;
public class Listele {
private String adi;
private String fiyat;
private String aciklama;
private String stok;
private String resim;
public Listele(String adi, String fiyat, String aciklama, String stok,String resim) {
this.adi = adi;
this.fiyat = fiyat;
this.aciklama = aciklama;
this.stok = stok;
this.resim = resim;
}
//getters and setters
#Override
public String toString() {
return "Listele{" +
"adi='" + adi + '\'' +
", fiyat='" + fiyat + '\'' +
", aciklama='" + aciklama + '\'' +
", stok='" + stok + '\'' +
", resim='" + resim + '\'' +
'}';
}
}
ListeleAdapter.Java
package com.example.hp.myapplication;
//imports
public class ListeleAdapter extends RecyclerView.Adapter<ListeleAdapter.urunlistem> {
private Context contexto;
private ArrayList<Listele>tortica;
public ListeleAdapter(ArrayList<Listele> tortica, Context contexto ) {
this.contexto = contexto;
this.tortica = tortica;
}
#Override
public urunlistem onCreateViewHolder(ViewGroup parent, int viewType) {
return new urunlistem(LayoutInflater.from(parent.getContext()).inflate(R.layout.list,null));
}
#Override
public void onBindViewHolder(urunlistem holder, int position) {
holder.adi.setText(tortica.get(position).getAdi());
holder.aciklama.setText(tortica.get(position).getAciklama());
holder.stok.setText(tortica.get(position).getStok());
holder.fiyat.setText(tortica.get(position).getFiyat());
Glide.with(contexto).load("http://192.168.1.33:8080/urunler/"+tortica.get(position).getResim()).into(holder.tresim);
}
#Override
public int getItemCount() {
return tortica.size();
}
public static class urunlistem extends RecyclerView.ViewHolder{
ImageView tresim;
TextView adi,fiyat,stok,aciklama;
Button sepete_ekle;
ArrayList<Listele> listeles = new ArrayList<Listele>();
public urunlistem(View itemView) {
super(itemView);
tresim=(ImageView)itemView.findViewById(R.id.resim);
adi=(TextView)itemView.findViewById(R.id.adi_urun);
fiyat=(TextView)itemView.findViewById(R.id.fiyat);
stok=(TextView)itemView.findViewById(R.id.stok);
aciklama=(TextView)itemView.findViewById(R.id.aciklama);
}
}
}
MainActivity.Java
package com.example.hp.myapplication;
//imports
public class MainActivity extends AppCompatActivity {
private static final String url="http://192.168.1.33:8080/urunler/goruntule.php";
private RecyclerView recyclerView;
private ListeleAdapter adapter;
private ArrayList<Listele>listeles = new ArrayList<>();
ProgressDialog progressDialog;
RequestQueue requestQu;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
requestQu = Volley.newRequestQueue(getApplicationContext());
goster();
}
private void goster() {
progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Bilgiler alınıyor");
recyclerView=(RecyclerView) findViewById(R.id.listado);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
//recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this,LinearLayoutManager.HORIZONTAL,false));
recyclerView.setHasFixedSize(true);
adapter = new ListeleAdapter(listeles,this);
recyclerView.setAdapter(adapter);
JsonArrayRequest request = new JsonArrayRequest(url, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
for(int i=0;i<response.length();i++)
{
try {
JSONObject object = response.getJSONObject(i);
String resimurl=object.getString("resim");
String adi=object.getString("adi");
String stok=object.getString("stok");
String fiyat=object.getString("fiyat");
String aciklama=object.getString("aciklama");
listeles.add(new Listele(adi,fiyat,aciklama,stok,resimurl));
} catch (JSONException e) {
Toast.makeText(MainActivity.this,""+e,Toast.LENGTH_LONG).show();
}
}
adapter.notifyDataSetChanged();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
requestQu.add(request);
}
}
I didn't see your logcat but first of all you adding OnClickListener to your Button in wrong place. Add it in onBindViewHolder instead of ViewHolder constructor. In your code like that :
#Override
public void onBindViewHolder(urunlistem holder, int position) {
holder.adi.setText(tortica.get(position).getAdi());
holder.aciklama.setText(tortica.get(position).getAciklama());
holder.stok.setText(tortica.get(position).getStok());
holder.fiyat.setText(tortica.get(position).getFiyat());
Glide.with(contexto).load("http://192.168.1.33:8080/urunler/"+
tortica.get(position).getResim()).into(holder.tresim);
holder.button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String salutation="Merhaba | Hello | Здравствуйте | Hallo | Salut";
Toast.makeText(mContext,salutation,Toast.LENGTH_SHORT).show();
}
});
}
It's because you never inflated the button in your ViewHolder class. Remember how were supposed to "find the view" when using views in java lol? Do that.
hope this help you
package com.example.hp.myapplication;
//imports
public class ListeleAdapter extends RecyclerView.Adapter<ListeleAdapter.urunlistem> {
private Context contexto;
private ArrayList<Listele>tortica;
public ListeleAdapter(ArrayList<Listele> tortica, Context contexto ) {
this.contexto = contexto;
this.tortica = tortica;
}
#Override
public urunlistem onCreateViewHolder(ViewGroup parent, int viewType) {
return new urunlistem(LayoutInflater.from(parent.getContext()).inflate(R.layout.list,null));
}
#Override
public void onBindViewHolder(urunlistem holder, int position) {
holder.adi.setText(tortica.get(position).getAdi());
holder.aciklama.setText(tortica.get(position).getAciklama());
holder.stok.setText(tortica.get(position).getStok());
holder.fiyat.setText(tortica.get(position).getFiyat());
Glide.with(contexto).load("http://192.168.1.33:8080/urunler/"+tortica.get(position).getResim()).into(holder.tresim);
}
#Override
public int getItemCount() {
return tortica.size();
}
//Step 1: Implement View.OnClickListener as below
public static class urunlistem extends RecyclerView.ViewHolder implements View.OnClickListener{
ImageView tresim;
TextView adi,fiyat,stok,aciklama;
Button sepete_ekle;
ArrayList<Listele> listeles = new ArrayList<Listele>();
public urunlistem(View itemView) {
super(itemView);
tresim=(ImageView)itemView.findViewById(R.id.resim);
adi=(TextView)itemView.findViewById(R.id.adi_urun);
fiyat=(TextView)itemView.findViewById(R.id.fiyat);
stok=(TextView)itemView.findViewById(R.id.stok);
aciklama=(TextView)itemView.findViewById(R.id.aciklama);
//Step 2: Register Your Button here below
sepete_ekle=(Button)itemView.findViewById(R.id.button);
sepete_ekle.setOnClickListener(this);
}
#Override
public void onClick(View v) {
// Step 3: Redirect to next Activity From here
Intent intent = new Intent(contexto, NextActivity.class);
contexto.startActivity(intent);
}
}
}