DataSnapshot.getValue() 没有正确检索对象
DataSnapshot.getValue() doesn't retrieve object properly
总的来说,我是 firebase 数据库和 firebase 的新手,在尝试使用它时遇到了一些小问题。
我正在使用从 firebase 控制台导入的以下 JSON 代码,最初我只是在 firebase 控制台中创建了一个 数据库 结构,然后下载了 JSON代码,如下:
{
"rides" : {
"arrive" : "kech",
"depart" : "agadir",
"detail" : "0,1",
"msg" : false,
"phone" : true,
"price" : 15,
"profile_id" : 0,
"spots" : 3,
"timedate" : "11/12/2017 11:15",
"vocal_id" : 0
}
}
我要获取的对象名为Ride.java:
public class Ride {
private String arrive;
private String depart;
private String detail;
private boolean msg;
private boolean phone;
private int price;
private int profile_id;
private int spots;
private String timedate;
private int vocal_id;
public Ride() {}
// public getters (I created them I just didn't post it all to make the post shorter)
}
要收听我的数据库引用,我使用以下代码:
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference ref = database.getReference("rides").child("0"); // 0 is the ride id
ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot singleSnapshot : dataSnapshot.getChildren()){
Ride ride = singleSnapshot.getValue(Ride.class);
rides.add(ride); // list of rides used later in a listadapter
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.e(TAG, "onCancelled", databaseError.toException());
}
});
我正在尝试从 firebase db 获取单程行程并将其显示在我的应用程序中。在 firebase 控制台中,它有 url: https://myapp.firebaseio.com/rides/0(第二次骑行的 ID 为 1,依此类推)。获取所有游乐设施并从每个游乐设施访问其属性的最佳做法是什么?
编辑: 当我删除 .child("0")
时,我没有收到任何错误,但我的 listView 中什么也没有出现。显然 rides.add(ride)
由于某种原因没有发生。
我通过在 addListenerForSingleValueEvent()
方法之外添加一个 Ride 的简单实例来测试它,它工作正常。
我也尝试将监听器更改为 addValueEventListener()
,结果相同..
Edit2: 当我尝试从我的数据库中检索整数时收到一条错误消息。
我在我的数据库侦听器中试过这个:
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot singleSnapshot: dataSnapshot.getChildren()) {
int price = (int) singleSnapshot.child("price").getValue(); // error takes place here
Log.d("FirebaseDb", String.valueOf(price));
}
}
结果是这个错误:(所有整数)
java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.Integer
at com.ride.ive.anas.iveride.Fragments.RidesFragment.onDataChange(RidesFragment.java:96)
但是当我检索字符串或布尔值时它工作正常,如:
String arrive = (String) singleSnapshot.child("arrive").getValue();
或Boolean usePhone = (Boolean) singleSnapshot.child("phone").getValue();
Edit3: 这是根据@Prodigy 的要求提供的RidesFragment.java 文件。
我在其中有一个 ListView
,我尝试显示存储在我的 firebase 数据库中的所有 Ride 实例。
public class RidesFragment extends Fragment {
ListView list;
RidesAdapter2 ridesAdapter;
List<Ride> rides;
Ride ride;
List<RidePojo> filteredRides;
LinearLayout layoutFilter;
boolean filtersVisible = false;
boolean searchDone = false;
String userNumber;
public RidesFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_rides, container, false);
getActivity().setTitle("Search for a ride:");
// filter action button stuff
setHasOptionsMenu(true);
layoutFilter = rootView.findViewById(R.id.ll_filter_screen);
/*FragmentManager fm = getActivity().getSupportFragmentManager();
fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);*/
ridesAdapter = new RidesAdapter2(getContext(), rides);
Bundle arguments = getArguments();
list = rootView.findViewById(R.id.rides_list);
rides = new ArrayList<>();
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference ref = database.getReference("rides");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot singleSnapshot: dataSnapshot.getChildren()) {
Ride ride = singleSnapshot.getValue(Ride.class);
rides.add(ride);
ridesAdapter.notifyDataSetChanged();
Log.d("FbDatabase", singleSnapshot.toString());
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.e(TAG, "onCancelled", databaseError.toException());
}
});
rides.add(ride);
// In case the rides ArrayList is not empty another fragment appears for no rides criteria
if(rides.isEmpty()) {
rootView = inflater.inflate(R.layout.fragment_empty, container, false);
Button rideButton = rootView.findViewById(R.id.btn_post_ride);
Button requestButton = rootView.findViewById(R.id.btn_post_request);
rideButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
launchFragment(new OfferRideFragment(), getActivity());
}
});
requestButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
launchFragment(new RequestFragment(), getActivity());
}
});
}
else {
list.setAdapter(ridesAdapter);
}
return rootView;
}
protected void launchFragment(Fragment f, FragmentActivity a) {
android.support.v4.app.FragmentTransaction fragmentTransaction =
a.getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, f);
fragmentTransaction.commit();
}
// ....
}
Firebase 数据库命名约定更像是命名文件路径,例如访问您使用 .child("rides") 的游乐设施,而对于到达它将是 .child("rides").child("arrive") 或 (rides/arrives)
从你发布的 firebase link 我可以看到你有一个带有子节点 0 等的节点......
但是从您发布的 json 看不到节点“0”,这肯定会引发错误。
The correct Json should be
{
"rides" : {
"0": {
"arrive" : "kech",
"depart" : "agadir",
"detail" : "0,1",
"msg" : false,
"phone" : true,
"price" : 15,
"profile_id" : 0,
"spots" : 3,
"timedate" : "11/12/2017 11:15",
"vocal_id" : 0
}
}
}
这将提取您需要的数据,并且不要忘记在添加数据时在旅游列表适配器上添加 notifydata 更改侦听器。
查看下面编辑后的代码
public class RidesFragment extends Fragment {
ListView list;
RidesAdapter2 ridesAdapter;
List<Ride> rides;
Ride ride;
List<RidePojo> filteredRides;
LinearLayout layoutFilter;
boolean filtersVisible = false;
boolean searchDone = false;
String userNumber;
public RidesFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_rides, container, false);
getActivity().setTitle("Search for a ride:");
// filter action button stuff
setHasOptionsMenu(true);
layoutFilter = rootView.findViewById(R.id.ll_filter_screen);
/*FragmentManager fm = getActivity().getSupportFragmentManager();
fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);*/
Bundle arguments = getArguments();
list = rootView.findViewById(R.id.rides_list);
rides = new ArrayList<>();
ridesAdapter = new RidesAdapter2(getContext(), rides);
list.setAdapter(ridesAdapter);
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference ref = database.getReference("rides");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot singleSnapshot: dataSnapshot.getChildren()) {
Ride ride = singleSnapshot.getValue(Ride.class);
rides.add(ride);
ridesAdapter.notifyDataSetChanged();
Log.d("FbDatabase", singleSnapshot.toString());
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.e(TAG, "onCancelled", databaseError.toException());
}
});
//rides.add(ride);
// In case the rides ArrayList is not empty another fragment appears for no rides criteria
if(rides.isEmpty()) {
rootView = inflater.inflate(R.layout.fragment_empty, container, false);
Button rideButton = rootView.findViewById(R.id.btn_post_ride);
Button requestButton = rootView.findViewById(R.id.btn_post_request);
rideButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
launchFragment(new OfferRideFragment(), getActivity());
}
});
requestButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
launchFragment(new RequestFragment(), getActivity());
}
});
}
//else {
//list.setAdapter(ridesAdapter);
//}
return rootView;
}
protected void launchFragment(Fragment f, FragmentActivity a) {
android.support.v4.app.FragmentTransaction fragmentTransaction =
a.getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, f);
fragmentTransaction.commit();
}
// ....
}
总的来说,我是 firebase 数据库和 firebase 的新手,在尝试使用它时遇到了一些小问题。
我正在使用从 firebase 控制台导入的以下 JSON 代码,最初我只是在 firebase 控制台中创建了一个 数据库 结构,然后下载了 JSON代码,如下:
{
"rides" : {
"arrive" : "kech",
"depart" : "agadir",
"detail" : "0,1",
"msg" : false,
"phone" : true,
"price" : 15,
"profile_id" : 0,
"spots" : 3,
"timedate" : "11/12/2017 11:15",
"vocal_id" : 0
}
}
我要获取的对象名为Ride.java:
public class Ride {
private String arrive;
private String depart;
private String detail;
private boolean msg;
private boolean phone;
private int price;
private int profile_id;
private int spots;
private String timedate;
private int vocal_id;
public Ride() {}
// public getters (I created them I just didn't post it all to make the post shorter)
}
要收听我的数据库引用,我使用以下代码:
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference ref = database.getReference("rides").child("0"); // 0 is the ride id
ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot singleSnapshot : dataSnapshot.getChildren()){
Ride ride = singleSnapshot.getValue(Ride.class);
rides.add(ride); // list of rides used later in a listadapter
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.e(TAG, "onCancelled", databaseError.toException());
}
});
我正在尝试从 firebase db 获取单程行程并将其显示在我的应用程序中。在 firebase 控制台中,它有 url: https://myapp.firebaseio.com/rides/0(第二次骑行的 ID 为 1,依此类推)。获取所有游乐设施并从每个游乐设施访问其属性的最佳做法是什么?
编辑: 当我删除 .child("0")
时,我没有收到任何错误,但我的 listView 中什么也没有出现。显然 rides.add(ride)
由于某种原因没有发生。
我通过在 addListenerForSingleValueEvent()
方法之外添加一个 Ride 的简单实例来测试它,它工作正常。
我也尝试将监听器更改为 addValueEventListener()
,结果相同..
Edit2: 当我尝试从我的数据库中检索整数时收到一条错误消息。
我在我的数据库侦听器中试过这个:
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot singleSnapshot: dataSnapshot.getChildren()) {
int price = (int) singleSnapshot.child("price").getValue(); // error takes place here
Log.d("FirebaseDb", String.valueOf(price));
}
}
结果是这个错误:(所有整数)
java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.Integer
at com.ride.ive.anas.iveride.Fragments.RidesFragment.onDataChange(RidesFragment.java:96)
但是当我检索字符串或布尔值时它工作正常,如:
String arrive = (String) singleSnapshot.child("arrive").getValue();
或Boolean usePhone = (Boolean) singleSnapshot.child("phone").getValue();
Edit3: 这是根据@Prodigy 的要求提供的RidesFragment.java 文件。
我在其中有一个 ListView
,我尝试显示存储在我的 firebase 数据库中的所有 Ride 实例。
public class RidesFragment extends Fragment {
ListView list;
RidesAdapter2 ridesAdapter;
List<Ride> rides;
Ride ride;
List<RidePojo> filteredRides;
LinearLayout layoutFilter;
boolean filtersVisible = false;
boolean searchDone = false;
String userNumber;
public RidesFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_rides, container, false);
getActivity().setTitle("Search for a ride:");
// filter action button stuff
setHasOptionsMenu(true);
layoutFilter = rootView.findViewById(R.id.ll_filter_screen);
/*FragmentManager fm = getActivity().getSupportFragmentManager();
fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);*/
ridesAdapter = new RidesAdapter2(getContext(), rides);
Bundle arguments = getArguments();
list = rootView.findViewById(R.id.rides_list);
rides = new ArrayList<>();
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference ref = database.getReference("rides");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot singleSnapshot: dataSnapshot.getChildren()) {
Ride ride = singleSnapshot.getValue(Ride.class);
rides.add(ride);
ridesAdapter.notifyDataSetChanged();
Log.d("FbDatabase", singleSnapshot.toString());
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.e(TAG, "onCancelled", databaseError.toException());
}
});
rides.add(ride);
// In case the rides ArrayList is not empty another fragment appears for no rides criteria
if(rides.isEmpty()) {
rootView = inflater.inflate(R.layout.fragment_empty, container, false);
Button rideButton = rootView.findViewById(R.id.btn_post_ride);
Button requestButton = rootView.findViewById(R.id.btn_post_request);
rideButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
launchFragment(new OfferRideFragment(), getActivity());
}
});
requestButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
launchFragment(new RequestFragment(), getActivity());
}
});
}
else {
list.setAdapter(ridesAdapter);
}
return rootView;
}
protected void launchFragment(Fragment f, FragmentActivity a) {
android.support.v4.app.FragmentTransaction fragmentTransaction =
a.getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, f);
fragmentTransaction.commit();
}
// ....
}
Firebase 数据库命名约定更像是命名文件路径,例如访问您使用 .child("rides") 的游乐设施,而对于到达它将是 .child("rides").child("arrive") 或 (rides/arrives)
从你发布的 firebase link 我可以看到你有一个带有子节点 0 等的节点...... 但是从您发布的 json 看不到节点“0”,这肯定会引发错误。
The correct Json should be
{
"rides" : {
"0": {
"arrive" : "kech",
"depart" : "agadir",
"detail" : "0,1",
"msg" : false,
"phone" : true,
"price" : 15,
"profile_id" : 0,
"spots" : 3,
"timedate" : "11/12/2017 11:15",
"vocal_id" : 0
}
}
}
这将提取您需要的数据,并且不要忘记在添加数据时在旅游列表适配器上添加 notifydata 更改侦听器。
查看下面编辑后的代码
public class RidesFragment extends Fragment {
ListView list;
RidesAdapter2 ridesAdapter;
List<Ride> rides;
Ride ride;
List<RidePojo> filteredRides;
LinearLayout layoutFilter;
boolean filtersVisible = false;
boolean searchDone = false;
String userNumber;
public RidesFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_rides, container, false);
getActivity().setTitle("Search for a ride:");
// filter action button stuff
setHasOptionsMenu(true);
layoutFilter = rootView.findViewById(R.id.ll_filter_screen);
/*FragmentManager fm = getActivity().getSupportFragmentManager();
fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);*/
Bundle arguments = getArguments();
list = rootView.findViewById(R.id.rides_list);
rides = new ArrayList<>();
ridesAdapter = new RidesAdapter2(getContext(), rides);
list.setAdapter(ridesAdapter);
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference ref = database.getReference("rides");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot singleSnapshot: dataSnapshot.getChildren()) {
Ride ride = singleSnapshot.getValue(Ride.class);
rides.add(ride);
ridesAdapter.notifyDataSetChanged();
Log.d("FbDatabase", singleSnapshot.toString());
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.e(TAG, "onCancelled", databaseError.toException());
}
});
//rides.add(ride);
// In case the rides ArrayList is not empty another fragment appears for no rides criteria
if(rides.isEmpty()) {
rootView = inflater.inflate(R.layout.fragment_empty, container, false);
Button rideButton = rootView.findViewById(R.id.btn_post_ride);
Button requestButton = rootView.findViewById(R.id.btn_post_request);
rideButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
launchFragment(new OfferRideFragment(), getActivity());
}
});
requestButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
launchFragment(new RequestFragment(), getActivity());
}
});
}
//else {
//list.setAdapter(ridesAdapter);
//}
return rootView;
}
protected void launchFragment(Fragment f, FragmentActivity a) {
android.support.v4.app.FragmentTransaction fragmentTransaction =
a.getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, f);
fragmentTransaction.commit();
}
// ....
}