返回一个对象 Android
Posted
技术标签:
【中文标题】返回一个对象 Android【英文标题】:return an object Android 【发布时间】:2015-06-03 10:26:02 【问题描述】:我想返回一个包含一些东西的对象。
这是声明;
Object user_det = get_user_det();
功能代码如下:
private Object get_user_det()
Firebase f_user = new Firebase("https://myapp.firebaseio.com/User/");
f_user.addListenerForSingleValueEvent(new ValueEventListener()
@Override
public void onDataChange(DataSnapshot snap_user)
// TODO Auto-generated method stub
Iterable<DataSnapshot> rs = snap_user.getChildren();
Iterator<DataSnapshot> irs = rs.iterator();
long allNum2 = snap_user.getChildrenCount();
int maxNum2 = (int)allNum2;
int count_user = 1;
while(irs.hasNext())
if(count_user <= maxNum2)
Firebase user_data = new Firebase("https://myapp.firebaseio.com/");
AuthData authData = user_data.getAuth();
Map<String, Object> nPost = (Map<String, Object>) irs.next().getValue();
String db_email = nPost.get("email_addr").toString();
if (authData != null)
String usr_email = authData.getProviderData().get("email").toString();
if(usr_email.equals(db_email))
//NB: I WANT TO ADD THE FOLLOWING INTO THE OBJECT
String disp_name = nPost.get("disp_name").toString();
String real_name = nPost.get("real_name").toString();
else
System.out.println("Failed");
count_user++;
@Override
public void onCancelled(FirebaseError arg0)
// TODO Auto-generated method stub
);
return null; //NB: I NEED TO RETURN THE OBJECT HERE.
我想返回字符串 disp_name 和 real_name 但它们在 addListenerForSingleValueEvent 中,那么如何将它们取出并返回给函数。
我在需要帮助的代码中写了“NB”。
感谢您的宝贵时间。
【问题讨论】:
您可以将它们添加到 ArrayList 中并返回它们.. 是吗?如果我是正确的,请告诉我。 @mubeen,不需要ArrayList,一个简单的String数组就可以了。 【参考方案1】:如果你想从你的 java 方法中返回一个对象,这样做:
对象类: 这包含您的对象的结构,并定义其中将包含哪些数据。还包括轻松获取数据的方法。
private class myObject
private String name;
private String realName;
//The constructor, so you can set the data when creating the Object.
public myObject (String disp_name, String real_name)
name = disp_name;
realName = real_name;
//Getter methods, to get the data.
public String getRealName() return realName;
public String getDisplayName() return name;
您的代码:
private Object get_user_det()
myObject o; //Declare it, so it can be returned.
...
String disp_name = nPost.get("disp_name").toString();
String real_name = nPost.get("real_name").toString();
o = new myObject(disp_name, real_name); //create it and set the data.
...
return myobject; //return the new Object with the data.
从对象中获取数据:
myObject o = get_user_det(); //Call the metod which return our Object.
String realName = o.getRealName(); //Get the data from the Object.
String displayName = o.getDisplayName;
在您的情况下,使用字符串数组会容易得多。
希望这会有所帮助。
【讨论】:
【参考方案2】:如果您在代码中添加一些println
s,可能最容易看到发生了什么:
private Object get_user_det()
Firebase f_user = new Firebase("https://myapp.firebaseio.com/User/");
System.out.println("Adding listener");
f_user.addListenerForSingleValueEvent(new ValueEventListener()
@Override
public void onDataChange(DataSnapshot snap_user)
System.out.println("Data received");
@Override
public void onCancelled(FirebaseError arg0)
// TODO Auto-generated method stub
);
System.out.println("Returning");
return null; //NB: I NEED TO RETURN THE OBJECT HERE.
如果你执行这段代码,你会看到它记录:
Adding listener
Returning
Data received
这很可能不是您所期望的。但是,如果您阅读下面的解释,希望它是有意义的。
异步加载
当你注册你的听众时:
f_user.addListenerForSingleValueEvent(new ValueEventListener()
您告诉 Firebase开始 监听事件。它关闭并开始从服务器检索数据。
由于检索数据可能需要一些时间,因此它会异步执行此检索,以免您的线程被阻塞。完全检索数据后,Firebase 会在您的侦听器中调用 onDataChange
方法。
在您开始收听和调用onDataChange
之间,您的代码会继续执行。所以没有办法返回异步加载的数据,因为当你的函数返回时,数据还没有加载。
解决方案
免责声明:我不是用 Java 解决这个问题的专家,所以我的解决方案可能存在问题。如果^H^H发现有,请在cmets中报告。
我知道该问题的三种可能解决方案:
-
强制代码等待数据返回
返回一个在某个时候将包含数据的 Future
将回调传递给
get_user_det
,并在数据可用时调用该函数
您可能会倾向于选择选项 1,因为它与您加载数据的心理模式最匹配。虽然这不一定是错误的,但请记住,异步加载是有充分理由的。现在可能值得接受“学习如何处理异步”的惩罚。
我不会为所有解决方案编写示例,而是参考一些相关问题:
Retrieving data from firebase returning NULL(使用方法3的答案) Is waiting for return, ok? Java wait() & notify() vs android wait() & notify()(来自采用方法 1 的用户提出的问题)【讨论】:
【参考方案3】:工作原理:
Firebase 使用反射构建 JSON 树对象以保存到数据库。当您检索此 JSON 树时,您可以将其转换回您的原始对象。就像序列化和反序列化一样。这意味着当您尝试像您一样“重建”您的对象时,您不需要处理键和值。都可以这样完成:
YourObject 对象 = (YourObject) dataSnapshot.getValue(YourObject.class);
注意getValue()
中的YourObject.class
。这告诉 firebase 通过此类进行反射并使用 dataSnapshot 找到适当的访问器。
怎么做
确保您的对象具有:
-
访问器 为所有字段提供适当的 getter 和 setter -(如果您不想保存特定字段,请使用
@JsonIgnore
注释)
空构造函数。您的对象必须提供一个完全不修改自身的构造函数。
你的对象应该是什么样子:
public class YourObject
private String displayName;
private String realName;
public YourObject() /*Empty constructor needed for Firebase */
// Accessors
public void setRealName(String realName)
this.realName = realName;
public String getRealName()
return this.realName;
public String getDisplayName()
return this.displayName;
public void setDisplayName(String displayName)
this.displayName = displayName;
然后,在任何 firebase 回调中,您只需将 DataSnapshot 投射到您的对象中:
public void onDataChange(DataSnapshot snap_user)
YourObject object = new Object;
if(snap_user.getValue() != null)
try
object = (YourObject) snap_user.getValue(YourObject.class); <-- Improtant!!!
catch(ClassCastException ex)
ex.printStackTrace();
return object;
还有
您似乎正在检索许多对象。执行此操作时,我发现最好使用 onChildEventListener
,然后对于该节点中的 每个 YourObject
s,将调用 onChildAdded(DataSnapshot ds, String previousChild);
。
【讨论】:
以上是关于返回一个对象 Android的主要内容,如果未能解决你的问题,请参考以下文章
AndroidAndroid动态代理为SurfaceHolder添加Hook