首页 > 解决方案 > 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)

标签: javaandroidfirebaseandroid-recyclerviewgoogle-cloud-firestore

解决方案


您正在初始化adapter内部onCreateView(),这是片段生命周期中的一个方法,它在之前被调用onStart(),因此在内部初始化适配器之后getMenuItems(),您必须调用startListening()

adapter.startListening();
adapter.notifyDataSetChanged();
mMenuItemRecyclerView.setAdapter(adapter);

然后在里面onDestroyView(),你可以调用stopListening()

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        adapter.stopListening();
    }

推荐阅读