How can I get distinct items from firebase to spinner in android? - java

I am trying to fill a spinner with categories, I manage to iterate every category in my database and add it to the spinner but I need to fetch only distinct values, see this image;
This is my code;
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
final List<String> categorySpinner = new ArrayList<>();
for (DataSnapshot childSpinner : snapshot.getChildren()) {
String spinnerCat = childSpinner.child("category").getValue(String.class);
categorySpinner.add(spinnerCat);
}
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(LineChartActivity.this, R.layout.spinner_item, categorySpinner);
arrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_item);
spinner_2.setAdapter(arrayAdapter);
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});

It's simple, simply change the line:
categorySpinner.add(spinnerCat);
to
if (!categorySpinner.contains(spinnerCat)) {
categorySpinner.add(spinnerCat);
}
Happy coding.

Related

recyclerview in FirebaseRecyclerviewAdapter turn all longth but write just one

I have a regular RecyclerView in FRA I set up in onbindviewholder class. İt turns longth as you see in app there is a space for all items normally I should see there reply text but just one can see.
dbreply.child(post_key).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for (DataSnapshot ds:snapshot.getChildren()) {
for (DataSnapshot snapshot1:ds.getChildren()) {
reply data = snapshot1.getValue(reply.class);
list.add(data);
holder.rcv.setLayoutManager(new LinearLayoutManager(getContext()));
myAdapter = new MyAdapter(getContext(), list);
holder.rcv.setAdapter(myAdapter);
myAdapter.notifyDataSetChanged();
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) { }});
You are getting that behavior because you are creating a new instance of MyAdapter at each iteration of the inner loop. What you should is to get all those 4 lines of code out of the loop, as you can see below:
for (DataSnapshot ds:snapshot.getChildren()) {
for (DataSnapshot snapshot1:ds.getChildren()) {
reply data = snapshot1.getValue(reply.class);
list.add(data);
}
holder.rcv.setLayoutManager(new LinearLayoutManager(getContext()));
myAdapter = new MyAdapter(getContext(), list);
holder.rcv.setAdapter(myAdapter);
myAdapter.notifyDataSetChanged();
}

How will I be able to get the value of this auto generated id I want them to be displayed in my recyclerview

This is my firebase database:
I want to display the value of the auto-generated id given by the push method
this is my code
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_recycler_view);
FirebaseApp.initializeApp(this);
recyclerView = findViewById(R.id.recyclerview);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
String key = newRef.getKey();
preRef.child(key).get();
list = new ArrayList<>();
myAdapter = new MyAdapter(this, list);
recyclerView.setAdapter(myAdapter);
preRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
Calendar calendar = dataSnapshot.getValue(Calendar.class);
list.add(calendar);
}
myAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
I cant display the value of the Uid can someone please help me?
To display the list of dates, you can do:
DatabaseReference actlogRef = FirebaseDatabase.getInstance().getReference("ActLog");
actlogRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for (DataSnapshot dataSnapshot : snapshot.child("date").getChildren()) {
String date = dataSnapshot.getValue(String.class);
list.add(date);
}
myAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
throw error.toException(); // never ignore errors
}
});
For this, list will have to be a list of strings, as that's what you store in the database. If you must use a list of Date objects, have a look at questions about parsing a data from a string in java.

Getting the key of its selected child value in a Spinner using Android Studio and Firebase

