Android-从片段中的Firebase数据库加载数据 [英] Android - Load data from Firebase Database in Fragment

查看:84
本文介绍了Android-从片段中的Firebase数据库加载数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a NavigationDrawer activity which is using fragments. In one of my fragments I want to load data from the Firebase database to a RecyclerView.

因此,对于存储在数据库中的对象,我有一个ArrayList.然后,将ValueEventListener添加到数据库引用中,在其中将数据库中的对象添加到数组列表中.然后,将ArrayList交给RecyclerView Adapter,后者应使用我的对象创建列表.

So I have an ArrayList for the objects I have stored in the database. Then I add a ValueEventListener to my database reference where I add the objects from the database to the array list. And then I give the ArrayList to the RecyclerView Adapter which should create the list with my objects.

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

When I use addListenerForSingleValueEvent it is never working, I always get an empty RecyclerView. When I use addValueEventListener it is working neither at the start, but when I switch the orientation of my phone to landscape the data suddenly appears. And if I go back to the normal orientation it is still there. But not at the start when I open the fragment.

这是我的片段类代码:

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:

And here is my 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:

And here my 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;
    }
}

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

Someone know what could be the problem?

当我System.out.prinln for()之后的ArrayList时,我得到了数据.因此,从数据库加载数据是可行的.但是无法显示数据.

When I System.out.prinln the ArrayList right after the for() I get the data. So loading the data from the database is working. But presenting the data is not working.

推荐答案

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

Firebase is asynchronous. Set or notify the adapter from within the callback.

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());
        }
    };


更详细地,


In more detail,

    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

这篇关于Android-从片段中的Firebase数据库加载数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