从 Firebase 数据库 Android 保存和检索数据
Posted
技术标签:
【中文标题】从 Firebase 数据库 Android 保存和检索数据【英文标题】:Save and retrieve data from firebase database Android 【发布时间】:2021-05-07 22:31:50 【问题描述】:我正在开展一个项目,我必须根据用户在地图上选择的位置进行自定义“游览/旅行”。 每次旅行都有一个标题,以及他选择的地点。 例如,他做了一个旅行(列表)并将其称为“Tour 1”,在这个“Tour 1”中,他首先想去酒店,然后去肯德基,然后去海滩。
我到了我列了一个列表并给它一个标题的地步,但是无法显示我在活动中计划去的地方,这是活动的截图activity example,这里是我的实时数据库的屏幕截图。
所以我想显示我计划去的所有地方,在活动中显示“Place 1”。 这是我的代码。
userDatabase = FirebaseDatabase.getInstance().getReference("UsersToursList").child(userID);
userDatabase.addValueEventListener(new ValueEventListener()
@Override
public void onDataChange(@NonNull DataSnapshot snapshot)
tourList.clear();
for (DataSnapshot tourSnapshot : snapshot.getChildren())
Tour tour = tourSnapshot.getValue(Tour.class);
tourList.add(tour);
MyToursListAdapter adapter = new MyToursListAdapter(MyToursActivity.this,tourList);
list_view_tours.setAdapter(adapter);
);
这是适配器类
class MyToursListAdapter extends ArrayAdapter<Tour>
private Activity mContext;
private List<Tour> TourList;
public MyToursListAdapter(Activity mContext, List <Tour> TourList)
super(mContext,R.layout.tours_item_list,TourList);
this.mContext = mContext;
this.TourList = TourList;
@Override
public View getView(int position, View convertView, ViewGroup parent)
TextView tvTourTitle,tvPlace;
LayoutInflater inflater = mContext.getLayoutInflater();
View listItemView = inflater.inflate(R.layout.tours_item_list,null,true);
tvTourTitle = listItemView.findViewById(R.id.tour_list_tv_TourTitle);
tvPlace = listItemView.findViewById(R.id.tour_list_tv_place);
Tour tour = TourList.get(position);
tvTourTitle.setText(tour.getTourTitle());
tvPlace.setText(tour.getPlace());
return listItemView;
旅游课
class Tour
String place;
public String getPlace()
return place;
希望你能理解。
编辑:根据@Simran Sharma 的请求,我将发布与此问题相关的全部代码。
首先,Tour.java
class Tour
String tourTitle;
String tourID;
String places;
public Tour()
public Tour(String TourTitle,String TourID)
tourTitle = TourTitle;
tourID = TourID;
public Tour(String TourTitle,String TourID,String Places)
tourTitle = TourTitle;
tourID = TourID;
places = Places;
public String getTourTitle()
return tourTitle;
public String getTourID()
return tourID;
public String getPlaces()
return places;
MyToursListAdapter.java,它实际上和以前一样,但我真的不知道我应该使用TextView还是ListView。所以请告诉我,因为我认为它是一个数组而不是一个普通的字符串。
这是我将地点添加(保存)到列表和数据库的代码:
Query query = myTourUserDatabase.orderByChild("tourTitle").equalTo(ListChosen);
query.addListenerForSingleValueEvent(new ValueEventListener()
@Override
public void onDataChange(@NonNull DataSnapshot snapshot)
if(snapshot.exists())
for (DataSnapshot issue : snapshot.getChildren())
ListID = issue.getKey();
Log.d("mytag", "onClick: MapActivity Chosen list ref from spinner " + ListID);
TourListChosen_UserDB = FirebaseDatabase.getInstance().getReference("UsersToursList").child(userID).child(ListID);
Map<String, Object> Place = new HashMap<>();
Place.put("place",PlaceName);
//Tour tour = snapshot.getValue(Tour.class);
//places.add(tour);
TourListChosen_UserDB.setValue(Place);
@Override
public void onCancelled(@NonNull DatabaseError error)
);
这是我检索整个列表的代码(应该包含我添加的所有地方'例如肯德基,酒店...'但它不起作用):
userDatabase.addValueEventListener(new ValueEventListener()
@Override
public void onDataChange(@NonNull DataSnapshot snapshot)
tourList.clear();
for (DataSnapshot tourSnapshot : snapshot.getChildren())
Tour tour = tourSnapshot.getValue(Tour.class);
tourList.add(tour);
MyToursListAdapter adapter = new MyToursListAdapter(MyToursActivity.this,tourList);
list_view_tours.setAdapter(adapter);
@Override
public void onCancelled(@NonNull DatabaseError error)
);
我想这就是我得到的关于这个问题的所有代码......
【问题讨论】:
【参考方案1】:但无法显示我在活动中计划去的地方
您不能这样做,因为您的“Tour”类中的“place”字段无法映射到动态 ID。它可以映射到一个名为“place”的属性,该属性可以保存一个特定的值,但您不能使用固定属性来映射那些推送的 ID。你应该做的是稍微改变你的数据库结构:
Firebase-root
|
--- UserToursList
|
--- On3I...Yq72
|
--- -MScb...BZUt
|
--- tourID: "-MScb...BZUt"
|
--- tourTitle: "Tour 1"
|
--- places
|
--- 0: "Jacob Samuel Hotel"
|
--- 1: "KFC"
|
--- 2: "Beach"
“地点”被认为是一个数组。您可以在 Java 代码中简单地将该数组作为 List<String>
获取。
还有另一种选择,您可以在其中使用 Map
Firebase-root
|
--- UserToursList
|
--- On3I...Yq72
|
--- -MScb...BZUt
|
--- tourID: "-MScb...BZUt"
|
--- tourTitle: "Tour 1"
|
--- places
|
--- "Jacob Samuel Hotel": true
|
--- "KFC": true
|
--- "Beach": true
由您决定哪一个最适合。
【讨论】:
感谢您的回答,能否请您给我看一下这段代码的示例,因为这是我添加位置列表的地方TourListChosen_UserDB = FirebaseDatabase.getInstance().getReference("UsersToursList").child(userID).child(ListID) Map<String, Object> Place = new HashMap<>(); Place.put("placeName", PlaceName); TourListChosen_UserDB.push().setValue(Place);
不,不正确。地图应如下所示:Map<String, Object> Place = new HashMap<>();
,在其中添加数据,如下所示:Place.put("Jacob Samuel Hotel", true);
,现在将此地图写入“地点”位置。试一试,告诉我它是否有效。
它没有按预期工作,我应该如何处理 Tour Class 和 Adapter Class ?我试图制作数组列表,但我做不到……我对 firebase 很陌生……
如果你的tourID
是一个字符串,你可以把它作为一个字符串来获取。同样,如果您的places
是一个数组,您可以将其作为List<String>
获取。 Map 也是一样,对吧?
除此之外,“它没有按预期工作”并没有提供太多信息来了解问题所在。如果您在实施上述解决方案时遇到新问题,最好创建一个新的MCVE 并发布一个新问题。【参考方案2】:
好的,让我们从 Tour.java 开始。
class Tour
// make these private
private String tourTitle, tourID;
// have this public
ArrayList<Place> places;
public Tour()
// required constructor
// main constructor
public Tour(String tourTitle,String tourID)
this.tourTitle = tourTitle;
this.tourID = tourID;
public String getTourTitle()
return tourTitle;
public String getTourID()
return tourID;
创建另一个类 Place.java
class Place
private String name;
public Place()
public Place(String name)
this.name = name;
public String getName()
return name;
我将在整个过程中使用以下数据库参考
dbRef = FirebaseDatabase.getInstance().getReference().child("userToursList").child(userId);
placesRef = dbRef.child(listId).child("places");
因此,当您想添加游览时,请执行以下操作:
Tour tour = new Tour("Tour1", listId);
dbRef.child(listId).setValue(tour);
当你想添加一个新的地方,使用下面的代码。
Place place = new Place("KFC");
placesRef.push().setValue(place);
现在在您的活动中声明以下字段:
ArrayList<Tour> tours = new ArrayList<>();
ArrayList<Place> places = new ArrayList<>();
MyToursListAdapter adapter = new Adapter(MyToursActivity.this, tours);
list_view_tours.setAdapter(adapter);
当你想检索旅游列表时:
dbRef.addChildEventListener(new ChildEventListener()
@Override
public void onChildAdded(@NonNull DataSnapshot snapshot, @Nullable String previousChildName)
// check if the snapshot exists or not
if (snapshot.exists())
// the snapshot exists, now retrieve the data
Tour tour = snapshot.getValue(Tour.class);
if (tour != null)
// update the list with a new tour item
tours.add(tour);
// tell the adapter that the data has been updated
adapter.notifyDataSetChanged();
@Override
public void onChildChanged(@NonNull DataSnapshot snapshot, @Nullable String previousChildName)
@Override
public void onChildRemoved(@NonNull DataSnapshot snapshot)
@Override
public void onChildMoved(@NonNull DataSnapshot snapshot, @Nullable String previousChildName)
@Override
public void onCancelled(@NonNull DatabaseError error)
);
当您想要检索特定游览中的地点列表时:
placesRef.addChildEventListener(new ChildEventListener()
@Override
public void onChildAdded(@NonNull DataSnapshot snapshot, @Nullable String previousChildName)
// check if the snapshot exists or not
if (snapshot.exists())
// the snapshot exists, now retrieve the data
Place place = snapshot.getValue(Place.class);
if (place != null)
// update the list with a new tour item
places.add(place);
// you can update the places list in the Tour class as well like below
tour.places.add(place);
// inform adapter that the data has changed so changes can be seen
adapter.notifyDataSetChanged();
@Override
public void onChildChanged(@NonNull DataSnapshot snapshot, @Nullable String previousChildName)
@Override
public void onChildRemoved(@NonNull DataSnapshot snapshot)
@Override
public void onChildMoved(@NonNull DataSnapshot snapshot, @Nullable String previousChildName)
@Override
public void onCancelled(@NonNull DatabaseError error)
);
【讨论】:
非常感谢的所有努力,它实际上工作得很好,而且比以前好多了,但是我还有一个很小的问题,那我就不贴了作为另一个帐户的答案,因为问题已经很长了.. 你能看看这个问题吗,继续我们的谈话。***.com/questions/66055110/… 我已经提到了你的那个问题的一些变化。更改它们并检查它是否有效。 你能再检查一下这个问题吗?感谢您的努力 我已经评论了什么是错误的,请相应地改变。以上是关于从 Firebase 数据库 Android 保存和检索数据的主要内容,如果未能解决你的问题,请参考以下文章
Android-从Firebase实时数据库读取数据并显示在RecyclerView上