【问题标题】:Android - Load data from Firebase Database in FragmentAndroid - 从片段中的 Firebase 数据库加载数据
【发布时间】:2017-05-28 03:54:31
【问题描述】:

我有一个使用片段的 NavigationDrawer 活动。在我的一个片段中,我想将数据从 Firebase 数据库加载到 RecyclerView。

所以我有一个用于存储在数据库中的对象的 ArrayList。然后我将 ValueEventListener 添加到我的数据库引用中,我将数据库中的对象添加到数组列表中。然后我将 ArrayList 提供给 RecyclerView 适配器,它应该使用我的对象创建列表。

当我使用 addListenerForSingleValueEvent 时,它永远不会工作,我总是得到一个空的 RecyclerView。当我使用 addValueEventListener 时,它一开始都不起作用,但是当我将手机的方向切换为横向时,数据突然出现。如果我回到正常方向,它仍然存在。但不是在我打开片段时开始。

这是我的片段类代码:

public class LogFragment extends Fragment {

    private RecyclerView recyclerView;
    private RecyclerView.Adapter rvAdapter;
    private RecyclerView.LayoutManager rvLayoutManager;
    private ArrayList<LogEntry> entries;

    private DatabaseReference databaseReference;
    private DatabaseReference logReference;
    private FirebaseAuth firebaseAuth;
    private FirebaseUser firebaseUser;

    public LogFragment() {
        // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        View rootView = inflater.inflate(R.layout.fragment_log, container, false);

        databaseReference = FirebaseDatabase.getInstance().getReference();
        firebaseAuth = FirebaseAuth.getInstance();
        firebaseUser = firebaseAuth.getCurrentUser();

        loadEntries();

        recyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerView);
        rvLayoutManager = new LinearLayoutManager(getActivity());
        recyclerView.setLayoutManager(rvLayoutManager);

        rvAdapter = new RvAdapter(entries);
        recyclerView.setAdapter(rvAdapter);

        // Inflate the layout for this fragment
        return rootView;
    }

    private void loadEntries(){
        entries = new ArrayList<>();
        logReference = databaseReference.child("log").child(firebaseUser.getUid());
        ValueEventListener valueEventListener = new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {

                for(DataSnapshot ds : dataSnapshot.getChildren()){
                    entries.add(ds.getValue(LogEntry.class));
                }

            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
                Log.w("LogFragment", "loadLog:onCancelled", databaseError.toException());
            }
        };
        logbuchReference.addValueEventListener(valueEventListener);

    }
}

这是我的 RvAdapter.java:

public class RvAdapter extends RecyclerView.Adapter<RvAdapter.MyViewHolder> {

    private ArrayList<LogEntry> entries;

    public RvAdapter(ArrayList<LogEntry> entries){
        this.entries = entries;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.log_entry_item, null);

        return new MyViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {

        SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy");
        SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm");

        holder.tvAction.setText(entries.get(position).action);
        holder.tvDate.setText(dateFormat.format(entries.get(position).date)+"\n"+timeFormat.format(entries.get(position).date));
        holder.ivIcon.setImageResource(entries.get(position).icon);

        holder.itemView.setOnClickListener(new View.OnClickListener(){

            @Override
            public void onClick(View v) {
                // Do something
            }
        });

    }

    @Override
    public int getItemCount() {
        return entries.size();
    }

    public class MyViewHolder extends RecyclerView.ViewHolder {

        TextView tvAction, tvDate;
        ImageView ivIcon;

        public MyViewHolder(View itemView) {
            super(itemView);
            tvAction = (TextView) itemView.findViewById(R.id.tvAction);
            tvDate = (TextView) itemView.findViewById(R.id.tvDate);
            ivIcon = (ImageView) itemView.findViewById(R.id.ivIcon);
        }
    }
}

这里是我的 LogEntry.java:

public class LogEntry {

    public String action;
    public Date date;
    public int icon;
    public String message;

    public LogEntry() {}

    public LogEntry(String action, Date date, int icon, String message) {
        this.action = action;
        this.date = date;
        this.icon = icon;
        this.message = message;
    }
}

有人知道可能是什么问题吗?

编辑:

当我 System.out.prinln 在 for() 之后的 ArrayList 时,我得到了数据。所以从数据库加载数据是有效的。但是显示数据不起作用。

【问题讨论】:

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


    【解决方案1】:

    Firebase 是异步的。在回调中设置或通知适配器。

    ValueEventListener valueEventListener = new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
    
                for(DataSnapshot ds : dataSnapshot.getChildren()){
                    entries.add(ds.getValue(LogEntry.class));
                }
    
                // Declare adapter and set here
    
                // OR... adapter.notifyDataSetChanged();
    
            }
    
            @Override
            public void onCancelled(DatabaseError databaseError) {
                Log.w("LogFragment", "loadLog:onCancelled", databaseError.toException());
            }
        };
    

    更详细的,

        loadEntries(); // ... Doing stuff in the background
    
        recyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerView);
        rvLayoutManager = new LinearLayoutManager(getActivity());
        recyclerView.setLayoutManager(rvLayoutManager);
    
        rvAdapter = new RvAdapter(entries); // This is still empty, probably
        recyclerView.setAdapter(rvAdapter);
    
        // entries.add() called later, but adapter never notified
    

    【讨论】:

      【解决方案2】:

      你可以使用https://github.com/firebase/FirebaseUI-Android来解决这个问题。

      按照一些代码来帮助你...

      ListView messagesView = (ListView) findViewById(R.id.messages_list);
      
      DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
      
      mAdapter = new FirebaseListAdapter<Chat>(this, Chat.class, android.R.layout.two_line_list_item, ref) {
          @Override
          protected void populateView(View view, Chat chatMessage, int position) {
              ((TextView)view.findViewById(android.R.id.text1)).setText(chatMessage.getName());
              ((TextView)view.findViewById(android.R.id.text2)).setText(chatMessage.getText());
      
          }
      };
      messagesView.setAdapter(mAdapter);
      

      祝你好运!!!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-03-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-15
        • 2017-02-20
        • 1970-01-01
        相关资源
        最近更新 更多