首页 > 解决方案 > Firebase 和 RecyclerView:setter 和 switch 的问题

问题描述

我对 Android 开发还很陌生,我刚刚开始使用该RecyclerView元素。不幸的是,我还没有在 SO 或其他适合我的平台上找到解决方案。

我能够在RecyclerView我的应用程序中实现,但是当我尝试从 Firebase 实时数据库获取数据时,由于出现一些错误,我的应用程序在打开活动后立即停止。我将在下面提供错误。


LOGCAT 错误:

2018-12-06 17:50:54.278 15910-15910/com.myapp.something.app W/ClassMapper: No setter/field for 02 found on class com.maxschabacker.apps.reclamatorium.GetReadyListModel
    2018-12-06 17:50:54.278 15910-15910/com.myapp.something.app W/ClassMapper: No setter/field for 01 found on class com.maxschabacker.apps.reclamatorium.GetReadyListModel
    2018-12-06 17:50:54.279 15910-15910/com.myapp.something.app W/ClassMapper: No setter/field for 03 found on class com.maxschabacker.apps.reclamatorium.GetReadyListModel
    2018-12-06 17:50:54.282 15910-15910/com.myapp.something.app E/AndroidRuntime: FATAL EXCEPTION: main
        Process: com.myapp.something.app, PID: 15910
        java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
            at com.myapp.something.app.GetReadyListViewHolder.setDetails(GetReadyListViewHolder.java:26)
            at com.myapp.something.app.GetReadyListActivity$1.populateViewHolder(GetReadyListActivity.java:49)
            at com.myapp.something.app.GetReadyListActivity$1.populateViewHolder(GetReadyListActivity.java:46)
            at com.firebase.ui.database.FirebaseRecyclerAdapter.onBindViewHolder(FirebaseRecyclerAdapter.java:177)
            at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:6781)
            at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:6823)
            at android.support.v7.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:5752)
            at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6019)
            at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5858)
            at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5854)
            at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2230)
            at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1557)
            at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1517)
            at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:612)
            at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3924)
            at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3641)
            at android.support.v7.widget.RecyclerView.consumePendingUpdateOperations(RecyclerView.java:1888)
            at android.support.v7.widget.RecyclerView$1.run(RecyclerView.java:407)
            at android.view.Choreographer$CallbackRecord.run(Choreographer.java:907)
            at android.view.Choreographer.doCallbacks(Choreographer.java:709)
            at android.view.Choreographer.doFrame(Choreographer.java:641)
            at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:893)
            at android.os.Handler.handleCallback(Handler.java:836)
            at android.os.Handler.dispatchMessage(Handler.java:103)
            at android.os.Looper.loop(Looper.java:203)
            at android.app.ActivityThread.main(ActivityThread.java:6361)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1063)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:924)
    2018-12-06 17:50:54.288 1163-6166/? W/ActivityManager:   Force finishing activity com.myapp.something.app/.GetReadyListActivity



实时数据库:

{
  "tools" : {
    "getready" : {
      "01" : {
        "desc" : "Stage left",
        "status" : false,
        "title" : "Stage 1"
      },
      "02" : {
        "desc" : "Stage right",
        "status" : false,
        "title" : "Stage 2"
      },
      "03" : {
        "desc" : "Backstage",
        "status" : false,
        "title" : "Stage 3"
      }
    }
  }
}

我的安全规则没有问题,因为我可以单独抓取物品。



GetReadyListActivity.java:

public class GetReadyListActivity extends AppCompatActivity {

    private Toolbar mToolbar;

    RecyclerView mRecyclerView;
    FirebaseDatabase mFirebaseDatabase;
    DatabaseReference mDatabaseReference;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_get_ready_list);

        mToolbar = findViewById(R.id.get_ready_list_app_bar_layout);
        setSupportActionBar(mToolbar);
        getSupportActionBar().setTitle("GetReady");
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        mRecyclerView = findViewById(R.id.getReadyListRecyclerView);
        mRecyclerView.setHasFixedSize(true);

        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));

        mFirebaseDatabase = FirebaseDatabase.getInstance();
        mDatabaseReference = mFirebaseDatabase.getReference("tools");
    }

    @Override
    protected void onStart() {
        super.onStart();

        FirebaseRecyclerAdapter<GetReadyListModel, GetReadyListViewHolder> firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<GetReadyListModel, GetReadyListViewHolder>(GetReadyListModel.class, R.layout.recyclerview_get_ready_list_row, GetReadyListViewHolder.class, mDatabaseReference) {
            @Override
            protected void populateViewHolder(GetReadyListViewHolder viewHolder, GetReadyListModel model, int position) {
                viewHolder.setDetails(getApplicationContext(), model.getTitle(), model.getDesc(), model.getStatus());
            }
        };

        mRecyclerView.setAdapter(firebaseRecyclerAdapter);
    }
}



GetReadyListModel.java:

public class GetReadyListModel {
    String title, desc;
    Boolean status;

    public Boolean getStatus() {
        return status;
    }

    public void setStatus(Boolean status) {
        this.status = status;
    }

    public GetReadyListModel() {}

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

}



GetReadyListViewHolder.java:

public class GetReadyListViewHolder extends RecyclerView.ViewHolder {

        View mView;

        public GetReadyListViewHolder(@NonNull View itemView) {
            super(itemView);

            mView = itemView;
        }

        public void setDetails(Context ctx, String title, String desc, Boolean status) {
            TextView mTitle = mView.findViewById(R.id.getReadyListTitle);
            TextView mDesc = mView.findViewById(R.id.getReadyDesc);
            Switch mStatus = mView.findViewById(R.id.getReadyListStatus);

            mTitle.setText(title);
            mDesc.setText(desc);
            mStatus.setChecked(status);

        }
    }



activity_get_ready_list.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".GetReadyListActivity"
    android:orientation="vertical">

    <include layout="@layout/app_bar_layout"
        android:id="@+id/get_ready_list_app_bar_layout"/>

    <android.support.v7.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/getReadyListRecyclerView"/>

</LinearLayout>



recyclerview_get_ready_list_row.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    app:cardBackgroundColor="#fff"
    app:cardCornerRadius="3dp"
    app:cardElevation="3dp"
    app:contentPadding="8dp"
    app:cardUseCompatPadding="true">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:id="@+id/getReadyListTitle"
            android:text="Loading..."
            android:textSize="24sp"
            android:textColor="#000"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

        <TextView
            android:id="@+id/getReadyListDesc"
            android:text="Loading..."
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

        <Switch
            android:id="@+id/getReadyListStatus"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    </LinearLayout>

</android.support.v7.widget.CardView>



我发布了我所有的代码,以使您更容易理解它,从而减少混乱。我希望它有效;-)

我还面临另一个问题,因为我无法将一个项目的开关关联到其相应的数据库子项。必须有某种标识符,但我不知道该怎么做。


先感谢您。
最大限度

标签: javaandroidfirebasefirebase-realtime-databaseandroid-recyclerview

解决方案


您收到以下错误:

java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法“void android.widget.TextView.setText(java.lang.CharSequence)”

因为您调用setText()方法的对象是null并且发生这种情况是因为您还没有为您的持有者创建视图。因此,除了方法之外,还必须实现另populateViewHolder()一种方法:

@NonNull
@Override
public GetReadyListViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_layout, parent, false);
    return new GetReadyListViewHolder(view);
}

推荐阅读