问题
I'm just starting to learn android studio and I'm working on a location-based project to insert location information into Firebase. I followed tutorial from youtube [https://www.youtube.com/watch?v=CwxdfamaCrk], however in the video only shows insert data from the code which is like this;
infectedArea = new ArrayList<>();
infectedArea.add(new LatLng(2.2258162, 102.4497224));
infectedArea.add(new LatLng(2.2252313, 102.4563797));
infectedArea.add(new LatLng(2.2261818, 102.4551067));
infectedArea.add(new LatLng(2.275295,102.444035));
FirebaseDatabase.getInstance()
.getReference("InfectedArea")
.child("Location")
.setValue(infectedArea)
.addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
Toast.makeText(MapsActivity.this, "Updated!", Toast.LENGTH_SHORT).show();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Toast.makeText(MapsActivity.this, ""+e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
Below are the snapshot of my firebase.
The one with index 0, 1, 2 and 3 are inserted from the code. Now I'm trying to continue inserting data from an input form but random key was generated and new geofence cannot be created. Is there anyway to continue inserting data with hard key?
I was thinking on removing the hard key and just use the generated key but then I have no idea how to alter the code to create multiple geofence.
回答1:
it will stockpile at HashMap, so you can getkey
to get random key, and you get random key you can insert data
DatabaseReference database = FirebaseDatabase.getInstance().getReference("InfectedArea").child("Location");
database_course.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
for(DataSnapshot ds :dataSnapshot.getChildren()){
String key = ds.getKey();
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
回答2:
Firebase intentionally doesn't offer an operation for inserting items with a sequential numeric key. See:
- the documentation on structuring data
- The classic blog post on best practices when using arrays in Firebase
- How to create auto incremented key in Firebase?
That said, you can use array-like structures with sequential numerical indexes, and you can use auto-ids. So let's look at each in turn.
Using sequential numerical indexes
To add a new item with key 4
to your current structure, you will need to:
- Determine the highest key
- Add a child node with one key higher
In its simplest format, that looks like this (on Android):
FirebaseDatabase.getInstance()
.getReference("InfectedArea")
.child("Location")
.runTransaction(new Transaction.Handler() {
@Override
public Transaction.Result doTransaction(MutableData mutableData) {
String lastKey = "-1";
for (MutableData child: mutableData.getChildren) {
lastKey = child.getKey();
}
int nextKey = Integer.parseInt(lastKey) + 1;
mutableData.child("" + nextKey).setValue("your next value here");
// Set value and report transaction success
return Transaction.success(mutableData);
}
@Override
public void onComplete(DatabaseError databaseError, boolean b,
DataSnapshot dataSnapshot) {
// Transaction completed
Log.d(TAG, "Transaction:onComplete:" + databaseError);
}
});
As you can see that is quite a lot of code. This is largely needed because multiple users may be accessing the same location at almost the same time, and we need to handle this. Firebase uses optimistic locking, but the above may still be come a serious bottleneck when there are multiple users. Plus: this is a lot more complex than your simple push().setValue(...)
.
Use auto-ids for your initial set of data, and for new data
You can easily write all points with push IDs (those are the keys that push()
generates), once you realize that calling only push()
doesn't yet write to the database. You can get a new push ID in pure Android code with:
String pushID = ref.push().getKey();
Knowing this, we can change your code to insert the initial locations to:
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
// It doesn't matter what the reference points to, as push IDs are statistically guaranteed to be unique, independent of their location.
Map<String, Object> values = new HashMap<>();
infectedArea.put(ref.push().getKey(), new LatLng(2.2258162, 102.4497224));
infectedArea.put(ref.push().getKey(), new LatLng(2.2252313, 102.4563797));
infectedArea.put(ref.push().getKey(), new LatLng(2.2261818, 102.4551067));
infectedArea.put(ref.push().getKey(), new LatLng(2.275295,102.444035));
FirebaseDatabase.getInstance()
.getReference("InfectedArea")
.child("Location")
.setValue(values)
.addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
Toast.makeText(MapsActivity.this, "Updated!", Toast.LENGTH_SHORT).show();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Toast.makeText(MapsActivity.this, ""+e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
This will result in a similar structure as you know have, but then with all keys being push IDs.
来源:https://stackoverflow.com/questions/59313556/continue-insert-new-data-in-existing-array-in-firebase-database-from-android