我有一个使用片段的NavigationDrawer活动。在我的一个片段中,我想将数据从Firebase数据库加载到RecyclerView。
所以我有一个ArrayList用于存储在数据库中的对象。然后我将ValueEventListener添加到我的数据库引用,在那里我将数据库中的对象添加到数组列表中。然后我将ArrayList提供给RecyclerView Adapter,它应该用我的对象创建列表。
当我使用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时,我得到了数据。因此从数据库加载数据是有效的。但是提交数据不起作用。
答案 0 :(得分:4)
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
答案 1 :(得分:1)
您可以使用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);
祝你好运!!!