Trying to replace a data from specific child (Firebase Database) - android

I want to replace kids/[id]/kidLimit/[new data]
So what I do is I make a spinner with kidName data, then with the selected item from that spinner I want to replace the data of kidLimit (with the same parent as the selected item from the spinner).
The first thing I do is to find the unique key of the selected item, then go to the kidLimit with that unique key to then use the setValue() method.
public class setLimit extends AppCompatActivity {
private DatabaseReference db;
private EditText etLimit;
private Button btnSetLimit;
private Spinner kidSpinner;
private String kidKey;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_set_limit);
etLimit = findViewById(R.id.et_limit);
btnSetLimit = findViewById(R.id.btn_confirm);
kidSpinner = findViewById(R.id.spinner_kid);
//PUTTING STRING LIST FROM FIREBASE TO SPINNER DROPDOWN STARTS HERE
db = FirebaseDatabase.getInstance().getReference().child("kids");
db.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
final List<String> kid = new ArrayList<>();
for (DataSnapshot dataSnapshot1: dataSnapshot.getChildren()) {
String kidName = dataSnapshot1.child("kidName").getValue(String.class);
kid.add(kidName);
}
ArrayAdapter<String> kidNameAdapter = new ArrayAdapter<>(setLimit.this, android.R.layout.simple_spinner_item, kid);
kidNameAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
kidSpinner.setAdapter(kidNameAdapter);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
//ENDS HERE
//ONCLICKLISTENER
btnSetLimit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
findId();
String newLimit = etLimit.getText().toString().trim();
db.child(kidKey).child("kidLimit").setValue(newLimit);
}
});
}
//FINDING KEY FROM THE SELECTED SPINNER ITEM
public void findId(){
String kidName = kidSpinner.getSelectedItem().toString();
db = FirebaseDatabase.getInstance().getReference().child("kids");
db.orderByChild("kidName").equalTo(kidName).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for(DataSnapshot dataSnapshot1:dataSnapshot.getChildren()){
kidKey = dataSnapshot1.getKey();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
So basically what I did was using the snapshot inside the onclick method to find the key. But when I check them on the log, it showed that the kidkey variable is null the first time I press the button, but after that it's not null anymore.
What can I to do so when I press the button, I can go to a specific child to replace it's data without getting any null pointer exception?
Here's the database that I use

When you do this
btnSetLimit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
findId();
String newLimit = etLimit.getText().toString().trim();
db.child(kidKey).child("kidLimit").setValue(newLimit);
}
});
findId(); is executed but you don't know when it will finish, so after that method is executed and waiting for data, this line
db.child(kidKey).child("kidLimit").setValue(newLimit);
will have kidKey with a null value because it has not been pulled yet from the database, so instead, you should move your code to the onDataChange() or make a new callback when all the asynchronous process finishes
btnSetLimit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
findId();
}
});
public void findId(){
String kidName = kidSpinner.getSelectedItem().toString();
String newLimit = etLimit.getText().toString().trim();
db = FirebaseDatabase.getInstance().getReference().child("kids");
db.orderByChild("kidName").equalTo(kidName).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for(DataSnapshot dataSnapshot1:dataSnapshot.getChildren()){
kidKey = dataSnapshot1.getKey();
}
db.child(kidKey).child("kidLimit").setValue(newLimit);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});

Related

Retrieve other values of child

