I want to add an object called funny_momments_row to an ArrayList called data, but it is not adding. I am checking that data is empty or not using isEmpty method afterwards. The code is running fine until this line:
funny_momments_row current = new funny_momments_row(dataSnapshot.child("like").getValue().toString(),dataSnapshot.child("url").getValue().toString());
Here is the complete class:
public class funny_moments extends Fragment {
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference("funnymomments");
ArrayList<funny_momments_row> data;
TextView tesgting;
private RecyclerView mRecyclerView;
public funny_moments() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_funny_moments, container, false);
mRecyclerView = (RecyclerView) view.findViewById(R.id.recylerview);
tesgting = (TextView) view.findViewById(R.id.test);
data = new ArrayList<>();
getData();
// Inflate the layout for this fragment
return view;
}
public void getData() {
funny_momments_row lu = new funny_momments_row("1", "hi");
myRef.child("video 0").setValue(lu);
myRef.child("video 0").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot videoSnapshot: dataSnapshot.getChildren()) {
funny_momments_row current = new funny_momments_row(dataSnapshot.child("like").getValue().toString(), dataSnapshot.child("url").getValue().toString());
data.add(current);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
if (data.isEmpty()) {
tesgting.setText("hi");
}
}
}
Try this because videoSnapsot is the data you need to add in the array list.
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot videoSnapshot: dataSnapshot.getChildren()) {
data.add(videoSnapshot.getValue(funny_momments_row.class));
//Create getter/setter method in funny_momments_row class if needed.
}
}
And, for funny_momments_row, java naming convention, please.
Related
I want to show data of all children inside all the Categories from the database (added the image below of what my database looks). I am adding data to my RecyclerView using the adapter which needs FirebaseRecyclerOptions object to be passed. I saw one answer where DataSnapshot was used to get child of child data, I tried to get the data using that and it showed me when I logged it in logcat (the commented code is what I tried using), but I do not know how to use that with my Adapter class.
This is what my database looks, I want the data inside of the highlighted fields:
{
"Category_wise": {
"education": {
"udemy": { <-Return data of this child
"companyName": "Udemy",
...
},
"khanacademy": { <-Return data of this child
"companyName": "Khan Academy",
...
}
},
"technology": {
"google": { <-Return data of this child
"companyName": "Google",
...
},
"facebook": { <-Return data of this child
"companyName": "Facebook",
...
},
....
}
}
In the below code, SCard is my Model Class and SCardAdapter is my Adapter Class.
This is my Fragment (HomeFragment) where I'm adding data into recyclerview:
public class HomeFragment extends Fragment{
private RecyclerView recyclerView;
private Query query;
private SCardAdapter<SCard, SCardAdapter.ViewHolder> adapter;
public HomeFragment() {}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_home, container, false);
recyclerView = v.findViewById(R.id.search_recyclerview);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setHasFixedSize(true);
setQueryByOrder("technology", "totalInvestors");
fetchResult(query);
return v;
}
// protected void fetchAll(){
// final DatabaseReference reference= FirebaseDatabase.getInstance().getReference("Category_wise");
// reference.addValueEventListener(new ValueEventListener() {
// #Override
// public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
// for (DataSnapshot snapshot : dataSnapshot.getChildren()){
// Log.i(TAG, "4321: Name of each company: " + Objects.requireNonNull(snapshot.child("companyName").getValue()).toString()
// }
// }
// #Override
// public void onCancelled(#NonNull DatabaseError databaseError) {}
// });
// }
protected void setQueryByOrder(String choice, String order){
query = FirebaseDatabase.getInstance()
.getReference()
.child("Category_wise").child(choice).orderByChild(order);
}
protected void fetchResult(Query query) {
FirebaseRecyclerOptions<SCard> options =
new FirebaseRecyclerOptions.Builder<SCard>()
.setQuery(query, new SnapshotParser<SCard>() {
#NonNull
#Override
public SCard parseSnapshot(#NonNull DataSnapshot snapshot) {
return new SCard(
Objects.requireNonNull(snapshot.child("companyName").getValue()).toString()...);
}
})
.build();
adapter = new SCardAdapter<>(options);
adapter.startListening();
recyclerView.setAdapter(adapter);
}
#Override
public void onStart() {
super.onStart();
adapter.startListening();
}
#Override
public void onStop() {
super.onStop();
adapter.stopListening();
}
}
This is my Adapter Class:
public class SCardAdapter<M extends SCard, V extends SCardAdapter.ViewHolder> extends FirebaseRecyclerAdapter<SCard, V> {
FirebaseRecyclerOptions<SCard> options;
public SCardAdapter(#Nullable FirebaseRecyclerOptions<SCard> options) {
super(options);
this.options = options;
}
#Override
protected void onBindViewHolder(V holder, #SuppressLint("RecyclerView") final int position, SCard model) {
holder.setName(model.getsName());
...
}
#Override
public V onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.startup_search_card, parent, false);
return (V) new ViewHolder(view);
}
public class ViewHolder extends RecyclerView.ViewHolder {
ImageView simg2;
TextView sname, sdesc, senddate, sperraised, snoin, sminam;
ProgressBar sraisingprogbar;
public ViewHolder(View itemView) {
super(itemView);
sname = itemView.findViewById(R.id.sname);
...
}
public void setName(String string) {
sname.setText(string);
}
...
}
}
First of all, you need to create 2 loops since your json looks like that and store them inside an arrayList. You are suppose to get all the data there inside the arrayList.
FirebaseDatabase.getInstance().getReference().child("Category_wise").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
ArrayList<Scard> sCardList = new ArrayList<Scard>();
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
if (snapshot.exists()){
for (DataSnapshot shot : snapshot.getChildren()){
if (shot.exists()){
final Scard scard = shot.getValue(Scard.class);
if (scard != null){
sCardList.add(scard);
}
}
}
}
}
final ScardAdapter scardAdapter = new ScardAdapter(sCardList);
recyclerView.setAdapter(scardAdapter);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
Next you need to create your own adapter. You can search on Google also for more information. But you will get the point here.
public class ScardAdapter extends RecyclerView.Adapter<ScardViewHolder> {
private ArrayList<Scard> sCardList;
public ScardAdapter(final ArrayList<Scard> sCardList) {
this.sCardList = sCardList;
}
#NonNull
#Override
public ScardViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.scard_item, parent, false);
return new ScardViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull final ScardViewHolder holder, final int position) {
final Scard model = sCardList.get(position);
holder.getTvCompanyName.setText(model.getCompanyName);
}
#Override
public int getItemCount() {
return sCardList.size();
}
}
I'm creating app with Firebase implementation. Now I'm stuck with showing list of data using recyclerView. After using my code I have empty activity without any error in Logcat but when turn off my mobile power button and again start then data show on recycleView. Also one thing when I go another activity and open this activity then again show blank page. I need someone's help :(
This is my fragment:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_message, container, false);
// Initialize
recyclerView = view.findViewById(R.id.recycleView);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
list = new ArrayList<>();
// For retrieve Chat User ID
databaseReference = FirebaseDatabase.getInstance().getReference().child("Chat");
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
list.clear();
for (DataSnapshot ds : snapshot.getChildren()) {
receiveID = ds.getKey();
// Restore Data on model class name UserDataInfo
databaseReference = FirebaseDatabase.getInstance().getReference().child("UsersData").child(receiveID);
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
String userName = String.valueOf(snapshot.child("userName").getValue());
String userNumber = String.valueOf(snapshot.child("userPhone").getValue());
String userType = String.valueOf(snapshot.child("userType").getValue());
String userImage = String.valueOf(snapshot.child("userName").getValue());
info = new UserDataInfo(userImage, userType, userNumber, userName, receiveID);
list.add(info);
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
// End
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
adapter = new messageListAdapter(list, getContext());
recyclerView.setAdapter(adapter);
}
My Adapter:
public class messageListAdapter extends RecyclerView.Adapter<messageListAdapter.ViewHolder> {
List<UserDataInfo> infoList;
Context context;
public messageListAdapter(List<UserDataInfo> infoList, Context context) {
this.infoList = infoList;
this.context = context;
}
#NonNull
#Override
public messageListAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.message_list_show_admin, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull messageListAdapter.ViewHolder holder, int position) {
final UserDataInfo userDataInfo = infoList.get(position);
holder.Name.setText(userDataInfo.getUserName());
holder.Number.setText(userDataInfo.getUserPhone());
holder.whichType.setText(userDataInfo.getUserType());
holder.linearLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(context, "ID: " + userDataInfo.getReceiveID(), Toast.LENGTH_SHORT).show();
}
});
}
#Override
public int getItemCount() {
return infoList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
ImageView Image;
TextView Name, Number, whichType;
LinearLayout linearLayout;
public ViewHolder(#NonNull View itemView) {
super(itemView);
Image = itemView.findViewById(R.id.UserImage);
Name = itemView.findViewById(R.id.Name);
Number = itemView.findViewById(R.id.Number);
whichType = itemView.findViewById(R.id.WhichType);
linearLayout = itemView.findViewById(R.id.Linear_layout);
}
}
}
my Firebase DataBase setup:
Database image
Database image
I would like to create a custom ListView populated by a custom ArrayAdapter. The code works fine, but the ListView is not showing data immediately. In order to have the data shown I need to click on a random EditText of the same page, close the Keyboard and magically the ListView shows data.
I don't know if it this can have an impact but the adapter is used in a fragment,which retrieve the data from Firebase during the OnCreate method.
Below my code, I removed everything not necessary for this topic and simplified the array.
This is my Class of elements inside the array:
public class ListItem {
private String Description;
private String Price;
public ListItem (String Description, String Price) {
this.Description = Description;
this.Price = Price;
}
public String getDescription() { return Description; }
public String getPrice() {
return Price;
}
public void setDescription(String description) {
Description = description;
}
public void setPrice(String price) {
Price = price;
}
}
The adapter is the following:
public class CustomListAdapter extends ArrayAdapter<ListItem> {
private Context mContext;
private Integer mResource;
private static class ViewHolder {
TextView txt_description_item;
TextView txt_price_item;
}
public CustomListAdapter(#NonNull Context context, int resource, #NonNull ArrayList<ListItem> objects) {
super(context, resource, objects);
mContext = context;
mResource = resource;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
String Description = getItem(position).getDescription();
String Price = getItem(position).getPrice();
LayoutInflater inflater = LayoutInflater.from(mContext);
convertView = inflater.inflate(mResource, parent, false);
ViewHolder viewHolder = new ViewHolder();
viewHolder.txt_description_item = convertView.findViewById(R.id.txt_description_item);
viewHolder.txt_price_item = convertView.findViewById(R.id.txt_price_item);
viewHolder.txt_description_item.setText(Description);
viewHolder.txt_price_item.setText(Price);
return convertView;
}
}
Finally this is the Fragment code:
public class MyFragment extends Fragment {
private ListView view_list_items;
private FirebaseDatabase database;
private DatabaseReference refDatabase;
private static final String USER = "user";
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
final View v = inflater.inflate(R.layout.fragment_myprofile, container, false);
view_list_items = v.findViewById(R.id.list_items);
database = FirebaseDatabase.getInstance();
refDatabase = database.getReference(USER);
refDatabase.child("items").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
final ArrayList<ListItem> arr_items = new ArrayList<>();
for (DataSnapshot ds : dataSnapshot.child("itemlist1").getChildren()) {
final String description = ds.getKey();
final String price = ds.getValue(String.class);
ListItem listItem = new ListItem(description,price);
arr_items.add(listItem);
}
CustomListAdapter adapter = new CustomListAdapter(getContext(),R.layout.layout_myItemList, arr_items);
view_list_items.setAdapter(adapter);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
EDIT:
I solved the issue by setting the adapter inside the 'for' cycle. Maybe it's not the most elegant solution but it works fine
for (DataSnapshot ds : dataSnapshot.child("itemlist1").getChildren()) {
final String description = ds.getKey();
final String price = ds.getValue(String.class);
ListItem listItem = new ListItem(description,price);
arr_items.add(listItem);
CustomListAdapter adapter = new
CustomListAdapter(getContext(),R.layout.layout_myItemList, arr_items);
view_list_items.setAdapter(adapter);
}
The firebase database is asynchronous i.e, the compiler doesn't wait for the code inside onDataChange() or onCancelled() to return a value. It would return all the values apart from those inside those 2 methods immediately, while for those 2 methods it would return the value when the value is available from the database. Below code might help you in better understanding
refDatabase.child("items").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
System.out.println("Inside onDataChange method");
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
System.out.println ("Outside onDataChange method");
The output will be like:
Outside onDataChange method
Inside onDataChange method
Notice that comes Outside onDataChange method first. This is the reason why your listView doesn't show data immediately.
What you can do to keep the user engaged is, add a spinner in your view which will be visible till the data is fetched from the database. To do this, try this code.
database = FirebaseDatabase.getInstance();
refDatabase = database.getReference(USER);
spinner.setVisibility(View.VISIBLE);
refDatabase.child("items").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
spinner.setVisibility(View.INVISIBLE);
//Your code goes here
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
//Error code goes here
}
});
I am trying to show some items in a RecyclerView and such items are contained in an ArrayList populated with RealtimeDatabase (Firebase) data. This is done every time some changes are detected in the db as follows. The problem is that lstCompany becomes null soon after the addValueEventListener. How can I keep it fulfilled?
public class FragmentCompanies extends Fragment {
View v;
private RecyclerView recyclerView;
private List<Company> lstCompany;
DatabaseReference db;
public FragmentCompanies(){}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
db = FirebaseDatabase.getInstance().getReference();
db.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
lstCompany = new ArrayList<>();
DataSnapshot ds = dataSnapshot.child("Company");
for (DataSnapshot company: ds.getChildren()){
Map<String, String> currCompany = (Map) company.getValue();
Company c = new Company(currCompany.get("name"), currCompany.get("overview"), currCompany.get("imageURL"));
lstCompany.add(c);
System.out.println(lstCompany);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
System.out.println(lstCompany);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState){
v = inflater.inflate(R.layout.fragment_companies,container,false);
System.out.println(lstCompany);
//bind the adapter to the recyclerView
recyclerView = v.findViewById(R.id.companies_recyclerview);
CompaniesRecyAdapter recyAdapter = new CompaniesRecyAdapter(getContext(), lstCompany);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.setAdapter(recyAdapter);
return v;
}
}
The last two println operations return null and it should not happen.
intialize the arraylist in onCreate, and when add data in on onDataChange and notify the adapter that data has been changed
public class FragmentCompanies extends Fragment {
View v;
private RecyclerView recyclerView;
private List<Company> lstCompany;
DatabaseReference db;
public FragmentCompanies(){}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState){
v = inflater.inflate(R.layout.fragment_companies,container,false);
lstCompany = new ArrayList<>();
System.out.println(lstCompany);
//bind the adapter to the recyclerView
recyclerView = v.findViewById(R.id.companies_recyclerview);
CompaniesRecyAdapter recyAdapter = new CompaniesRecyAdapter(getContext(), lstCompany);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.setAdapter(recyAdapter);
db = FirebaseDatabase.getInstance().getReference();
db.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
DataSnapshot ds = dataSnapshot.child("Company");
for (DataSnapshot company: ds.getChildren()){
Map<String, String> currCompany = (Map) company.getValue();
Company c = new Company(currCompany.get("name"), currCompany.get("overview"), currCompany.get("imageURL"));
lstCompany.add(c);
System.out.println(lstCompany);
System.out.println(c.getCompanyName);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
System.out.println(lstCompany);
return v;
}
}
Im facing this issue due to the asynchronous nature of Firebase database in my quiz app.Question score contains the current user and its score .Ranking contains the users and their corresponding marks.Question score has the score stored in it but when i am updating the ranking database with the score ... The value of marks in Ranking object is being reset to zero.How should i approach this?
I've already tried using Ranking Callback to update the database but no luck.
public class RankingFragment extends Fragment {
View myFragment;
RecyclerView rankingList;
LinearLayoutManager layoutManager;
FirebaseRecyclerAdapter<Ranking, RankingViewHolder> adapter;
FirebaseDatabase database;
DatabaseReference questionScore, rankingTbl;
String k;
int sum=0;
public static RankingFragment newInstance() {
RankingFragment rankingFragment = new RankingFragment();
return rankingFragment;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
database = FirebaseDatabase.getInstance();
questionScore = database.getReference("Question_Score");
rankingTbl = database.getReference("Ranking");
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
myFragment = inflater.inflate(R.layout.fragment_ranking, container, false);
rankingList = (RecyclerView) myFragment.findViewById(R.id.rankingList);
layoutManager = new LinearLayoutManager(getActivity());
rankingList.setHasFixedSize(true);
layoutManager.setReverseLayout(true);
layoutManager.setStackFromEnd(true);
rankingList.setLayoutManager(layoutManager);
updateScore(Common.currentUser.getUsername());
return myFragment;
}
private void updateScore(final String username)
{
questionScore.orderByChild("user").equalTo(username).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot data : dataSnapshot.getChildren()) {
QuestionScore ques = data.getValue(QuestionScore.class);
sum+=Integer.parseInt(ques.getScore());
}
Ranking ranking = new Ranking(username, sum);
rankingTbl.child(ranking.getUsername()).setValue(ranking);
adapter = new FirebaseRecyclerAdapter<Ranking, RankingViewHolder>(
Ranking.class, R.layout.layout_ranking, RankingViewHolder.class, rankingTbl.orderByChild("marks")
) {
#Override
protected void populateViewHolder(final RankingViewHolder viewHolder, Ranking model, int position) {
viewHolder.txt_name.setText(model.getUsername());
viewHolder.txt_score.setText(String.valueOf(model.getMarks()));
}
};
finish();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
private void finish() {
adapter.notifyDataSetChanged();
rankingList.setAdapter(adapter);
}
}
The marks of the ranking database are storing 0 and thus the view holder is also populated with zero whereas it should store the score of the current user(stored in "sum+=Integer.parseInt(ques.getScore());"
You are assigning the value from QuestionScore to sum instead it should be like adding all the QuestionScore values
for (DataSnapshot data : dataSnapshot.getChildren()) {
QuestionScore ques = data.getValue(QuestionScore.class);
sum+=Integer.parseInt(ques.getScore()); // <--- changed = to +=
}