我正在尝试使用FirebaseUI及其recyclerAdapter在recyclerView中显示以下JSON结构。
我正在关注我假设的Firebase团队制作的示例(我自己在这里和那里进行了更改)Firebase Quickstart - Database
JSON Firebase结构:
{
"restaurants": {
"pushID": {
"name": "string",
"address": "string",
"times": "string",
"logo": "string",
"phone": "string",
"email": "string",
"order": "true", //Boolean
"booking": "true",
"delivery": "false"
},
...
}
}
我已经查看过关于在这里和其他网站(即GitHub)上收到“NoSuchMethodException”的帖子。
一般的答案似乎是有两个可能的原因:
1)确保您的viewHolder类是公开的
2)如果你的TaskViewHolder是一个内部类,例如你的活动,确保它是静态的
以下是相关代码。
型号:
@IgnoreExtraProperties
public class Restaurant {
public String name, address,
time, logo, phone;
public String uid;
public int favoriteCount = 0;
public Map<String, Boolean> favorites = new HashMap<>();
public Restaurant(){
// Default constructor required for calls to DataSnapshot.getValue(Restaurant.class)
}
public Restaurant(String name, String address, String time,
String logo, String phone, String uid){
this.name = name;
this.address = address;
this.time = time;
this.logo = logo;
this.phone = phone;
this.uid = uid;
}
@Exclude
public Map<String, Object> toMap() {
HashMap<String, Object> result = new HashMap<>();
result.put("uid", uid);
result.put("name", name);
result.put("time", time);
result.put("logo", logo);
result.put("favoriteCount", favoriteCount);
result.put("favorites", favorites);
return result;
}
}
我的viewHolder类(它是一个单独的类;因此不需要“static”)。
EllipsisUtil.class是我使用的方法,将文本视图限制为单行。没什么好看的。
public class RestaurantViewHolder extends RecyclerView.ViewHolder {
public TextView restaurantName, restaurantAddress; //tvDate, tvTime, tvPeople;
public ImageView restaurantImageLogo, restaurantFavorite;
private final Activity activity;
private Locale locale = Locale.US;
//private SimpleDateFormat dateFormat = new SimpleDateFormat("EEEE, MMMM dd yyyy", locale);
public RestaurantViewHolder(Activity activity, View itemView){
super(itemView);
this.activity = activity;
restaurantName = (TextView) itemView.findViewById(R.id.resName);
restaurantAddress = (TextView) itemView.findViewById(R.id.resAddress);
restaurantImageLogo = (ImageView) itemView.findViewById(R.id.RestaurantLogo);
restaurantFavorite = (ImageButton) itemView.findViewById(R.id.rFavorite);
//additional views for bookings activity
/*
tvDate = (TextView) itemView.findViewById(R.id.bookingDate);
tvTime = (TextView) itemView.findViewById(R.id.bookingTime);
tvPeople = (TextView) itemView.findViewById(R.id.numberPeople);
*/
}
public void bindToRestaurant(Restaurant restaurant, View.OnClickListener favoriteClickListener) {
//final int peopleNum = Integer.parseInt(restaurantInfo.booking_people);
restaurantName.setText(restaurant.name);
singleLineText(restaurantName);
restaurantAddress.setText(restaurant.address);
singleLineText(restaurantAddress);
restaurantFavorite.setOnClickListener(favoriteClickListener);
// Create a storage reference from our app
String dirName = "restaurantLogos/";
String bucketUrl = "myFirebaseURL/";
// Initialize Storage
StorageReference mStorageRef = FirebaseStorage.getInstance().getReference();
StorageReference storageRef = mStorageRef.getStorage().
getReferenceFromUrl(bucketUrl+dirName+restaurant.logo+".png");
String logoUrl = storageRef.getDownloadUrl().toString();
Glide.with(activity).load(logoUrl).into(restaurantImageLogo);
//additional views for bookings activity
/*
tvDate.setText(dateFormat.format(restaurantInfo.booking_date));
tvTime.setText(restaurantInfo.booking_time);
String people;
if (peopleNum > 1){
people = restaurantInfo.booking_people+" people";
}else{
people = restaurantInfo.booking_people+" person";
}
tvPeople.setText(people);
*/
}
public void singleLineText(TextView textView){
EllipsisUtil ellipsisUtil = new EllipsisUtil(textView);
ellipsisUtil.singleLineText();
}
}
我的处理Firebase适配器的活动类
// Set up FirebaseRecyclerAdapter with the Query
Query restaurantQuery = getQuery(mDatabase);
mAdapter = new FirebaseRecyclerAdapter<Restaurant, RestaurantViewHolder>(Restaurant.class, R.layout.list_row,
RestaurantViewHolder.class, restaurantQuery) {
@Override
protected void populateViewHolder(final RestaurantViewHolder viewHolder, final Restaurant model, int position) {
final DatabaseReference restaurantRef = getRef(position);
final String restaurantKey = restaurantRef.getKey();
//setting Strings data for intent data passing
//final String time = model.restaurant_time;
//final String phone = model.restaurant_phone;
//Log.d(TAG, "2: "+time+" / "+phone);
// Set click listener for the whole post view
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//starting a new intent from onClick action
Context context = v.getContext();
//RV = Restaurant View
Intent intentRV = new Intent(context, Restaurant.class);
intentRV.putExtra("rName", viewHolder.restaurantName.getText().toString());
intentRV.putExtra("rAddress", viewHolder.restaurantAddress.getText().toString());
//intentRV.putExtra("rTime",time);
//intentRV.putExtra("rPhone",phone);
//pass RID to next activity
intentRV.putExtra("resID", restaurantKey);
context.startActivity(intentRV);
}
});
// Determine if the current user has liked this post and set UI accordingly
if (model.favorites.containsKey(getUid())) {
viewHolder.restaurantFavorite.setImageResource(R.drawable.ic_favorite_white_24dp);
} else {
viewHolder.restaurantFavorite.setImageResource(R.drawable.ic_favorite_border_white_24dp);
}
viewHolder.bindToRestaurant(model, new View.OnClickListener() {
@Override
public void onClick(View favoriteView) {
// Need to write to both places the post is stored
DatabaseReference globalRestaurantRef = mDatabase.child("favorites").child(restaurantRef.getKey());
DatabaseReference userRestaurantRef = mDatabase.child("user_favorites").child(model.uid).child(restaurantRef.getKey());
// Run two transactions
onFavoriteClicked(globalRestaurantRef);
onFavoriteClicked(userRestaurantRef);
}
});
}
};
recyclerView.setAdapter(mAdapter);
}
我的查询方法
public Query getQuery(DatabaseReference databaseReference){
// All the restaurants
return databaseReference.child("restaurants");//restaurants
}
我得到的Logcat错误:
java.lang.RuntimeException: java.lang.NoSuchMethodException: <init> [class android.view.View]
at com.firebase.ui.database.FirebaseRecyclerAdapter.onCreateViewHolder(FirebaseRecyclerAdapter.java:171)
at android.support.v7.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:6290)
at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5478)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5363)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5359)
at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2141)
at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1525)
at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1488)
at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:585)
at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3506)
at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3254)
at android.support.v7.widget.RecyclerView.consumePendingUpdateOperations(RecyclerView.java:1623)
at android.support.v7.widget.RecyclerView$1.run(RecyclerView.java:331)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
at android.view.Choreographer.doCallbacks(Choreographer.java:580)
at android.view.Choreographer.doFrame(Choreographer.java:549)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
Caused by: java.lang.NoSuchMethodException: <init> [class android.view.View]
at java.lang.Class.getConstructor(Class.java:531)
at java.lang.Class.getConstructor(Class.java:495)
at com.firebase.ui.database.FirebaseRecyclerAdapter.onCreateViewHolder(FirebaseRecyclerAdapter.java:168)
at android.support.v7.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:6290)
at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5478)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5363)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5359)
at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2141)
at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1525)
at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1488)
at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:585)
at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3506)
at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3254)
at android.support.v7.widget.RecyclerView.consumePendingUpdateOperations(RecyclerView.java:1623)
at android.support.v7.widget.RecyclerView$1.run(RecyclerView.java:331)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
at android.view.Choreographer.doCallbacks(Choreographer.java:580)
at android.view.Choreographer.doFrame(Choreographer.java:549)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
java.lang.RuntimeException: java.lang.NoSuchMethodException: <init> [class android.view.View]
at com.firebase.ui.database.FirebaseRecyclerAdapter.onCreateViewHolder(FirebaseRecyclerAdapter.java:171)
at android.support.v7.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:6290)
at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5478)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5363)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5359)
at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2141)
at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1525)
at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1488)
at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:585)
at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3506)
at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3254)
at android.support.v7.widget.RecyclerView.consumePendingUpdateOperations(RecyclerView.java:1623)
at android.support.v7.widget.RecyclerView$1.run(RecyclerView.java:331)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
at android.view.Choreographer.doCallbacks(Choreographer.java:580)
at android.view.Choreographer.doFrame(Choreographer.java:549)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
Caused by: java.lang.NoSuchMethodException: <init> [class android.view.View]
at java.lang.Class.getConstructor(Class.java:531)
at java.lang.Class.getConstructor(Class.java:495)
at com.firebase.ui.database.FirebaseRecyclerAdapter.onCreateViewHolder(FirebaseRecyclerAdapter.java:168)
at android.support.v7.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:6290)
at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5478)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5363)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5359)
at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2141)
at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1525)
at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1488)
at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:585)
at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3506)
at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3254)
at android.support.v7.widget.RecyclerView.consumePendingUpdateOperations(RecyclerView.java:1623)
at android.support.v7.widget.RecyclerView$1.run(RecyclerView.java:331)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
at android.view.Choreographer.doCallbacks(Choreographer.java:580)
at android.view.Choreographer.doFrame(Choreographer.java:549)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
这是我的祖父依赖:
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:25.1.0'
compile 'com.android.support:design:25.1.0'
compile 'com.android.support:recyclerview-v7:25.1.0'
compile 'com.github.bumptech.glide:glide:3.7.0'
compile 'com.android.volley:volley:1.0.0'
compile 'com.firebaseui:firebase-ui-database:1.0.0'
compile 'com.google.firebase:firebase-database:10.0.1'
compile 'com.google.firebase:firebase-storage:10.0.1'
compile 'com.google.firebase:firebase-crash:10.0.1'
compile 'com.google.firebase:firebase-auth:10.0.1'
compile 'com.google.firebase:firebase-ads:10.0.1'
compile 'com.google.firebase:firebase-invites:10.0.1'
compile 'com.google.firebase:firebase-core:10.0.1'
compile 'com.android.support:support-v4:25.1.0'
compile 'com.google.firebase:firebase-appindexing:10.0.1'
}
这是我的progaurd规则:
-keepattributes Signature
-keepattributes *Annotation*
-keepattributes EnclosingMethod
-keepattributes InnerClasses
-keep class package.ViewHolder.** {
*;
}
-keepclassmembers class package.Models.** {
*;
}
到目前为止,我已经尝试过多次写作而没有运气。
请协助我找到解决方案。
答案 0 :(得分:1)
您只需要替换
compile 'com.firebaseui:firebase-ui-database:1.0.0'
到
compile 'com.firebaseui:firebase-ui-database:1.0.1'
在你的app level build.gradle文件中。
您使用的10.0.1
Firebase / Play服务版需要1.0.1
FirebaseUI版本。所以这将解决你的问题。
参考下表:
> FirebaseUI Version Firebase/Play Services Version
> 1.0.1 10.0.0 or 10.0.1
> 1.0.0 9.8.0
> 0.6.2 9.8.0
> 0.6.1 9.6.1
> 0.6.0 9.6.0
> 0.5.3 9.4.0
> 0.4.4 9.4.0
> 0.4.3 9.2.1
> 0.4.2 9.2.0
> 0.4.1 9.0.2
> 0.4.0 9.0.0
答案 1 :(得分:-1)
看来你的餐厅课是错的。 您必须提供完整的JSON,
餐厅类应该是这样的:
public class Restaurant {
public PushID pushId;
//Constructor
//getter and setters for PushId
public void setPushId(PushId pushId) {
this.pushId = pushId;
}
public PushId getPushId() {
return pushId;
}
}
PushId Class应该是这样的
public class PushId {
public String name, address,
time, logo, phone;
public String uid;
public int favoriteCount = 0;
public Map<String, Boolean> favorites = new HashMap<>();
public Restaurant() {
}
public Restaurant(String name, String address, String time,
String logo, String phone, String uid) {
this.name = name;
this.address = address;
this.time = time;
this.logo = logo;
this.phone = phone;
this.uid = uid;
}
@Exclude
public Map<String, Object> toMap() {
HashMap<String, Object> result = new HashMap<>();
result.put("uid", uid);
result.put("name", name);
result.put("time", time);
result.put("logo", logo);
result.put("favoriteCount", favoriteCount);
result.put("favorites", favorites);
return result;
}
使用字段
中的字段答案 2 :(得分:-1)
ViewHolder类需要是public static
公共静态类RestaurantViewHolder扩展了RecyclerView.ViewHolder