So, I have this Firebase Structure.
I made an autocompletetext to get all child named "alimento".
That's OK!
But now, based on this "alimento" selection, I want to get all other childs in TextViews referent to this selection.
Is It possible? I don't know If I was clear enough.
This is my code: (I tried a lot of stuff, but all always return 0.00, so I won't put anything)
public class MainActivity extends AppCompatActivity {
private Button btnList, buttonAdicionar;
private AutoCompleteTextView autoCompleteTextView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnList = (Button) findViewById(R.id.btnList);
buttonAdicionar = (Button) findViewById(R.id.buttonAdicionar);
//Nothing special, create database reference.
final DatabaseReference database = FirebaseDatabase.getInstance().getReference();
//Create a new ArrayAdapter with your context and the simple layout for the dropdown menu provided by Android
final HRArrayAdapter<String> adapter = new HRArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line);
//Child the root before all the push() keys are found and add a ValueEventListener()
database.child("alimentos").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
adapter.clear();
//Basically, this says "For each DataSnapshot *Data* in dataSnapshot, do what's inside the method.
for (DataSnapshot suggestionSnapshot : dataSnapshot.getChildren()){
//Get the suggestion by childing the key of the string you want to get.
String autocomplete = suggestionSnapshot.child("alimento").getValue(String.class);
adapter.add(autocomplete);
adapter.notifyDataSetChanged();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
autoCompleteTextView = (AutoCompleteTextView) findViewById(R.id.acTV);
autoCompleteTextView.setAdapter(adapter);
autoCompleteTextView.setThreshold(1);
autoCompleteTextView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final String alimento = (String) parent.getItemAtPosition(position);
Log.d("TAG", alimento);
Toast.makeText(getApplicationContext(), alimento, Toast.LENGTH_SHORT).show();
}
});
btnList.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(getApplicationContext(), FoodActivity.class));
}
});
buttonAdicionar.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(getApplicationContext(), NewAlimentoActivity.class));
}
});
}
}
This is an example that what I want (using SQL):
If you're asking how to get all child nodes with a specific value in their alimento property, that'd be something like:
database.child("alimentos")
.orderByChild("alimento")
.equalTo("Arroz, integral, cozido")
.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()){
String base = snapshot.child("base").getValue(String.class);
double baseValue = Double.parseDouble(base);
...
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException(); // never ignore errors
}
});

Firebase push() method create multiple key continuously

