问题
I'm working on a project where I have to do a custom "tour/trip" based on the locations the user chooses on the map. and every tour has a title, with the locations that he chose. say for example he made a tour(list) and called it 'Tour 1' and in this 'Tour 1' first he wants to go to the hotel, and then to KFC, and then to the beach.
I'm at the point where I made a list and gave it a title, but can't show the places that I planned to go in the activity, here is a screenshot of the activity activity example, and here is a screenshot of my realtime database.
so I want to show all the places that I planned to go, where it says 'Place 1' in the activity. here is my code.
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);
}
});
here is the Adapter class
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;
}
Tour class
class Tour {
String place;
public String getPlace() {
return place;
}
I hope you understand.
EDIT: based on @Simran Sharma request I'll post the whole code that is realted to this issue.
First, 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, its actually the same as before, but i don't really know if i should use TextView or ListView. so let me know please because i think its an array not a normal string.
here is the code where i add(save) the place to the list and database:
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) {
}
});
here is the code where i retreive the whole list (supposed to be with all the places that i added 'example KFC, Hotel ...' but its not working):
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) {
}
});
I think this is all the code what i got about this issue...
回答1:
Ok, so let's start with the 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;
}
}
Create another class Place.java
class Place {
private String name;
public Place() {}
public Place(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
I am gonna use the below database reference throughout
dbRef = FirebaseDatabase.getInstance().getReference().child("userToursList").child(userId);
placesRef = dbRef.child(listId).child("places");
So when you want to add a tour do like below:
Tour tour = new Tour("Tour1", listId);
dbRef.child(listId).setValue(tour);
And when you want to add a new place, use the below code.
Place place = new Place("KFC");
placesRef.push().setValue(place);
Now in your activity declare the below fields:
ArrayList<Tour> tours = new ArrayList<>();
ArrayList<Place> places = new ArrayList<>();
MyToursListAdapter adapter = new Adapter(MyToursActivity.this, tours);
list_view_tours.setAdapter(adapter);
And when you want to retrieve the list of tours:
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) { }
});
And when you want to retrieve the list of places in a particular tour:
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) { }
});
回答2:
but can't show the places that I planned to go in the activity
You cannot do that because your "place" field in your "Tour" class cannot be mapped to a dynamic ID. It can be mapped to a property called "place", that can hold a specific value, but you cannot use a fixed property to map those pushed IDs. What you should do instead, is to change your database structure a little bit:
Firebase-root
|
--- UserToursList
|
--- On3I...Yq72
|
--- -MScb...BZUt
|
--- tourID: "-MScb...BZUt"
|
--- tourTitle: "Tour 1"
|
--- places
|
--- 0: "Jacob Samuel Hotel"
|
--- 1: "KFC"
|
--- 2: "Beach"
Where the "places" is considered an array. You can simply get that array as a List<String>
in your Java code.
There is another option, in which you can use a Map<String, Object>, instead of an array, and your schema should look like this:
Firebase-root
|
--- UserToursList
|
--- On3I...Yq72
|
--- -MScb...BZUt
|
--- tourID: "-MScb...BZUt"
|
--- tourTitle: "Tour 1"
|
--- places
|
--- "Jacob Samuel Hotel": true
|
--- "KFC": true
|
--- "Beach": true
It's up to you to decide which one fits best.
来源:https://stackoverflow.com/questions/66031824/save-and-retrieve-data-from-firebase-database-android