【问题标题】:DataSnapshot.getValue() doesn't retrieve object properlyDataSnapshot.getValue() 无法正确检索对象
【发布时间】:2017-08-29 09:39:27
【问题描述】:

我是 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$1.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();
    }
// ....
}

【问题讨论】:

  • 为您的 Ride 类创建 getter 和 setter,其余的事情可以从这个 stackoverflower 回答 Here
  • 我自己创作的,只是不想发帖,写在这里让帖子更短
  • 将添加侦听器的代码发布到数据库参考
  • 完成@BurhanuddinRashid,如果你能回答我的问题,那就太好了
  • 我相信你必须从你的数据库查询中删除.child("0")

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


【解决方案1】:

Firebase 数据库命名约定更像是命名文件路径,例如访问您使用 .child("rides") 的游乐设施,而对于到达,它将是 .child("rides").child("arrive") 或 (rides /到达)

从您发布的 firebase 链接中,我可以看到您有一个带有子节点 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();
    }
// ....
}

【讨论】:

  • 工作正常,没有错误,但rides.add(ride) 仍然无法工作......
  • 在 valuechangelistener 的 for 循环中,在rides.add(ride) 之后添加 adapter.notifyDataSetChanged()。让我知道它是否有效
  • 实际上我稍后在代码中创建了适配器,但我在开始时对其进行了初始化并尝试了您所说的但没有任何改变。同样的结果..
  • 你能展示你的代码吗,你如何使用适配器、listview和arraylist
  • 你需要添加这个list.setAdapter(ridesAdapter);在您的 listview decleration 旁边并删除“list.setAdapter(ridesAdapter);”从 else 因为它永远不会被调用
猜你喜欢
  • 1970-01-01
  • 2015-01-13
  • 2020-02-08
  • 1970-01-01
  • 1970-01-01
  • 2013-04-22
  • 1970-01-01
  • 2021-05-07
  • 1970-01-01
相关资源
最近更新 更多