从Android继续在Firebase数据库的现有阵列中插入新数据 [英] Continue insert new data in existing array in Firebase Database from Android
问题描述
我刚刚开始学习android studio,并且我正在基于位置的项目中将位置信息插入Firebase.我遵循了youtube上的教程[
从代码中插入索引为0、1、2和3的那个.现在,我试图继续从输入表单中插入数据,但是生成了随机密钥,并且无法创建新的地理围栏.反正有继续用硬键插入数据吗?
我当时想删除硬键,只使用生成的键,但是后来我不知道如何更改代码以创建多个地理围栏.
Firebase故意不提供使用顺序数字键插入项目的操作.参见:
也就是说,您可以使用具有顺序数字索引的类似数组的结构,并且可以使用自动标识.因此,让我们依次看一下.
使用顺序数字索引
要将键为 4
的新项目添加到当前结构中,您需要:
- 确定最高键
- 添加一个高一键的子节点
在最简单的格式下,它看起来像这样(在Android上):
FirebaseDatabase.getInstance().getReference("InfectedArea").child(位置").runTransaction(new Transaction.Handler(){@Overridepublic Transaction.Result doTransaction(MutableData mutableData){字符串lastKey ="-1";for(MutableData child:mutableData.getChildren){lastKey = child.getKey();}int nextKey = Integer.parseInt(lastKey)+1;mutableData.child(" + nextKey).setValue(此处的下一个值");//设置价值并报告交易成功返回Transaction.success(mutableData);}@Override公共无效onComplete(DatabaseError databaseError,boolean b,DataSnapshot dataSnapshot){//交易完成Log.d(TAG,"Transaction:onComplete:" + databaseError);}});
如您所见,这是很多代码.这是非常需要的,因为多个用户几乎可以同时访问同一位置,因此我们需要进行处理.Firebase使用乐观锁定,但是当有多个用户时,以上可能仍然会成为严重的瓶颈.另外:这比简单的 push().setValue(...)
复杂得多.
将自动编号用于您的初始数据集和新数据
一旦意识到只调用 push()
不会,就可以轻松地编写带有推送ID的所有点(这些点是 push()
生成的键).尚未写入数据库.您可以使用以下纯Android代码获取新的推送ID:
字符串pushID = ref.push().getKey();
知道了这一点,我们可以更改您的代码以将初始位置插入到:
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();//引用指向什么都没有关系,因为从统计角度上保证推入ID的唯一性,而与它们的位置无关.Map< String,Object>值=新的HashMap<>();被感染的区域.put(ref.push().getKey(),new LatLng(2.2258162,102.4497224));被感染的区域.put(ref.push().getKey(),new LatLng(2.2252313,102.4563797));被感染的区域.put(ref.push().getKey(),new LatLng(2.2261818,102.4551067));被感染的区域.put(ref.push().getKey(),new LatLng(2.275295,102.444035));FirebaseDatabase.getInstance().getReference("InfectedArea").child(位置").setValue(值).addOnCompleteListener(new OnCompleteListener< Void>(){@Overridepublic void onComplete(@NonNull Task< Void>任务){Toast.makeText(MapsActivity.this,"Updated!",Toast.LENGTH_SHORT).show();}}).addOnFailureListener(new OnFailureListener(){@Override公共无效onFailure(@NonNull异常e){Toast.makeText(MapsActivity.this," + e.getMessage(),Toast.LENGTH_SHORT).show();}});
这将产生与您所知道的类似的结构,但是所有键都是推送ID.
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.
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.
这篇关于从Android继续在Firebase数据库的现有阵列中插入新数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!