Firebase Android 访问 child
Firebase Android accessing child
我今天请求你的帮助,因为我的应用程序在使用 FirebaseDatabase 和 FireBaseAdapter 时遇到问题。
DB 的结构如下所示:
`{
"First_Main_Node" : {
"Child_Node1" : {
"description" : "Blabla",
"image" : "Image1.jpg",
"title" : "My Awesome Title"
},
"Child_Node2" : {
"description" : "Blabla",
"image" : "Image2.jpg",
"title" : "My Awesome Title"
},
"Child_Node3" : {
"description" : "Blabla",
"image" : "Image3.jpg",
"title" : "My Awesome Title"
},
"Child_Node4" : {
"description" : "Blabla",
"image" : "Image4.jpg",
"title" : "My Awesome Title"
},
"Child_Node5" : {
"description" : "Blabla",
"image" : "Image5.jpg",
"title" : "My Awesome Title"
},
"Child_Node6" : {
"description" : "Blabla",
"image" : "Image6.jpg",
"title" : "My Awesome Title"
},
"Child_Node7" : {
"description" : "Blabla",
"image" : "Image7.jpg",
"title" : "My Awesome Title"
},
"Child_Node8" : {
"description" : "Blabla",
"image" : "Image8.jpg",
"title" : "My Awesome Title"
}
},
"Second_Main_Node" : {
"Child_Node1" : {
"Element" : {
"image" : "Image1.jpg",
"price" : "100",
"title" : "My Awesome Title"
}
}
}`
我的应用程序的主要 activity 是一个带有 Cardviews 的 RecyclerView,我使用 FirebaseAdapter 填充它,它通过获取 child 填充 viewHolder First_Main_Node 使用这行代码:
myRef = FirebaseDatabase.getInstance().getReference().child("/First_Main_Node");
事实是,正如您在 DB 结构中看到的那样,有一个 Second_Main_Node,他有 Nested Child_Node,他有 Nested Element 本身终于有了标题、价格、图片 child .
我的问题来了,我想访问 Second_Main_Node > Child_Node1 并填充另一个 RecyclerView 但是这次使用所有 "Element" child人内Child_Node1
我尝试了上面的代码行,通过 /Second_Main_Node/Child_Node1 更改 child 方法路径参数,但是 RecyclerView 显示带有“Null" 作为标题,没有其他任何事情发生,或者我的应用程序在打开第二个 RecyclerView 后立即崩溃,我试图更改参考,Child,但都没有成功,我不明白我如何访问这些元素并填充第二个 RecyclerView ,我认为这并不难,但我已经将近一个星期试图解决这个问题。
这是与 MainActivity RecyclerView 相关的代码
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new GridLayoutManager(this, 2));
myref = FirebaseDatabase.getInstance().getReference().child("/First_Main_Node");
FirebaseRecyclerAdapter<Watch, MainActivity.WatchViewHolder> recyclerAdapter = new FirebaseRecyclerAdapter<Watch, MainActivity.WatchViewHolder>(
Watch.class,
R.layout.individual_row,
MainActivity.WatchViewHolder.class,
myref
) {
@Override
protected void populateViewHolder(final MainActivity.WatchViewHolder viewHolder, final Watch model, int position) {
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent(MainActivity.this, WatchDisplayActivity.class);
startActivity(i);
}
});
viewHolder.setTitle(model.getTitle());
viewHolder.setDescription(model.getDescription());
viewHolder.setImage(model.getImage());
}
};
recyclerView.setAdapter(recyclerAdapter);
}
public static class WatchViewHolder extends RecyclerView.ViewHolder {
View mView;
TextView textView_title;
TextView textView_description;
ImageView imageView;
public WatchViewHolder(View itemView) {
super(itemView);
mView = itemView;
textView_title = itemView.findViewById(R.id.tv_titre);
textView_description = itemView.findViewById(R.id.tv_desc);
imageView = itemView.findViewById(R.id.iv_image);
}
public void setTitle(String title) {
textView_title.setText(title + "");
}
public void setDescription(String description) {
textView_description.setText(description);
}
public void setImage(String image) {
Picasso.with(mView.getContext())
.load(image)
.into(imageView);
}
}
}
和第二个RecylerView相关的那个
rv_display.setHasFixedSize(true);
rv_display.setLayoutManager(new GridLayoutManager(this,2));
myref = FirebaseDatabase.getInstance().getReference().child("/Second_Main_Node/Child_Node1");
FirebaseRecyclerAdapter<Watch, WatchDisplayActivity.WatchViewHolder> recyclerAdapter = new FirebaseRecyclerAdapter<Watch, WatchViewHolder>(
Watch.class,
R.layout.individual_row_display,
WatchDisplayActivity.WatchViewHolder.class,
myref
) {
@Override
protected void populateViewHolder(WatchViewHolder viewHolder, Watch model, int position) {
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(),"Test",Toast.LENGTH_SHORT).show();
}
});
viewHolder.setTextView_price(model.getPrice());
viewHolder.setImageView(model.getImage());
viewHolder.setTextView_title(model.getTitle());
}
};rv_display.setAdapter(recyclerAdapter);
}
public static class WatchViewHolder extends RecyclerView.ViewHolder{
View mView;
TextView textView_title;
TextView textView_price;
ImageView imageView;
public WatchViewHolder(View itemView){
super(itemView);
mView = itemView;
textView_price = itemView.findViewById(R.id.tv_price_display);
textView_title = itemView.findViewById(R.id.tv_titre_display);
imageView = itemView.findViewById(R.id.iv_image_display);
}
public void setTextView_title(String title) {
textView_title.setText(title + "");
}
public void setTextView_price(String price) {
textView_price.setText(price);
}
public void setImageView(String image) {
Picasso.with(mView.getContext())
.load(image)
.into(imageView);
}
}
这是Logcat
02-26 16:57:41.103 19143-19143/package_name E/AndroidRuntime: FATAL EXCEPTION: main
Process: fr.package_name, PID: 19143
com.google.firebase.database.DatabaseException: Failed to convert value of type java.lang.Double to String
at com.google.android.gms.internal.zg.zzb(Unknown Source)
at com.google.android.gms.internal.zg.zza(Unknown Source)
at com.google.android.gms.internal.zg.zzb(Unknown Source)
at com.google.android.gms.internal.zh.zze(Unknown Source)
at com.google.android.gms.internal.zg.zzb(Unknown Source)
at com.google.android.gms.internal.zg.zza(Unknown Source)
at com.google.firebase.database.DataSnapshot.getValue(Unknown Source)
at com.firebase.ui.database.FirebaseRecyclerAdapter.parseSnapshot(FirebaseRecyclerAdapter.java:154)
at com.firebase.ui.database.FirebaseRecyclerAdapter.getItem(FirebaseRecyclerAdapter.java:143)
at com.firebase.ui.database.FirebaseRecyclerAdapter.onBindViewHolder(FirebaseRecyclerAdapter.java:183)
at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:6482)
at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:6515)
at android.support.v7.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:5458)
at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5724)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5563)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5559)
at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2229)
at android.support.v7.widget.GridLayoutManager.layoutChunk(GridLayoutManager.java:556)
at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1516)
at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:608)
at android.support.v7.widget.GridLayoutManager.onLayoutChildren(GridLayoutManager.java:170)
at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3693)
at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3410)
at android.support.v7.widget.RecyclerView.consumePendingUpdateOperations(RecyclerView.java:1710)
at android.support.v7.widget.RecyclerView.run(RecyclerView.java:346)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:858)
at android.view.Choreographer.doCallbacks(Choreographer.java:670)
at android.view.Choreographer.doFrame(Choreographer.java:603)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:844)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:234)
at android.app.ActivityThread.main(ActivityThread.java:5526)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:102)
问题解决了,确实 price child 需要一个字符串,而我给出了一个 long/float 类型。
通过在价格值上添加双引号 price: "99,9"
而不是 price: 99,9
它解决了问题,我现在可以在没有崩溃或异常的情况下访问子节点
我今天请求你的帮助,因为我的应用程序在使用 FirebaseDatabase 和 FireBaseAdapter 时遇到问题。
DB 的结构如下所示:
`{
"First_Main_Node" : {
"Child_Node1" : {
"description" : "Blabla",
"image" : "Image1.jpg",
"title" : "My Awesome Title"
},
"Child_Node2" : {
"description" : "Blabla",
"image" : "Image2.jpg",
"title" : "My Awesome Title"
},
"Child_Node3" : {
"description" : "Blabla",
"image" : "Image3.jpg",
"title" : "My Awesome Title"
},
"Child_Node4" : {
"description" : "Blabla",
"image" : "Image4.jpg",
"title" : "My Awesome Title"
},
"Child_Node5" : {
"description" : "Blabla",
"image" : "Image5.jpg",
"title" : "My Awesome Title"
},
"Child_Node6" : {
"description" : "Blabla",
"image" : "Image6.jpg",
"title" : "My Awesome Title"
},
"Child_Node7" : {
"description" : "Blabla",
"image" : "Image7.jpg",
"title" : "My Awesome Title"
},
"Child_Node8" : {
"description" : "Blabla",
"image" : "Image8.jpg",
"title" : "My Awesome Title"
}
},
"Second_Main_Node" : {
"Child_Node1" : {
"Element" : {
"image" : "Image1.jpg",
"price" : "100",
"title" : "My Awesome Title"
}
}
}`
我的应用程序的主要 activity 是一个带有 Cardviews 的 RecyclerView,我使用 FirebaseAdapter 填充它,它通过获取 child 填充 viewHolder First_Main_Node 使用这行代码:
myRef = FirebaseDatabase.getInstance().getReference().child("/First_Main_Node");
事实是,正如您在 DB 结构中看到的那样,有一个 Second_Main_Node,他有 Nested Child_Node,他有 Nested Element 本身终于有了标题、价格、图片 child .
我的问题来了,我想访问 Second_Main_Node > Child_Node1 并填充另一个 RecyclerView 但是这次使用所有 "Element" child人内Child_Node1
我尝试了上面的代码行,通过 /Second_Main_Node/Child_Node1 更改 child 方法路径参数,但是 RecyclerView 显示带有“Null" 作为标题,没有其他任何事情发生,或者我的应用程序在打开第二个 RecyclerView 后立即崩溃,我试图更改参考,Child,但都没有成功,我不明白我如何访问这些元素并填充第二个 RecyclerView ,我认为这并不难,但我已经将近一个星期试图解决这个问题。
这是与 MainActivity RecyclerView 相关的代码
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new GridLayoutManager(this, 2));
myref = FirebaseDatabase.getInstance().getReference().child("/First_Main_Node");
FirebaseRecyclerAdapter<Watch, MainActivity.WatchViewHolder> recyclerAdapter = new FirebaseRecyclerAdapter<Watch, MainActivity.WatchViewHolder>(
Watch.class,
R.layout.individual_row,
MainActivity.WatchViewHolder.class,
myref
) {
@Override
protected void populateViewHolder(final MainActivity.WatchViewHolder viewHolder, final Watch model, int position) {
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent(MainActivity.this, WatchDisplayActivity.class);
startActivity(i);
}
});
viewHolder.setTitle(model.getTitle());
viewHolder.setDescription(model.getDescription());
viewHolder.setImage(model.getImage());
}
};
recyclerView.setAdapter(recyclerAdapter);
}
public static class WatchViewHolder extends RecyclerView.ViewHolder {
View mView;
TextView textView_title;
TextView textView_description;
ImageView imageView;
public WatchViewHolder(View itemView) {
super(itemView);
mView = itemView;
textView_title = itemView.findViewById(R.id.tv_titre);
textView_description = itemView.findViewById(R.id.tv_desc);
imageView = itemView.findViewById(R.id.iv_image);
}
public void setTitle(String title) {
textView_title.setText(title + "");
}
public void setDescription(String description) {
textView_description.setText(description);
}
public void setImage(String image) {
Picasso.with(mView.getContext())
.load(image)
.into(imageView);
}
}
}
和第二个RecylerView相关的那个
rv_display.setHasFixedSize(true);
rv_display.setLayoutManager(new GridLayoutManager(this,2));
myref = FirebaseDatabase.getInstance().getReference().child("/Second_Main_Node/Child_Node1");
FirebaseRecyclerAdapter<Watch, WatchDisplayActivity.WatchViewHolder> recyclerAdapter = new FirebaseRecyclerAdapter<Watch, WatchViewHolder>(
Watch.class,
R.layout.individual_row_display,
WatchDisplayActivity.WatchViewHolder.class,
myref
) {
@Override
protected void populateViewHolder(WatchViewHolder viewHolder, Watch model, int position) {
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(),"Test",Toast.LENGTH_SHORT).show();
}
});
viewHolder.setTextView_price(model.getPrice());
viewHolder.setImageView(model.getImage());
viewHolder.setTextView_title(model.getTitle());
}
};rv_display.setAdapter(recyclerAdapter);
}
public static class WatchViewHolder extends RecyclerView.ViewHolder{
View mView;
TextView textView_title;
TextView textView_price;
ImageView imageView;
public WatchViewHolder(View itemView){
super(itemView);
mView = itemView;
textView_price = itemView.findViewById(R.id.tv_price_display);
textView_title = itemView.findViewById(R.id.tv_titre_display);
imageView = itemView.findViewById(R.id.iv_image_display);
}
public void setTextView_title(String title) {
textView_title.setText(title + "");
}
public void setTextView_price(String price) {
textView_price.setText(price);
}
public void setImageView(String image) {
Picasso.with(mView.getContext())
.load(image)
.into(imageView);
}
}
这是Logcat
02-26 16:57:41.103 19143-19143/package_name E/AndroidRuntime: FATAL EXCEPTION: main
Process: fr.package_name, PID: 19143
com.google.firebase.database.DatabaseException: Failed to convert value of type java.lang.Double to String
at com.google.android.gms.internal.zg.zzb(Unknown Source)
at com.google.android.gms.internal.zg.zza(Unknown Source)
at com.google.android.gms.internal.zg.zzb(Unknown Source)
at com.google.android.gms.internal.zh.zze(Unknown Source)
at com.google.android.gms.internal.zg.zzb(Unknown Source)
at com.google.android.gms.internal.zg.zza(Unknown Source)
at com.google.firebase.database.DataSnapshot.getValue(Unknown Source)
at com.firebase.ui.database.FirebaseRecyclerAdapter.parseSnapshot(FirebaseRecyclerAdapter.java:154)
at com.firebase.ui.database.FirebaseRecyclerAdapter.getItem(FirebaseRecyclerAdapter.java:143)
at com.firebase.ui.database.FirebaseRecyclerAdapter.onBindViewHolder(FirebaseRecyclerAdapter.java:183)
at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:6482)
at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:6515)
at android.support.v7.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:5458)
at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5724)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5563)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5559)
at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2229)
at android.support.v7.widget.GridLayoutManager.layoutChunk(GridLayoutManager.java:556)
at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1516)
at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:608)
at android.support.v7.widget.GridLayoutManager.onLayoutChildren(GridLayoutManager.java:170)
at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3693)
at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3410)
at android.support.v7.widget.RecyclerView.consumePendingUpdateOperations(RecyclerView.java:1710)
at android.support.v7.widget.RecyclerView.run(RecyclerView.java:346)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:858)
at android.view.Choreographer.doCallbacks(Choreographer.java:670)
at android.view.Choreographer.doFrame(Choreographer.java:603)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:844)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:234)
at android.app.ActivityThread.main(ActivityThread.java:5526)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:102)
问题解决了,确实 price child 需要一个字符串,而我给出了一个 long/float 类型。
通过在价格值上添加双引号 price: "99,9"
而不是 price: 99,9
它解决了问题,我现在可以在没有崩溃或异常的情况下访问子节点