I'm trying to get the key of a certain child value by allowing the user to choose from a Spinner.
The Spinner has "Product_Name" values as its choices. By choosing one, the program should get its key and use it to get another child value for other uses.
Example:
PRODUCTS->
-LoUXnfUCEj4k4A3dkte->
Product_Name:"Steak"
By choosing "Steak" in the Spinner, I have to get "-LoUXnfUCEj4k4A3dkte"
databaseRefSelectItem = FirebaseDatabase.getInstance().getReference("PRODUCTS");
final DatabaseReference mDatabase = databaseRefSelectItem;
mDatabase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull final DataSnapshot dataSnapshot) {
//We create an array list to hold the values brought from the database and show them in the spinner
final List<String> titleList = new ArrayList<String>();
for(final DataSnapshot snapshot : dataSnapshot.getChildren()) {
titleProduct = snapshot.child("Product_Name").getValue(String.class);
//populate the spinner with that array list
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(AddTransactionActivity.this, android.R.layout.simple_spinner_item, titleList);
arrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
selectProduct.setAdapter(arrayAdapter);
titleList.add(titleProduct);
//Click event for each spinner element
selectProduct.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
//pass the reference from that value into another snapshot in order to query those values, here you need to get your node id and inside just get your number , name and so on
selectItem = titleList.get(i);
mDatabase.child(selectItem).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(final DataSnapshot dataSnapshot2) {
key = dataSnapshot2.getKey();
currentItemStock = dataSnapshot2.child(key).child("Current_Stock").getValue(String.class);
currentStk.setText(key);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
How can I get "-LoUXnfUCEj4k4A3dkte"?
Notes:
-LoUXnfUCEj4k4A3dkte is randomly generated.
Use .getKey() to get the key of the snapshot like:
for(final DataSnapshot snapshot : dataSnapshot.getChildren()) {
if (snapshot.child("Product_Name").getValue(String.class).equals("Steak")){
String theKey = snapshot.getKey(); //This will return -LoUXnfUCEj4k4A3dkte
}
}
Will return key of the snapshot at that reference.
Found a solution.
Thank you as well to Yash Krishan for the code snippet :).
databaseRefSelectItem = FirebaseDatabase.getInstance().getReference("PRODUCTS");
final DatabaseReference mDatabase = databaseRefSelectItem;
mDatabase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull final DataSnapshot dataSnapshot) {
//We create an array list to hold the values brought from the database and show them in the spinner
final List<String> titleList = new ArrayList<String>();
for(final DataSnapshot snapshot : dataSnapshot.getChildren()) {
titleProduct = snapshot.child("Product_Name").getValue(String.class);
//populate the spinner with that array list
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(AddTransactionActivity.this, android.R.layout.simple_spinner_item, titleList);
arrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
selectProduct.setAdapter(arrayAdapter);
titleList.add(titleProduct);
//Click event for each spinner element
selectProduct.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
//pass the reference from that value into another snapshot in order to query those values, here you need to get your node id and inside just get your number , name and so on
selectItem = titleList.get(i);
if (titleProduct.equals(selectItem)){
key = dataSnapshot.child(selectItem).getKey(); //This will return -LoUXnfUCEj4k4A3dkte
}
mDatabase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull final DataSnapshot dataSnapshot2) {
for(final DataSnapshot snapshot : dataSnapshot.getChildren()) {
if (snapshot.child("Product_Name").getValue(String.class).equals(selectItem)){
key = snapshot.getKey().toString();
}
keyholder = dataSnapshot.child(key).child("Current_Stock").getValue(String.class);
}
currentStk.setText(keyholder);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});

Firebase listener in listener skipped

In my app I use the firebase database. There are questions and the corresponding comments stored in seperat nodes. Now I try to get the questions with the one listener and access the comments with a second listener. Unfortunately I‘m confused by their behavior: the recyclerView always gets an empty questionsList, like the second listener is skipped. But after the recyclerView got the list and the adapter is set up, my LogCat starts printing the questions and the comment information.
But why is the recyclerView populated and used before the for loop that processes the data has finished?
The method to fetch the information:
private void getQuestionsFromDatabase() {
mQuestions.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
questionList = new ArrayList<>();
for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
final String title = dataSnapshot1.child("title").getValue().toString();
final String question = dataSnapshot1.child("question").getValue().toString();
final String commentId = dataSnapshot1.child("commentId").getValue().toString();
mComments.child(commentId).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
count = dataSnapshot.getChildrenCount();
QuestionModel questionModel = new QuestionModel(title, question, commentId, String.valueOf(count));
questionList.add(questionModel);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
Log.d("questionList length: ", String.valueOf(questionList.size()));
recyclerViewAdapter = new RecyclerViewQuestionAdapter(questionList, getActivity());
recyclerViewlayoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(recyclerViewlayoutManager);
recyclerView.setAdapter(recyclerViewAdapter);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
It is used before, because the onDataChange is asynchronous, which means that the compiler will not wait until data is fetched from the database, instead it will execute the code after the listener. Therefore to solve your problem, you should do the following:
mComments.child(commentId).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
count = dataSnapshot.getChildrenCount();
QuestionModel questionModel = new QuestionModel(title, question, commentId, String.valueOf(count));
questionList.add(questionModel);
Log.d("questionList length: ", String.valueOf(questionList.size()));
recyclerViewAdapter = new RecyclerViewQuestionAdapter(questionList, getActivity());
recyclerViewlayoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(recyclerViewlayoutManager);
recyclerView.setAdapter(recyclerViewAdapter);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}

Android Firebase - Change listview data from firebase based on spinner

Hi I'm trying to display certain data on my listview based on item selected from a spinner. This is how the display page currently looks. It's reading all the data from the node. Because "Running" is selected on the spinner above, I want the list view to only show Running.
Here is the code i'm using to read all the data.
#Override
protected void onStart() {
super.onStart();
//reading data to listview, every time its saved
currentUserDB2.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
cardiosList.clear();
for(DataSnapshot cardioHistorySnapshot : dataSnapshot.getChildren()){
Cardio cardio = cardioHistorySnapshot.getValue(Cardio.class);
cardiosList.add(cardio);
}
CardioHistoryList adapter = new CardioHistoryList(Cardio_History.this, cardiosList);
ListViewCardioHistory.setAdapter(adapter);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
Working code
spinnerCardioHistory.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
String name = spinnerCardioHistory.getSelectedItem().toString();
currentUserDB2.orderByChild("detailCategory").equalTo(name).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
cardiosList.clear();
for (DataSnapshot cardioHistorySnapshot : dataSnapshot.getChildren()){
Cardio cardio = cardioHistorySnapshot.getValue(Cardio.class);
cardiosList.add(cardio);
}
CardioHistoryList adapter = new CardioHistoryList(Cardio_History.this, cardiosList);
ListViewCardioHistory.setAdapter(adapter);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
If you want only the word Running to be displayed then do the following:
String text = spinner.getSelectedItem().toString();
FirebaseUser user=FirebaseAuth.getInstance().getCurrentUser();
DatabaseReference currentUserDB2=FirebaseDatabase.getInstance().getReference().child("Cardio").child(user.getUid());
currentUserDB2.orderByChild("detailCategory").equalTo(text).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
cardiosList.clear();
for(DataSnapshot cardioHistorySnapshot : dataSnapshot.getChildren()){
String category=cardioHistorySnapshot.child("detailCategory").getValue().toString();
cardiosList.add(category);
}
CardioHistoryList adapter = new CardioHistoryList(Cardio_History.this, cardiosList);
ListViewCardioHistory.setAdapter(adapter);
First you get the select texted that is in the spinner String text = spinner.getSelectedItem().toString();
then you add it in the query orderByChild("detailCategory").equalTo(text) and then retrieve from the database and it will only add the word that is selected in the spinner which is "Running".

Categories