I am trying to create a random key in a child on button click and insert data in this key
but When I click on the button it creates multiple keys with the same data and it goes continuously till I close the app in the background
above problem is in postreview() method in my code i call this method on the button clcik
public class DisplayStory extends AppCompatActivity {
TextView Tittle;
WebView webView;
String story;
String storyname;
String catagory;
String TAG = "display";
DatabaseReference storyref;
DatabaseReference ratingref;
RatingObject ratingObject;
// review stuff
RatingBar user_ratingBar;
EditText comment_EditText;
EditText senderName_editText;
Button submit;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_story);
Tittle = findViewById(R.id.TITLE);
webView = findViewById(R.id.webview);
// review stuff
user_ratingBar = findViewById(R.id.ratings_to_submit);
comment_EditText = findViewById(R.id.comment_to_submit);
senderName_editText = findViewById(R.id.sender_name);
submit = findViewById(R.id.submit_btn);
storyname = getIntent().getStringExtra("tittle");
catagory = getIntent().getStringExtra("catagory");
Log.d(TAG,"storyname "+storyname);
Log.d(TAG,"storyname "+catagory);
Tittle.setText(storyname);
storyref = FirebaseDatabase.getInstance().getReference(catagory).child(storyname);
ratingref = FirebaseDatabase.getInstance().getReference(catagory).child(storyname).child("rating");
submit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
PostReview();
}
});
storyref.child("story").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()){
story = dataSnapshot.getValue().toString();
webView.loadData(story,"text/html", "UTF-8");
webView.getSettings().setBuiltInZoomControls(true);
webView.getSettings().setDisplayZoomControls(false);
Log.d(TAG,"story exist ");
Log.d(TAG,"story "+story);
}
else {
Log.d(TAG,"no story exist ");
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
public void PostReview(){
final String name,comment;
final float rating;
name = senderName_editText.getText().toString();
comment = comment_EditText.getText().toString();
rating = user_ratingBar.getRating();
ratingref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
ratingObject =
new RatingObject(name,comment,rating);
ratingref.push().setValue(ratingObject);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
As far as I can see, there is no need to attach a listener in your PostReview method since you don't use any data from the dataSnapshot in there.
So in that case, the code can be much simpler:
public void PostReview(){
final String name,comment;
final float rating;
name = senderName_editText.getText().toString();
comment = comment_EditText.getText().toString();
rating = user_ratingBar.getRating();
ratingObject = new RatingObject(name,comment,rating);
ratingref.push().setValue(ratingObject);
}
This will also solve the endless loop, which was caused by calling setValue inside the onDataChange of a listener added with addValueEventListener. For a longer explanation of that, see:
Changing value in Firebase results in infinite loop
Insert data to firebase -Android - and check specific properties

In Android Studio, retrieving Data from Firebase does not work

When running the app the data is not retrieved but when debugging i can see where it is in terms of the database link.
When it runs and get to addValueEventListener, it doesn't go into the function which is pretty weird, don't know if this is because its async or not but either way data from Firebase does not get retrieved.
public GarbageItems(int itemNum) {
String itemId = String.valueOf(itemNum);
database = FirebaseDatabase.getInstance();
gameObjectRef = database.getReference().child("gameObjects");
itemInformationGrabber(gameObjectRef, itemId);
}//GarbageItems(Constructor)
private void itemInformationGrabber(DatabaseReference gameObjectRef, String itemId) {
DatabaseReference dataReference = gameObjectRef.child(itemId);
DatabaseReference itemColor = dataReference.child("Color");
itemColor.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange( DataSnapshot dataSnapshot) {
String color = dataSnapshot.getValue(String.class);
setColor(color);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
This is in a different classs that calls GarbageItem
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
colorTextView = findViewById(R.id.ColorTextView);
itemTextView = findViewById(R.id.ItemNameTextView);
GarbageItems garbageItems = new GarbageItems(1);
Color = garbageItems.getColor();
}
try this...
private void itemInformationGrabber(DatabaseReference gameObjectRef, String itemId) {
DatabaseReference dataReference = gameObjectRef.child(itemId);
DatabaseReference itemColor = dataReference.child("Color");
itemColor.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange( DataSnapshot dataSnapshot) {
for(Datasnapshot dataSnap : dataSnapshot.getChildren()){
String color = dataSnap.child("Color").getValue(String.class);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
Hope it helps you :)

Populating a Spinner with keys from a Firebase database, then another Spinner from the first's selection

I want to get all of the "Group No" keys in a single Spinner, then all of the "School No" keys of the selected "Group No" in a second Spinner.
Here's my database:
Here's my Java code:
public class Collection extends AppCompatActivity {
TextView ttl, tgat, tsch;
Button btnshw, btngt;
Spinner sping;
DatabaseReference d2ref;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_collection);
tgat = (TextView) findViewById(R.id.texigat);
tsch = (TextView) findViewById(R.id.texisch);
//tcls = (TextView) findViewById(R.id.texiclass);
ttl = (TextView) findViewById(R.id.texirs);
btnshw = (Button) findViewById(R.id.bshow);
btngt = (Button) findViewById(R.id.bgat);
sping = (Spinner) findViewById(R.id.spingat);
btnshw.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
d2ref = FirebaseDatabase.getInstance().getReference().child("2018-19").child("Group No 14")
.child("School no 109").child("Standard 2nd");
d2ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
String rs = dataSnapshot.child("Rupees").getValue().toString();
ttl.setText(rs);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
});
btngt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
d2ref = FirebaseDatabase.getInstance().getReference().child("2018-19");
ValueEventListener eventListener = new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
final List<String> grpno = new ArrayList<String>();
for (DataSnapshot dsnap : dataSnapshot.child("Group No 14").getChildren()) {
String grp = dsnap.getKey();
grpno.add(grp);
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(Collection.this, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
sping.setAdapter(adapter);
/*I wasn't able to get the value in 1st spinner so I didn't
wrote program for second spinner*/
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
};
d2ref.addListenerForSingleValueEvent(eventListener);
}
});
}
}
I've tried to fetch it in the TextView and increment the value with the Button, but the TextView gets only "Group No 2" in it.
Putting the key into a Spinner is as simple as putting the value into the Spinner. All you have to do is to remove the child() from the for loop.
Instead of doing this:
for (DataSnapshot dsnap : dataSnapshot.child("Group No 14").getChildren()) {
String grp = dsnap.getKey();
grpno.add(grp);
}
You have to do this:
for (DataSnapshot dsnap : dataSnapshot.getChildren()) {
String grp = dsnap.getKey();
grpno.add(grp);
}
Hope this helps..

