【问题标题】:Create a CardView only if object have a specific value in Firebase仅当对象在 Firebase 中具有特定值时才创建 CardView
【发布时间】:2018-07-15 23:15:53
【问题描述】:

我的 firebase 数据库中有名为 userForm 的对象。 每个 userForm 都有一个名为 isPassedInspection 的实例变量,它在我的 firebase 中设置为 true 或 false。

用户可以将 Form 对象发送到我的 firebase,因此一旦我认为他们发送的表单按照我的标准“已批准”,我就会手动将 isPassedInspection 设置为 true。

我希望我的 RecyclerView 只为 userForm 创建 CardViews,它的 isPassedInspection 为真,否则,不要创建 CardView(返回 null)。

这是我的代码:

    adapter = new FirebaseRecyclerAdapter<userForm, userFormViewHolder>(options) {
    boolean isFormInspected;
    @Override
    public userFormViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        isPassedFormQuery.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                if(!dataSnapshot.exists()){
                    Log.e(TAG,"datasnapshot doesn't exist in db");
                }
                for(DataSnapshot singleSnapshot: dataSnapshot.getChildren()){
                    if(singleSnapshot.exists()){
        //get the boolean variable from firebase for this item, and set it to "isFormInspected" 
         isFormInspected = singleSnapshot.getValue(userForm.class).isPassedInspection();
                    }
                }
            }
            @Override
            public void onCancelled(DatabaseError databaseError) {
            }
        });
            // if form is manually inspected create a CardView for that form, else return null
            if(isFormInspected){
            CardView cv =(CardView)LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.form_card, parent, false);
            Log.e(TAG, "Created a CardView");
            return new userFormViewHolder(cv);
            }
           else{
Log.e(TAG,"Form  is not inspected,so dont create a CardView");
           return null;
           }
    }

即使我确定我的项目 isPassedInspection 是真的,我总是得到我制作的这个日志:

表单没有被检查,所以不要创建 CardView

然后这个错误:

java.lang.NullPointerException:尝试写入字段'int android.support.v7.widget.RecyclerView$ViewHolder.mItemViewType' 空对象引用

有什么建议吗?谢谢!

【问题讨论】:

  • 您正试图在回调之外访问 isFormInspected,所以它总是相同的。您需要在回调中移动代码,因为这样可以保证为 isFormInspected 返回一个值
  • 如果我将代码移动到回调中,即 void onDateChange 方法中,我会收到错误“无法从具有 void 结果类型的方法返回值”,因为我我试图在 void 方法中返回新的 userFormViewHolder(cv)
  • 好的,问题是你不应该在你的适配器内部进行这个 firebase 调用。我建议您应该做的是在您的活动中进行调用,然后将 userForm 列表传递给您的适配器。然后您可以直接从解析的对象访问 isFormInspected,而不是进行调用并等待值。
  • 1.是的,您也将无法访问您的对象,因为您需要首先等待回调,所以最好的方法是一次获取它们。 2 是的,您还可以获取 userForms 列表(您可能需要来自对象的其他信息)并将其传递给适配器,以便您可以访问适配器内部的 isFormInspected。更重要的是,您将网络调用与非常重要的视图渲染分开。
  • 假设您将回调代码添加到您的活动中,并且如果您在回调中添加将列表添加到适配器的代码,则您的列表可以在数据库更新时更新

标签: java android firebase-realtime-database android-recyclerview android-cardview


【解决方案1】:

使用您自己的适配器类。 你可以看到代码。 UserForm.class

