我需要访问数据库中的books字段。我创建了一个带有recyclerview的片段,用于显示书籍。我在应用程序中需要的是每个用户只能请求一本书。因此,我在根节点下直接创建了另一个节点作为“用户”,但是在添加“用户”节点后,recyclerview无法正常工作。这是添加“用户”后数据库的外观。 Database Snapshot
这是“回收之前”视图: Before Adding users field
这是After RecyclerView: After Adding users field
这是从Firebase数据库导出的json代码。
{
"books" : {
"BOOK 1 BY AUTHOR 1": {
"author" : "Author 1",
"category" : "CLASSICAL",
"description" : "",
"image" : "NO_IMAGE",
"requested" : "NO",
"requester" : "NO_ONE",
"title" : "Book 1"
},
"BOOK 2 BY AUTHOR 2" : {
"author" : "Author 2",
"category" : "SPIRITUALITY",
"description" : "",
"image" : "NO_IMAGE",
"requested" : "NO",
"requester" : "NO_ONE",
"title" : "Book 2"
},
"BOOK 3 BY AUTHOR 3" : {
"author" : "author 3",
"category" : "ADVENTURE",
"description" : "",
"image" : "NO_IMAGE",
"requested" : "NO",
"requester" : "NO_ONE",
"title" : "book 3 "
}
},
"user" : {
"User1" : {
"requestedBook" : "no"
},
"User2" : {
"requestedBook" : "yes"
}
}
}
`这是片段代码。
package club.bms.keshav.readersreserve.fragments;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.Fragment;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import com.google.firebase.database.ChildEventListener;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import java.util.ArrayList;
import java.util.List;
import club.bms.keshav.readersreserve.NewBookAttributes;
import club.bms.keshav.readersreserve.R;
import club.bms.keshav.readersreserve.dataHelper.Book;
import club.bms.keshav.readersreserve.dataHelper.BooksAdapter;
public class HomeFragment extends Fragment{
private static final String TAG = "HomeFragment";
RecyclerView.LayoutManager mLayoutManager;
RecyclerView recyclerView;
List<Book> bookList = new ArrayList<>();
BooksAdapter adapter;
private ChildEventListener childEventListener;
private ProgressBar progressBar;
private DatabaseReference databaseReference;
public HomeFragment() {
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setHasOptionsMenu(true);
Log.d(TAG, "onCreate: ");
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable final ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.activity_recyclerview_declaration, container, false);
view.setBackgroundResource(R.color.white);
Log.d(TAG, "onCreateView: background color set");
recyclerView = view.findViewById(R.id.recycler_view);
progressBar = view.findViewById(R.id.progress_bar_home_fragment);
recyclerView.setVisibility(View.GONE);
progressBar.setVisibility(View.VISIBLE);
final Context context = view.getContext();
FloatingActionButton fab = (FloatingActionButton) view.findViewById(R.id.add_book_fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(context, NewBookAttributes.class));
}
});
mLayoutManager = new GridLayoutManager(view.getContext(), 2, GridLayoutManager.VERTICAL, false);
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
Log.d(TAG, "onCreateView: recyclerview set without adapter");
databaseReference = FirebaseDatabase.getInstance().getReference();
databaseReference.keepSynced(true);
Log.d(TAG, "onCreateView: database ref created");
childEventListener = new ChildEventListener() {
@Override
public void onChildAdded(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
Log.d(TAG, "onChildAdded: ");
getAllBooks(dataSnapshot, context);
}
@Override
public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
Log.d(TAG, "onChildChanged: ");
getAllBooks(dataSnapshot, context);
}
@Override
public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {
taskDeletion(dataSnapshot, context);
}
@Override
public void onChildMoved(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
};
databaseReference.addChildEventListener(childEventListener);
Log.d(TAG, "onCreateView: added listener");
return view;
}
private void taskDeletion(DataSnapshot dataSnapshot, Context context) {
for(DataSnapshot snapshot: dataSnapshot.getChildren())
{
Book book = snapshot.getValue(Book.class);
Book tempBook = new Book();
tempBook.setAuthor(book.getAuthor());
tempBook.setTitle(book.getTitle());
tempBook.setDescription(book.getDescription());
for(int i=0;i<bookList.size();i++)
{
Book b = bookList.get(i);
if(b.getAuthor().equals(tempBook.getAuthor()) && b.getTitle().equals(tempBook.getTitle()))
{
bookList.remove(i);
}
}
}
adapter = new BooksAdapter(context, bookList);
adapter.notifyDataSetChanged();
recyclerView.setAdapter(adapter);
Log.d(TAG, "taskDeletion: adapter set");
}
private void getAllBooks(DataSnapshot dataSnapshot, Context context) {
bookList.clear();
Book book;
for(DataSnapshot dataSnapshot1: dataSnapshot.getChildren()) {
book = dataSnapshot1.getValue(Book.class);
bookList.add(book);
}
adapter = new BooksAdapter(context, bookList);
recyclerView.setAdapter(adapter);
progressBar.setVisibility(View.GONE);
recyclerView.setVisibility(View.VISIBLE);
Log.d(TAG, "getAllBooks: adapter set");
}
@Override
public void onDetach() {
super.onDetach();
databaseReference.removeEventListener(childEventListener);
Log.d(TAG, "onDetach: removed listener");
}
}
当我以编程方式添加“用户”节点时,卡片视图变为空,并且在单击卡片视图时会显示NullPointerException。
这是RecyclerView适配器的代码
package club.bms.keshav.readersreserve.dataHelper;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import com.google.firebase.storage.FirebaseStorage;
import com.google.firebase.storage.StorageReference;
import java.util.List;
import club.bms.keshav.readersreserve.ConstantFields;
import club.bms.keshav.readersreserve.GlideApp;
import club.bms.keshav.readersreserve.R;
import club.bms.keshav.readersreserve.Single_Book_Activity;
class RecyclerViewHolder extends RecyclerView.ViewHolder implements View.OnLongClickListener, View.OnClickListener {
public TextView mAuthor, mTitle, mCategory;
public ImageView mBookImage;
//public TextView btn, mauthor;
private ItemClickListener itemClickListener;
public RecyclerViewHolder(@NonNull View itemView) {
super(itemView);
mAuthor = itemView.findViewById(R.id.textV_book_author);
mTitle = itemView.findViewById(R.id.textV_book_title);
mBookImage = itemView.findViewById(R.id.image_for_book);
mCategory = itemView.findViewById(R.id.textV_book_category);
// mStatus = itemView.findViewById(R.id.textV_book_status);
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
}
public void setmBookImage(String path, final Context context)
{
if(path == null || path.equals(ConstantFields.NO_IMAGE))
{
Glide.with(context)
.load(R.drawable.default_book_cover)
.into(mBookImage);
}
else{
StorageReference storageReference = FirebaseStorage.getInstance().getReference().child("images/" + path + "/" + path + " cover");
GlideApp.with(MyApp.getAppContext())
.load(storageReference)
.apply(new RequestOptions()
.placeholder(R.drawable.rolling_placeholder)
.error(R.drawable.default_book_cover)
)
.into(mBookImage);
}
}
public void setItemClickListener(ItemClickListener itemClickListener) {
this.itemClickListener = itemClickListener;
}
@Override
public void onClick(View v) {
itemClickListener.onClick(v, getAdapterPosition(), false);
}
@Override
public boolean onLongClick(View v) {
itemClickListener.onClick(v, getAdapterPosition(), true);
return true;
}
}
public class BooksAdapter extends RecyclerView.Adapter<RecyclerViewHolder> {
private Context mContext;
private List<Book> bookList;
private Book book;
private ItemClickListener itemClickListener = new ItemClickListener() {
@Override
public void onClick(View view, int position, boolean isLongClicked) {
if (isLongClicked) {
// AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
// builder.setMessage("DELETE");
// AlertDialog dialog = builder.create();
// dialog.show();
//DO SOMETHING
} else {
Intent intent = new Intent(mContext, Single_Book_Activity.class);
Bundle args = new Bundle();
book = bookList.get(position);
args.putSerializable("bookObject", book);
intent.putExtras(args);
mContext.startActivity(intent);
}
}
};
public BooksAdapter(Context mContext, List<Book> bookList) {
this.mContext = mContext;
this.bookList = bookList;
}
@NonNull
@Override
public RecyclerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.book_list_row, parent, false);
return new RecyclerViewHolder(itemView);
}
@Override
public void onBindViewHolder(@NonNull RecyclerViewHolder holder, int i) {
book = bookList.get(i);
holder.mAuthor.setText(book.getAuthor());
holder.mTitle.setText(book.getTitle());
holder.mCategory.setText(book.getCategory());
holder.setmBookImage(book.getImage(), mContext);
holder.setItemClickListener(itemClickListener);
}
@Override
public int getItemCount() {
return bookList.size();
}
}
还有其他方法可以应用一个用户,一本书规则吗?
将代码更改为
databaseReference = FirebaseDatabase.getInstance().getReference().child(ConstantFields.CHILD_BOOK);
bookRef = databaseReference.child(ConstantFields.CHILD_BOOK);
bookRef.addChildEventListener(...);
我可以成功地将书添加到数据库中的所需位置(我不知道如何),但是不会调用OnChildAdded()或onChildChanged()方法,因此进度条将继续无限显示,并且书不显示
答案 0 :(得分:0)
检查您的数据库参考。
database = FirebaseDatabase.getInstance.getReference
这将检查整个数据库。
您的子事件侦听器应检查database.child(“ books”)
DatabaseReference db = FirebaseDatabase.getInstance.getReference
dbBooks = db.child("books")
dbBooks.addChildEventListener(new ChildEventListener{
}
答案 1 :(得分:0)
我认为JJ Swart的答案是正确的,这里的问题是您对整个数据的BookReference引用,而不仅仅是对“书籍的数据”的引用。您可以向我们显示您的“例外”信息,以查看将“书”的引用更改为您的错误之后的情况。