2017-01-12 109 views
3

我有一個使用片段的NavigationDrawer活動。在我的一個片段中,我想將Firebase數據庫中的數據加載到RecyclerView中。Android - 從片段中的Firebase數據庫加載數據

所以我有一個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的ArrayList中的()我得到的數據。所以從數據庫加載數據正在工作。但呈現數據不起作用。

回答

3

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

您可以使用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); 

祝你好運!