【问题标题】:Save and retrieve data from firebase database Android从 Firebase 数据库 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) {

        }
    });

我想这就是我得到的关于这个问题的所有代码......

【问题讨论】:

    标签: java android database firebase firebase-realtime-database


    【解决方案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) { }
            });
    

    【讨论】:

    • 非常感谢的所有努力,它实际上工作得很好,而且比以前好多了,但是我还有一个很小的问题,那我就不贴了作为另一个帐户的答案,因为问题已经很长了..
    • 你能看看这个问题吗,继续我们的谈话。stackoverflow.com/questions/66055110/…
    • 我已经提到了你的那个问题的一些变化。更改它们并检查它是否有效。
    • 你能再检查一下这个问题吗?感谢您的努力
    • 我已经评论了什么是错误的,请相应地改变。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-08
    • 1970-01-01
    • 2019-06-15
    • 2016-06-21
    • 2013-06-28
    相关资源
    最近更新 更多