PopulateView function being fired many times before stopping

I'm using the following code to fill a list with data from a child within firebase database. The list is filled successfully, but I've got an issue: FirebaseListAdapter is being called multiple times before stopping, what does not occur when I use it in other activities.
One weird thing is that when I click a specific listView item, data from another item is passed through my openChat intent, what makes wrong data be retrieved to the chat activity I open. It seems that the calling multiple times thing is messing all the data.
Can someone point out what might be wrong with my code and/or what I must do to optimize it?
//database references
chatsRef = FirebaseDatabase.getInstance().getReference().child("chats").child(mAuth.getCurrentUser().getUid()); //the children of this are other users IDs
usersRef = FirebaseDatabase.getInstance().getReference().child("users");
////////// code for populateView I use within FirebaseListAdapter ///////////
FirebaseListAdapter<ChatUsers> firebaseListAdapter = new FirebaseListAdapter<ChatUsers>(getActivity(), ChatUsers.class, R.layout.item_user_listing, chatsRef) {
protected void populateView(View view, ChatUsers chatUsers, int position) {
TextView nameChatItemList = (TextView) view.findViewById(R.id.nameChatItemList);
id_other_user = getRef(position).getKey();
usersRef.child(id_other_user).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//for (DataSnapshot ds : dataSnapshot.getChildren())
Toast.makeText(mActivity, dataSnapshot.getValue().toString(), Toast.LENGTH_SHORT).show();
name = dataSnapshot.child("name").getValue().toString();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent openChat= new Intent(getActivity().getApplicationContext(), Chat.class);
openChat.putExtra("iduser_chat", id_outro_usuario);
openChat.putExtra("name_user_chat", name);
startActivity(openChat);
}
});
}
}
EDIT Changes implemented as suggested by Farmaan
FirebaseListAdapter<ChatUsers> firebaseListAdapter = new FirebaseListAdapter<ChatUsers>(getActivity(), ChatUsers.class, R.layout.item_user_listing, ChatsRef) {
#Override
protected void populateView(View view, ChatUsers chatUsers, int position) {
TextView nomeImageChatItemList = (TextView) view.findViewById(R.id.nomeChatItemList);
String id_other_user = getRef(position).getKey();
usersRef.child(id_other_user).addListenerForSingleValue(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String name = dataSnapshot.child("name").getValue().toString();
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
usersRef.child(id_other_user).addListenerForSingleValue(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String name = dataSnapshot.child("name").getValue().toString();
Intent openChat = new Intent(getActivity().getApplicationContext(), Chat.class);
openChat.putExtra("iduser_chat", id_other_user);
openChat.putExtra("nameuser_chat", name);
startActivity(openChat);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
});
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
};
Since id_other_user and name are the class level field and you are updating it every time you populate the view.So the last view which is populated will decide the user id and the name.That's wrong with your code.
chatsRef = FirebaseDatabase.getInstance().getReference().child("chats").child(mAuth.getCurrentUser().getUid()); //the children of this are other users IDs
usersRef = FirebaseDatabase.getInstance().getReference().child("users");
////////// code for populateView I use within FirebaseListAdapter ///////////
protected void populateView (View view, ChatUsuarios chatUsuarios,int position){
TextView nameChatItemList = (TextView) view.findViewById(R.id.nameChatItemList);
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String id_other_user = getRef(position).getKey();
usersRef.child(id_other_user).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//for (DataSnapshot ds : dataSnapshot.getChildren())
String name = dataSnapshot.child("name").getValue().toString();
Intent openChat = new Intent(getActivity().getApplicationContext(), Chat.class);
openChat.putExtra("iduser_chat", id_other_user);
openChat.putExtra("name_user_chat", name);
startActivity(openChat);
Toast.makeText(mActivity, dataSnapshot.getValue().toString(), Toast.LENGTH_SHORT).show();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
});
}

Categories

Resources