I am developing a bus booking app. But I have a problem with the update and delete function. I am able to update the timings and price. But whenever I try to update the source or destination or bus number...my app gets stuck. When I checked my Firebase realtime database....it looks as if the value is stuck in an infinite loop...as the updated value...keeps getting changed from the old to the new value and new value to the old value continuously. This is causing my app to get stuck. I have two files with regard to this.
- EditBus.java
package com.example.busticketbooking;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import java.util.HashMap;
import java.util.Map;
public class Edit_Bus extends AppCompatActivity {
//Variables
public EditText busNumEdit,srcEdit,destEdit,timingsEdit,priceEdit;
private DatabaseReference databaseReference;
public String BusID;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_edit_bus);
busNumEdit =findViewById(R.id.BusNumber);
srcEdit=findViewById(R.id.source);
destEdit=findViewById(R.id.dest);
timingsEdit=findViewById(R.id.timings);
priceEdit=findViewById(R.id.price);
Button deleteButton = findViewById(R.id.deletebtn);
Button updateButton = findViewById(R.id.updatebtn);
FirebaseDatabase firebaseDatabase = FirebaseDatabase.getInstance();
BusRVModel busRVModel = getIntent().getParcelableExtra("Bus");
if(busRVModel !=null){
busNumEdit.setText(busRVModel.getBusNum());
srcEdit.setText(busRVModel.getSrc());
destEdit.setText(busRVModel.getDest());
timingsEdit.setText(busRVModel.getTimings());
priceEdit.setText(busRVModel.getPrice());
BusID= busRVModel.getBusID();
}
databaseReference= firebaseDatabase.getReference("Bus").child(BusID);
updateButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String busNumVar= busNumEdit.getText().toString();
String srcVar=srcEdit.getText().toString();
String destVar=destEdit.getText().toString();
String timingsVar=timingsEdit.getText().toString();
String priceVar=priceEdit.getText().toString();
Map<String,Object> map=new HashMap<>();
map.put("busNum", busNumVar);
map.put("src",srcVar);
map.put("dest",destVar);
map.put("timings",timingsVar);
map.put("price",priceVar);
map.put("busID",BusID);
databaseReference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
databaseReference.updateChildren(map);
Toast.makeText(Edit_Bus.this, "Bus updated", Toast.LENGTH_SHORT).show();
startActivity(new Intent(Edit_Bus.this,MainActivity2.class));
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
Toast.makeText(Edit_Bus.this, "Update Error", Toast.LENGTH_SHORT).show();
}
});
}
});
deleteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
deleteBus();
}
});
}
private void deleteBus(){
databaseReference.removeValue();
Toast.makeText(this, "Bus Deleted!!!", Toast.LENGTH_SHORT).show();
startActivity(new Intent(Edit_Bus.this,MainActivity2.class));
}
}
- BusRVModel.java
package com.example.busticketbooking;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.ArrayList;
public class BusRVModel implements Parcelable{
private String busNum;
private String src;
private String dest;
private String timings;
private String price;
private String BusID;
public BusRVModel() {
}
public BusRVModel(String busNum, String src, String dest, String timings, String price, String busID ) {
this.busNum = busNum;
this.src = src;
this.dest = dest;
this.timings = timings;
this.price = price;
BusID = busID;
}
protected BusRVModel(Parcel in) {
busNum = in.readString();
src = in.readString();
dest = in.readString();
timings = in.readString();
price = in.readString();
BusID = in.readString();
}
public static final Creator<BusRVModel> CREATOR = new Creator<BusRVModel>() {
@Override
public BusRVModel createFromParcel(Parcel in) {
return new BusRVModel(in);
}
@Override
public BusRVModel[] newArray(int size) {
return new BusRVModel[size];
}
};
public String getBusNum() {
return busNum;
}
public void setBusNum(String busNum) {
this.busNum = busNum;
}
public String getSrc() {
return src;
}
public void setSrc(String src) {
this.src = src;
}
public String getDest() {
return dest;
}
public void setDest(String dest) {
this.dest = dest;
}
public String getTimings() {
return timings;
}
public void setTimings(String timings) {
this.timings = timings;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String getBusID() {
return BusID;
}
public void setBusID(String busID) {
BusID = busID;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeString(busNum);
parcel.writeString(src);
parcel.writeString(dest);
parcel.writeString(timings);
parcel.writeString(price);
parcel.writeString(BusID);
}
}
- AddBus.java
package com.example.busticketbooking;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
public class Add_Bus extends AppCompatActivity {
private EditText busNum,src,dest,timings,price;
private Button button;
private FirebaseDatabase firebaseDatabase;
private DatabaseReference databaseReference;
private String BusID;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_bus);
busNum=findViewById(R.id.BusNumber);
src=findViewById(R.id.source);
dest=findViewById(R.id.dest);
timings=findViewById(R.id.timings);
price=findViewById(R.id.price);
button=findViewById(R.id.btn);
firebaseDatabase=FirebaseDatabase.getInstance();
databaseReference=firebaseDatabase.getReference("Bus");
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String busNumVar=busNum.getText().toString();
String srcVar=src.getText().toString();
String destVar=dest.getText().toString();
String timingsVar=timings.getText().toString();
String priceVar=price.getText().toString();
BusID=busNumVar;
BusRVModel busRVModel=new BusRVModel(busNumVar,srcVar,destVar,timingsVar,priceVar,BusID);
databaseReference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
databaseReference.child(BusID).setValue(busRVModel);
Toast.makeText(Add_Bus.this, "Bus added", Toast.LENGTH_SHORT).show();
startActivity(new Intent(Add_Bus.this,MainActivity2.class));
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
Toast.makeText(Add_Bus.this, "Error is: " error.toString(), Toast.LENGTH_SHORT).show();
}
});
}
});
}
}
CodePudding user response:
The problem is here:
databaseReference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
databaseReference.updateChildren(map);
Toast.makeText(Edit_Bus.this, "Bus updated", Toast.LENGTH_SHORT).show();
startActivity(new Intent(Edit_Bus.this,MainActivity2.class));
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
Toast.makeText(Edit_Bus.this, "Update Error", Toast.LENGTH_SHORT).show();
}
});
You're adding a listener to the database by calling addValueEventListener
, which is documented as:
This method is triggered once when the listener is attached and again every time the data, including children, changes.
Now inside the onDataChange
you modify the data at databaseReference
, and as the documentation says that leads to onDataChange
being called again, which leads to you updating the data again, which leads to...
Since it seems you only want to update the data once, you can use addListenerForSingleValueEvent
to prevent retriggering onDataChange
:
//