如何从android中的firebase中检索List对象

Posted

技术标签:

【中文标题】如何从android中的firebase中检索List对象【英文标题】:How to Retrieve a List object from the firebase in android 【发布时间】:2015-08-24 23:45:50 【问题描述】:

我在从 Firebase 检索列表时遇到问题。我存储它没有问题,但是一旦我尝试将 dataSnapshot.getValue() 转换为 ArrayList,我的应用程序就会崩溃,并给出一个异常:

HashMap 不能转换为 ArrayList

但是当我尝试将其转换为 HashMap 时,它也会崩溃,并给出异常:

ArrayList 不能转换为 hashmap

需要帮助!这是造成问题的代码:

Fire.addValueEventListener(new ValueEventListener() 
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) 
        List<TaskDes> td = (ArrayList<TaskDes>) dataSnapshot.getValue()
        notifyDataSetChanged();
    

    @Override
    public void onCancelled(FirebaseError firebaseError) 

    
);

我想将 Firebase 中的所有数据检索为一个列表。 TaskDes 类包含三个字段:

class TaskDes  // definition
    boolean done
    String taskDescription
    String taskTitle

【问题讨论】:

很遗憾,这里没有足够的代码来帮助您解决问题。积极的一面:Firebase 的 androidChat 示例应用可以满足您的所有需求,仅此而已。在这里看看:github.com/firebase/AndroidChat/tree/master/app/src/main/java/…。我最近在 Firebase Google Group 上解释了它的内部结构:groups.google.com/d/msg/firebase-talk/OCoQPvpgl1U/Nli_OywG7LYJ 谢谢,我会试一试,另一件事我想问一下我是否将 hashmap 存储在火力基地上,然后从火力基地检索它时,我可以直接投射datasnapshot.getValue() 到 hashmap ?? 是的,这是可能的。但前提是您正确地为 Task 类建模。看看这个例子。你的Task 应该看起来像github.com/firebase/AndroidChat/blob/master/app/src/main/java/… 【参考方案1】:

您需要创建一个 GenericTypeIndicator 对象以作为DataSnapshot.getValue() 参数传递。

代码:

GenericTypeIndicator<List<String>> t = new GenericTypeIndicator<List<String>>() ;

List<String> yourStringArray = dataSnapshot.getValue(t);

【讨论】:

如果列表在另一个对象中怎么办? @GregEnnis 如果列表在另一个对象中,你有没有想过如何解决它? @GregEnnis 我找到了方法。 GenericTypeIndicator&lt;MyModel&gt; t = new GenericTypeIndicator&lt;MyModel&gt;() ; 就这样。在我的MyModel 中,我有一个List 以及其他字段。 老兄,你救了我的命【参考方案2】:

你的模型

public class TaskDes 
    private boolean done;
    private String taskDescription;
    private String taskTitle;

    public TaskDes() 
    

    public boolean isDone() 
        return done;
    

    public void setDone(boolean done) 
        this.done = done;
    

    public String getTaskDescription() 
        return taskDescription;
    

    public void setTaskDescription(String taskDescription) 
        this.taskDescription = taskDescription;
    

    public String getTaskTitle() 
        return taskTitle;
    

    public void setTaskTitle(String taskTitle) 
        this.taskTitle = taskTitle;
    


您需要创建一个GenericTypeIndicator 对象以作为DataSnapshot.getValue() 参数传递。

活动中

 private static final String TAG=MainActivity.class.getSimpleName();
 private FirebaseDatabase database;
 private DatabaseReference myRef=null;

 @Override
 protected void onCreate(Bundle savedInstanceState)
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    database=FirebaseDatabase.getInstance();
    myRef=database.getReference("ADD_YOUR_REFERECE");


    myRef.addValueEventListener(new ValueEventListener()
       @Override
       public void onDataChange(DataSnapshot dataSnapshot)
          /* This method is called once with the initial value and again whenever data at this location is updated.*/
          long value=dataSnapshot.getChildrenCount();
          Log.d(TAG,"no of children: "+value);

          GenericTypeIndicator<List<TaskDes>> genericTypeIndicator =new GenericTypeIndicator<List<TaskDes>>();

          List<TaskDes> taskDesList=dataSnapshot.getValue(genericTypeIndicator);

          for(int i=0;i<taskDesList.size();i++)
             Toast.makeText(MainActivity.this,"TaskTitle = "+taskDesList.get(i).getTaskTitle(),Toast.LENGTH_LONG).show();
          
       

       @Override
       public void onCancelled(DatabaseError error)
          // Failed to read value
          Log.w(TAG,"Failed to read value.",error.toException());
       
    );
 

【讨论】:

感谢它帮助很大【参考方案3】:

制作另一个包含您的项目列表的项目: 这是你的物品:

class TaskDes  // definition
    boolean done
    String taskDescription
    String taskTitle

这是列表项

        class TaskDesList  // definition
              private  ArreyList<TaskDes> yourlist
            

      public TaskDesList()
         

        public ArrayList<TaskDes> getYourlist() 
            return yourlist;
        

当调用 EventListener 时

ref.addValueEventListener(new ValueEventListener() 
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) 
                yourlist.clear();
             taskDesList=dataSnapshot.getValue(TaskDesList.class);
                if (taskDesList!=null) 
                    yourlist= taskDesList.getYourlist();
                

现在“yourlist”是一个包含所有“TaskDes”项目的列表

【讨论】:

【参考方案4】:

有点晚了,但以防万一其他人需要。

如果列表在另一个对象中。

对象

public class Question 

    public Date date;
    public String questionNumber;
    public String questionText;
    public QuestionType questionType;
    public String multipleSelection1;
    public String multipleSelection2;
    public String multipleSelection3;

    public Question() 
        // Default constructor required for calls to DataSnapshot.getValue(User.class)
    

然后得到你的问题对象数组

GenericTypeIndicator<List<Question>> t = new GenericTypeIndicator<List<Question>>() ;
List<Question> questionList = dataSnapshot.getValue(t);

【讨论】:

【参考方案5】:

显然,GenericTypeIndicator 不适用于所有 List 对象,尤其是当对象不包含像地图这样的原始类型时。因此,如果它不适用于您的用例,因为它不适用于我,请尝试以下替代解决方案:

 @Override
 public void onDataChange(DataSnapshot dataSnapshot) 

    List<TaskDes> tDlist = new ArrayList<>();

    for (DataSnapshot d: dataSnapshot.getChildren())
        TaskDes tD = d.getValue(TaskDes.class);
        tDlist.add(tD);
    

    notifyDataSetChanged();
 

如前面的答案中所述,请确保您的类(如本例中的 TaskDes)有一个为空的公共构造函数,以便 getValue 方法可以正确反序列化为您的 java 类。

【讨论】:

以上是关于如何从android中的firebase中检索List对象的主要内容,如果未能解决你的问题,请参考以下文章

如何根据 android 中的用户位置从 Firebase 数据库中检索数据?

如何从firebase检索多个数据到android中的列表视图?

发送数据时,从 Android 应用中的 Firebase 检索 ServerValue.Timestamp

我如何从firebase检索数据到android listview顶部[重复]

如何在 Android 中使用 MVC 模式从 firebase 检索数据? [复制]

从多个孩子 Android Firebase 中检索同一个孩子