java - onStart() 方法中的 FirestoreRecyclerAdapter.startListening 在我的 Fragment 中抛出空对象错误
问题描述
当 adapter.startListening() 方法在我的 Fragment 的 onStart() 方法中运行时,FirestoreRecyclerAdapter 会引发空对象错误。
我的 Firestore 数据库
(Desserts, Starters) 是菜单集合的子集合,使用 for 循环动态获取。
MenuFragment.java
public class MenuFragment extends Fragment implements View.OnClickListener {
private View view;
private FirebaseFirestore db;
private FirebaseAuth mAuth;
private FirebaseUser mCurrentUser;
private String Ruid,mItemName,mItemPrice,mItemIsActive,mItemSpecs;
private FloatingActionButton mCreateNewMenuBtn;
private DocumentReference mResMenuCategoryRef, mMenuItemRef;
private ArrayList<String> categoryList;
private FirestoreRecyclerAdapter<MenuItemModel, MenuItemHolder> adapter;
LinearLayoutManager linearLayoutManager;
private RecyclerView mMenuItemRecyclerView;
public MenuFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(@NotNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_menu,container,false);
init();
getMenuItems();
mCreateNewMenuBtn.setOnClickListener(this);
return view;
}
private void init() {
mCreateNewMenuBtn = view.findViewById(R.id.createNewMenuBtn);
mAuth = FirebaseAuth.getInstance();
mCurrentUser = mAuth.getCurrentUser();
assert mCurrentUser != null;
Ruid = mCurrentUser.getUid();
db = FirebaseFirestore.getInstance();
mResMenuCategoryRef = db.collection("RestaurantList").document(Ruid);
mMenuItemRecyclerView = view.findViewById(R.id.menuItemRecyclerView);
linearLayoutManager = new LinearLayoutManager(requireActivity(), LinearLayoutManager.VERTICAL, false);
mMenuItemRecyclerView.setLayoutManager(linearLayoutManager);
}
private void getMenuItems() {
mResMenuCategoryRef.get().addOnCompleteListener(task -> {
if (task.isSuccessful()){
DocumentSnapshot documentSnapshot = task.getResult();
assert documentSnapshot != null;
if (documentSnapshot.exists()){
categoryList = (ArrayList<String>) documentSnapshot.get("Categories");
assert categoryList != null;
Log.d("CATEGORIES", categoryList.toString());
for(int i = 0 ; i < categoryList.size() ; i++){
String MenuItemSubCollection = categoryList.get(i);
CollectionReference menuItemReference = db.collection("Menu").document(Ruid).collection(MenuItemSubCollection);
menuItemReference.get().addOnCompleteListener(task1 -> {
if (task1.isSuccessful()){
for (QueryDocumentSnapshot document : Objects.requireNonNull(task1.getResult())) {
DocumentReference mMenuItemRef = menuItemReference.document(document.getId());
mMenuItemRef.get().addOnCompleteListener(task2 -> {
if (task2.isSuccessful()){
DocumentSnapshot mMenuItemSnapShot = task2.getResult();
assert mMenuItemSnapShot != null;
Query query = db.collection("Menu").document(Ruid).collection(MenuItemSubCollection);
FirestoreRecyclerOptions<MenuItemModel> menuItemModel = new FirestoreRecyclerOptions.Builder<MenuItemModel>()
.setQuery(query, MenuItemModel.class)
.build();
adapter = new FirestoreRecyclerAdapter<MenuItemModel, MenuItemHolder>(menuItemModel) {
@Override
public void onBindViewHolder(MenuItemHolder holder, int position, MenuItemModel model) {
holder.mItemName.setText(model.getName());
Log.d("SHOWING", model.getName());
String specImage = model.getSpecification();
if (specImage.equals("Veg")){
Glide.with(Objects.requireNonNull(requireActivity()))
.load(R.drawable.veg_symbol).into(holder.foodSpecification);
}else {
Glide.with(Objects.requireNonNull(requireActivity()))
.load(R.drawable.non_veg_symbol).into(holder.foodSpecification);
}
holder.mItemPrice.setText(model.getPrice());
holder.itemView.setOnClickListener(v -> {
});
}
@Override
public MenuItemHolder onCreateViewHolder(ViewGroup group, int i) {
View view = LayoutInflater.from(group.getContext())
.inflate(R.layout.menu_item_details, group, false);
return new MenuItemHolder(view);
}
@Override
public void onError(FirebaseFirestoreException e) {
Log.e("error", e.getMessage());
}
};
adapter.notifyDataSetChanged();
mMenuItemRecyclerView.setAdapter(adapter);
}
});
}
}
});
}
}
}
});
}
public class MenuItemHolder extends RecyclerView.ViewHolder {
@BindView(R.id.itemName)
TextView mItemName;
@BindView(R.id.foodMark)
ImageView foodSpecification;
@BindView(R.id.itemPrice)
TextView mItemPrice;
@BindView(R.id.itemActiveSwitch)
Switch isActiveSwitch;
public MenuItemHolder(View itemView) {
super(itemView);
ButterKnife.bind(requireActivity(), itemView);
}
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.createNewMenuBtn:
Fragment fragment = new CreateNewMenuFragment();
FragmentManager fragmentManager = Objects.requireNonNull(getActivity()).getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragmentContainer, fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
break;
}
}
@Override
public void onStart() {
super.onStart();
adapter.startListening();
}
@Override
public void onStop() {
super.onStop();
adapter.stopListening();
}
}
MenuItemModel.java
public class MenuItemModel {
private String name;
private String price;
private String specification;
public MenuItemModel(String name, String price, String specification) {
this.name = name;
this.price = price;
this.specification = specification;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String getSpecification() {
return specification;
}
public void setSpecification(String specification) {
this.specification = specification;
}
}
日志猫
2020-07-09 20:47:57.251 1689-1689/com.example.muncherestaurantpartner E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.muncherestaurantpartner, PID: 1689
java.lang.NullPointerException: Attempt to invoke virtual method 'void com.firebase.ui.firestore.FirestoreRecyclerAdapter.startListening()' on a null object reference
at Fragments.MenuFragment.onStart(MenuFragment.java:205)
at androidx.fragment.app.Fragment.performStart(Fragment.java:2632)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:915)
at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManagerImpl.java:1238)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:1303)
at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:439)
at androidx.fragment.app.FragmentManagerImpl.executeOps(FragmentManagerImpl.java:2079)
at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManagerImpl.java:1869)
at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManagerImpl.java:1824)
at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManagerImpl.java:1727)
at androidx.fragment.app.FragmentManagerImpl$2.run(FragmentManagerImpl.java:150)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:201)
at android.app.ActivityThread.main(ActivityThread.java:6864)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)
解决方案
您正在初始化adapter
内部onCreateView()
,这是片段生命周期中的一个方法,它在之前被调用onStart()
,因此在内部初始化适配器之后getMenuItems()
,您必须调用startListening()
:
adapter.startListening();
adapter.notifyDataSetChanged();
mMenuItemRecyclerView.setAdapter(adapter);
然后在里面onDestroyView()
,你可以调用stopListening()
:
@Override
public void onDestroyView() {
super.onDestroyView();
adapter.stopListening();
}
推荐阅读
- sql - 如何编写查询以选择日期格式为“DD-MMM-YYYY”的数据?
- eclipse - IntelliJ 或 Eclipse 的插件以不同颜色绘制方法参数?
- excel - 文本框将日期转换为数字
- android-fragments - 在 Android Studio 的活动中正确使用 Volley
- java - 在 JPA/Jackson 中使用自定义子对象序列化 @ManyToOne 对象
- android - 如何在 ConstraintLayout 中制作具有最小高度的可拉伸视图?
- python - python中类初始化的最佳实践
- css - 更改 WebView 中滚动条角的颜色
- typescript - react-transition 的样式对象导致“无索引签名”错误
- c# - 类 Object 的 Linq 降序