从 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&lt;String&gt; 获取。

还有另一种选择,您可以在其中使用 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&lt;String, Object&gt; Place = new HashMap&lt;&gt;(); Place.put("placeName", PlaceName); TourListChosen_UserDB.push().setValue(Place); 不,不正确。地图应如下所示:Map&lt;String, Object&gt; Place = new HashMap&lt;&gt;();,在其中添加数据,如下所示:Place.put("Jacob Samuel Hotel", true);,现在将此地图写入“地点”位置。试一试,告诉我它是否有效。 它没有按预期工作,我应该如何处理 Tour Class 和 Adapter Class ?我试图制作数组列表,但我做不到……我对 firebase 很陌生…… 如果你的tourID 是一个字符串,你可以把它作为一个字符串来获取。同样,如果您的places 是一个数组,您可以将其作为List&lt;String&gt; 获取。 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 保存和检索数据的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Firebase 检索用户数据 android

Android,从 firebase 数据库中获取价值

Android-从Firebase实时数据库读取数据并显示在RecyclerView上

如何从android上的firebase获取用户uid?

android - 将数据保存到firebase是用字母键保存的

是否可以在 Android Studio 中使用 Firebase 数据库添加子代同时保留旧代?