sorry I don't speak very well English.
My problem is that in the next fragment of code,
in valueEventListener, not enter, I don't know why, so, I can't getValue of "cantidad" of my realtime database.
The databaseReference get correctly, but when get the line eventValueEventListener = new Value..., not enter in onDataChange() method.
What is the problem?
Thanks.
btnGoToEvent.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(auth != null && btnGoToEvent.getText().equals("¡ME APUNTO!")) {
btnGoToEvent.setText("Al final no voy a ir");
databaseReference = FirebaseDatabase.getInstance().getReference().child("Eventos").child(String.valueOf(position));
valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
cantidad = Integer.parseInt(dataSnapshot.child("cantidad").getValue().toString());
cantidad++;
databaseReference.setValue(cantidad);
databaseReference.push().setValue(new User(auth.getEmail()));
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
};
}else if(auth != null && btnGoToEvent.getText().equals("Al final no voy a ir")){
btnGoToEvent.setText("¡ME APUNTO!");
}else{
Toast.makeText(getApplicationContext(), "Necesita estar registrado para apuntarse", Toast.LENGTH_LONG).show();
}
}
});
All you're doing there is creating a new ValueEventListener. That won't get any callback until you add it to a Reference to listen to.
Maybe you meant to also write this line to set that up?
databaseReference.addValueEventListener(valueEventListener);
Related
I'm a beginner & I don't know most of the Android Paradigms please help!!
Sorry!! if anyone find's this question a duplicate.
I'm facing a problem with ProgressDialog dismissing on null reference during loading of a Spinner.
It happens once during disconnecting & reconnecting to Internet, but before disconnection everything works fine i.e the loading stops when there is something in the Spinner
I've set the dismiss() method to execute when there is something in the Spinner using if() statement, but I don't know how it executes before it finds something in the Spinner, I've even set a Regex so that the dialog should get dismissed when it matches the Regex & even after this the dialog dismisses anyway.
Here's my code
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
spingroup = (Spinner) findViewById(R.id.spingrp);
if(Connection.isConn(this)) {
Toast.makeText(this, "No internet connection detected, please check your internet connection", Toast.LENGTH_SHORT).show();
AlertDialog alertDog = new AlertDialog.Builder(this).create();
alertDog.setTitle("No Internet!!");
alertDog.setMessage("Please connect to internet & try again");
alertDog.setIcon(R.drawable.no_internet);
alertDog.setCanceledOnTouchOutside(false);
alertDog.setButton("Exit", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
alertDog.show();
}
if (!Connection.isConn(this)){
progress = ProgressDialog.show(MainActivity.this, "Loading Group","Please wait!!", true);
progress.setCancelable(true);
progress.setIcon(R.drawable.list_icon);
}
//Yes this if() statement gets called before the null reference error
dbrefspingrp = FirebaseDatabase.getInstance().getReference();
dbrefspingrp.child("2018-19").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
final List<String> listgrp = new ArrayList<String>();
listgrp.add("--Select Group--");
for (DataSnapshot grpsnap: dataSnapshot.getChildren()){
String group = grpsnap.getKey();
listgrp.add(group);
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_spinner_item,listgrp );
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
adapter.notifyDataSetChanged();
spingroup.setAdapter(adapter);
String test = listgrp.get(listgrp.size()-1);
boolean reg = Pattern.matches("(?i)group no [0-9]{2}", test);
if (reg == true) {
progress.dismiss();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
My Attempts
1-
if (spingroup.getSelectedItem().toString().equals("--Select Group--")) {
progress.dismiss();
}
2-
if (!spingroup.getSelectedItem().toString().equals(null)) {
progress.dismiss();
}
3-
if (spingroup.getSelectedItem().toString().equals("--Select Group--") && spingroup.getSelectedItem.toString != (null) {
progress.dismiss();
}
Your problem is that the ProgressDialog progress is null. Probably because this part of the code is never called (or at least not before you try to access the ProgressDialog):
if (!Connection.isConn(this)){
progress = ProgressDialog.show(MainActivity.this, "Loading Group","Please wait!!", true);
progress.setCancelable(true);
progress.setIcon(R.drawable.list_icon);
}
You can avoid the exception by checking your ProgressDialog before accessing it like:
if (progress != null && progress.isShowing()) {
progress.dismiss();
}
I have a question about list. I have a list that save more than one data. and then, when I run my apps it work and show the data. but when I debug and want to check the size of my list just show 0 of size. what is the problem?
please help.
this is my code :
query.addValueEventListener(new com.firebase.client.ValueEventListener() {
#Override
public void onDataChange(com.firebase.client.DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
for (com.firebase.client.DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
SisaKendaraanModel sisaModel = postSnapshot.getValue(SisaKendaraanModel
if (//somecondition) {
if (//somecondition) {
kendaraanModel.add(kendaraan);
adapter.notifyDataSetChanged();
} else {
kendaraanModel.remove(kendaraan);
adapter.notifyDataSetChanged();
break;
}
} else {
if (//somecondition) {
kendaraanModel.add(kendaraan);
adapter.notifyDataSetChanged();
} else {
kendaraanModel.remove(kendaraan);
adapter.notifyDataSetChanged();
break;
}
}
}
} else {
if (//somecondition) {
kendaraanModel.add(kendaraan);
adapter.notifyDataSetChanged();
} else {
kendaraanModel.remove(kendaraan);
adapter.notifyDataSetChanged();
}
}
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
}
} else {
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
long sizeKendaraanModel = kendaraanModel.size(); // it show 0
adapter = new MenuHasilPencarianAdapter(MenuHasilPencarian.this, kendaraanModel, tanggalSewaPencarian, tanggalKembaliPencarian, jumlahKendaraanPencarian);
recyclerView.setAdapter(adapter);
This is my debug result:
See you are making asynchronous call addValueEventListener . your code below is going to call just after setting listener.
long sizeKendaraanModel = kendaraanModel.size();
So this will give you size 0 each time cause its called sequentially. The onDataChange not called yet cause its an Asynchronous call .
You can match this scenario the when we start and new thread and its runs in its own flow(the run() method) then we have to wait for response .
So what you can do is .
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot != null) {
// Add remove your value here
}
long sizeKendaraanModel = kendaraanModel.size();
adapter = new MenuHasilPencarianAdapter(MenuHasilPencarian.this, kendaraanModel, tanggalSewaPencarian, tanggalKembaliPencarian, jumlahKendaraanPencarian);
recyclerView.setAdapter(adapter);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Also in your code i am seeing lots of adapter.notifyDataSetChanged(); . If you are using recycler view notifyDataSetChanged() is most expensive in term of just notifying the the list for changes . So make Use of .
notifyItemRangeChanged()
notifyItemChanged()
notifyItemInserted()
notifyItemRemoved()
This is because You are adding value in "kendaraanModel" after Initializing Recycler
and after adding values in "kendaraanModel" , You have added > adapter.notifyDataSetChanged(); i.e affecting the list..
So,
if you want to check size You can check it in "OnDataChange"
Hello so I've been strugging for awhile now. I want to consult someone about my code. I want to apply
a coloring function to my app.
When the person presses the button when it's at its:
GREEN state it updates the value on the database to BEING HOUSEKEPT
YELLOW state when pressed sends READY FOR INSPECTION RoomStatus
RED state when pressed sends READY FOR HOUSEKEEPING RoomStatus
It was working earlier but when I tried to restrict the users that users who are Housekeepers can't access the RED STATE which are for House Keepers, I inserted somewhere in my code where I want to implement it.
I'm going over loops here can somebody tell me where I did wrong?
Here's my code:
Button room1;
private DatabaseReference mFirebaseDatabase, mFirebaseDatabase1, mFirebaseDatabase1room;
private FirebaseDatabase mFirebaseInstance;
private DatabaseReference referenceroom1;
private String roomStat;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_navi_to_scan2);
mFirebaseInstance = FirebaseDatabase.getInstance();
mFirebaseDatabase1 = mFirebaseInstance.getReference("Rooms");
mFirebaseDatabase = mFirebaseInstance.getReference("Users");
mFirebaseDatabase1room = mFirebaseInstance.getReference("Rooms").child("Room1");
referenceroom1 = mFirebaseDatabase1.child("Room1").child("RoomStatus");
room1 = (Button) findViewById(R.id.rm1Btn);
mFirebaseDatabase1.child("Room1").addValueEventListener(new ValueEventListener() { //attach listener
#Override
public void onDataChange(DataSnapshot dataSnapshot) { //something changed!
for (DataSnapshot locationSnapshot : dataSnapshot.getChildren()) {
String location = locationSnapshot.getValue().toString();
if (location.equals("READY FOR HOUSEKEEPING")) {
room1.setBackgroundColor(Color.GREEN);
roomStat = "Green";
} else if (location.equals("BEING HOUSEKEPT")) {
room1.setBackgroundColor(Color.YELLOW);
roomStat = "Yellow";
} else {
room1.setBackgroundColor(Color.RED);
roomStat = "Red";
}
if (roomStat.equals("Green")) {
room1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String message = "BEING HOUSEKEPT";
DatabaseReference reference = mFirebaseDatabase1.child("Room1").child("RoomStatus");
reference.setValue(message);
Intent next1 = new Intent(getApplicationContext(), ReaderActivity3.class);
startActivity(next1);
}
});
} else if (roomStat.equals("Yellow")) {
room1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String message = "READY FOR INSPECTION";
DatabaseReference reference = mFirebaseDatabase1.child("Room1").child("RoomStatus");
reference.setValue(message);
Intent next1 = new Intent(getApplicationContext(), ReaderActivity2.class);
startActivity(next1);
}
});
} else {
room1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String message = "READY FOR HOUSEKEEPING";
DatabaseReference reference = mFirebaseDatabase1.child("Room1").child("RoomStatus");
reference.setValue(message);
Intent next1 = new Intent(getApplicationContext(), ReaderActivity.class);
startActivity(next1);
//I ALSO WANT TO PUT A CONDITION HERE FETCHING userType from Structure
// mFirebaseDatabase = mFirebaseInstance.getReference("Users").child("userKey");
//but doing this would mean that I would have to put a listener inside, would that be okay? I tried when this
//was working at first but it didin't and now the whole thing is not working
}
});
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) { //update UI here if error occurred.
}
});
}
Here's my structure:
Can you help me identify what's the problem with how i implemented this?
I see nothing wrong, try debugging. Android is buggy nowadays, especially when you're connecting to a cloud database. In the left side of the run button the bug shaped one. Debug.
Or maybe you could try to show your location which is your string, to check if you pulled the right info from your database. You can use logs. A guide can be found here
https://developer.android.com/studio/debug/am-logcat.html
I have put a button in my App. When I press the button +1 value saves to my database. So I want to check a method that when the button count =5 show an alert.It checks when i click the button. When my button count =5 alert shows 3-4 times. But I want to show it for 1 time :(
Here is the code :
private void ButtonChecker(){
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference ezzeearnRef = rootRef.child(User1);
ValueEventListener eventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Long BRef1 = dataSnapshot.child("BRef").getValue(Long.class);
assert BRef1 != null;
int x = BRef1.intValue( );
ref = x;
if (x ==5){
showAlert("Don't CLick Button ");
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
};
ezzeearnRef.addValueEventListener(eventListener);
}
You're registering a new listener every time that the user presses the button. If the initial value is 3, the user has to press the button twice to get it to 5. That means your code registers two listeners and thus shows two alerts.
Two solutions:
Only register a listener once.
Register listeners that only get the current value.
Register listeners that only get the current value
This is the simplest change: we'll register a listener that:
Reads the current value
Automatically unregisters itself
The only change is how you register the listener:
ezzeearnRef.addListenerForSingleValueEvent(eventListener);
But this still registers/unregisters a listener for every click, which can be a bit wasteful. In addition: if you ever make your app multi-user, this misses the fact that other users may be incrementing the counter too.
Only register a listener once
Whenever possible, register and unregister your listeners in activity-lifecycle methods. For example, it is quite common to register the listeners in onStart and unregister them in onStop:
#Override
protected void onStart() {
super.onStart();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference ezzeearnRef = rootRef.child(User1);
ValueEventListener eventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Long BRef1 = dataSnapshot.child("BRef").getValue(Long.class);
assert BRef1 != null;
int x = BRef1.intValue( );
ref = x;
if (x ==5){
showAlert("Don't CLick Button ");
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException(); // don't ignore errors
}
};
ezzeearnRef.addValueEventListener(eventListener);
}
#Override
protected void onStop() {
super.onStop();
ezzeearnRef.removeEventListener(eventListener);
}
With this code your listener will be active during the lifecycle of the activity. During that time, if the counter (is or) becomes 5, the alert will show once.
Sometime firebase call for data multiple time so you will get same x value more then one time. to fix this use a boolean variable which store value about alert.
boolean isAlertShown = false;
private void ButtonChecker(){
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference ezzeearnRef = rootRef.child(User1);
ValueEventListener eventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Long BRef1 = dataSnapshot.child("BRef").getValue(Long.class);
assert BRef1 != null;
int x = BRef1.intValue( );
ref = x;
if (x ==5 && !isAlertShown){
isAlertShown = true;
showAlert("Don't CLick Button ");
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
};
ezzeearnRef.addValueEventListener(eventListener);
}
I have a textView in my activity - say, "Username". It is supposed to be populated from a Firebase database. I am making the Firebase query in Asynctask so as not to block the activity. However that means that the TextView loads first, before the Firebase query is completely executed.
So what is the best way to refresh this textBox after the Firebase query is executed inside the AsyncTask and the username gets known?
I do not want to showprogressBar and block the activity while the data is being fetched from the database. That would defeat the purpose of doing it in AsyncTask.
Code for the AsyncTask is below
private class CheckUserLoginAndRetrieveDataFromFirebase extends AsyncTask <Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... voids) {
if (thisAppUser!=null) {
setUserDataForToday();
if (createNewNode) { //This is the first time the User is logging in
createUsersNodesForFirstTime();
}
}
return null;
}
Code for my Firebase Query in the AsyncTask is below
public static void setUserDataForToday() {
setProperDatabaseReference(); //This sets reference to user specific nodes in the database
myRef.child("dashboard").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Dashboard dashboard = dataSnapshot.getValue(Dashboard.class);
if (dataSnapshot.getChildrenCount() > 0) {
createNewNode = false;
if (dashboard.checkIfTodaysDateExistsInDatabase()) {
//An entry for todays date exists in database, so no data change needed
myDashboard = dashboard;
}
I hope this example will help you
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setUserDataForToday();
Log.d("MainActivity", "Process is not blocked");
}
public void setUserDataForToday() {
Log.d("MainActivity", "Called method");
DatabaseReference database = FirebaseDatabase.getInstance().getReference();
database.child("users").child("1").child("name").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
String userName = dataSnapshot.getValue(String.class);
Log.d("MainActivity", "Received value: " + dataSnapshot.getValue());
dataSnapshot.getKey();
TextView textView = (TextView) findViewById(R.id.textUserName);
textView.setText(userName);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.d("MainActivity", "DB error: " + databaseError.getMessage());
}
});
}
public void onClick(View v) {
setUserDataForToday();
}
}
If you are working with Android studio click tools>Firebase>Realtime Database and follow instructions. This will get you started. You probably want to click tools>firebase>authentication if you want to have users and if you want only certain users to access certain things configure rules for the database. Frank is correct no need for async task.