public class UserForm {
String name,birthday,hobby;
boolean isPassedInspection;

public UserForm(String name, String birthday, String hobby, boolean isPassedInspection) {
    this.name = name;
    this.birthday = birthday;
    this.hobby = hobby;
    this.isPassedInspection = isPassedInspection;
}

public UserForm() {
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public String getBirthday() {
    return birthday;
}

public void setBirthday(String birthday) {
    this.birthday = birthday;
}

public String getHobby() {
    return hobby;
}

public void setHobby(String hobby) {
    this.hobby = hobby;
}

public boolean isPassedInspection() {
    return isPassedInspection;
}

public void setPassedInspection(boolean passedInspection) {
    isPassedInspection = passedInspection;
}}

// 适配器类

public class FormsAdapter extends RecyclerView.Adapter<FormsViewHolder> {
private ArrayMap<String,UserForm> formsList=new ArrayMap<>();
/*use arrayMap to get from data and key */
public FormsAdapter() {
formsList=new ArrayMap<>();
}

@Override
public FormsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    LayoutInflater inflater = LayoutInflater.from(parent.getContext());
    // inflating card view item
    View v = inflater.inflate(R.layout.form_card, parent, false);
    return new FormsViewHolder(v);
}

@Override
public void onBindViewHolder(FormsViewHolder holder, int position) {
    String itemKey=formsList.keyAt(position);
    UserForm userForm=formsList.get(itemKey);
    // set one forms data
    holder.setFormsData(userForm);
    holder.view.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            // handle click event
        }
    });
}

@Override
public int getItemCount() {
    return formsList.size();
}

public void addAFormItem(String key,UserForm userForm)
{
    if (!formsList.containsKey(key))
    {
        formsList.put(key,userForm);
        notifyItemInserted(formsList.size());
    }
} }

ViewHolder 类

public class FormsViewHolder extends RecyclerView.ViewHolder {

public View view;
public FormsViewHolder(View itemView) {
    super(itemView);
    view=itemView;
}
public void setFormsData(UserForm userForm)
{
    // initialise card views items and set value in them
    TextView userName=(TextView)view.findViewById(R.id.userName);
    userName.setText(userForm.getName());
}}

你的片段

public class FormsListFragment extends Fragment {

private DatabaseReference formsRef;
private FormsAdapter adapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View  view = inflater.inflate(R.layout.fragment_forms_list, container, false);
    /**/
    RecyclerView recyclerView=(RecyclerView)view.findViewById(R.id.recycler_view);
    recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
    adapter=new FormsAdapter();
    recyclerView.setAdapter(adapter);
    formsRef= FirebaseDatabase.getInstance().getReference().child("forms");
    formsRef.addChildEventListener(new ChildEventListener() {
        @Override
        public void onChildAdded(DataSnapshot dataSnapshot, String s) {
            /*add data in adapter one by one if isPassedInspection true*/
            String itemKey=dataSnapshot.getKey();
            UserForm userForm=dataSnapshot.getValue(UserForm.class);
            if (userForm.isPassedInspection())
                adapter.addAFormItem(itemKey,userForm);
        }

        @Override
        public void onChildChanged(DataSnapshot dataSnapshot, String s) {
              /*when something change in data then add in adapter if isPassedInspection true*/
            String itemKey=dataSnapshot.getKey();
            UserForm userForm=dataSnapshot.getValue(UserForm.class);
            if (userForm.isPassedInspection())
                adapter.addAFormItem(itemKey,userForm);
        }

        @Override
        public void onChildRemoved(DataSnapshot dataSnapshot) {

        }

        @Override
        public void onChildMoved(DataSnapshot dataSnapshot, String s) {

        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });
    return view;
}}

【讨论】:

  • 你真的不遗余力地帮助我.. 它就像魅力一样!谢谢!!! @Satish Rajbhar
  • 嘿@Satish Rajbhar,我可以在使用 ArrayMap 插入时对表单进行排序吗?据我了解,它可以更好地管理内存,所以我想使用它;但是我意识到我应该使用 LinkedHashMap 来维持秩序。你怎么看?
  • 您能否分享一下数据库中表单的确切顺序以及您在 recyclerView 中获得的顺序的屏幕截图。如果问题通过使用 LinkedHashMap 得到解决,请继续。
猜你喜欢
  • 2018-12-29
  • 2020-02-27
  • 1970-01-01
  • 2023-02-20
  • 1970-01-01
  • 1970-01-01
  • 2018-04-03
  • 2014-06-18
  • 2018-03-29
相关资源
最近更新 更多