在RecyclerView.setHasFixedSize上与Firestore的聊天与NullPointerException崩溃

时间:2018-01-12 18:28:08

标签: android firebase google-cloud-firestore firebaseui

我是RecyclerView的新手,所以如果分辨率非常简单,请原谅我。我四处寻找但没有运气,所以我需要指导。 使用FirestoreUI将聊天功能与Firestore相匹配,从https://github.com/firebase/FirebaseUI-Android获取代码。

这是主要代码:

import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
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.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.firebase.ui.auth.util.ui.ImeHelper;
import com.firebase.ui.firestore.FirestoreRecyclerAdapter;
import com.firebase.ui.firestore.FirestoreRecyclerOptions;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.firestore.CollectionReference;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.Query;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

/**
 * Class demonstrating how to setup a {@link RecyclerView} with an adapter while taking sign-in
 * states into consideration. Also demonstrates adding data to a ref and then reading it back using
 * the {@link FirestoreRecyclerAdapter} to build a simple chat app.
 * <p>
 * For a general intro to the RecyclerView, see <a href="https://developer.android.com/training/material/lists-cards.html">Creating
 * Lists</a>.
 */
public class BlaBlaBlaChat extends AppCompatActivity
        implements FirebaseAuth.AuthStateListener {
    private static final String TAG = "BlaBlaBlaChat";

    private static final CollectionReference sChatCollection =
            FirebaseFirestore.getInstance().collection("chats");
    /** Get the last 50 chat messages ordered by timestamp . */
    private static final Query sChatQuery = sChatCollection.orderBy("timestamp").limit(50);

    static {
        FirebaseFirestore.setLoggingEnabled(true);
    }

    @BindView(R.id.messagesList)
    RecyclerView mRecyclerView;

    @BindView(R.id.sendButton)
    Button mSendButton;

    @BindView(R.id.messageEdit)
    EditText mMessageEdit;

    @BindView(R.id.emptyTextView)
    TextView mEmptyListMessage;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.ireland_chat);
        ButterKnife.bind(this);

        mRecyclerView.setHasFixedSize(true);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));

        ImeHelper.setImeOnDoneListener(mMessageEdit, new ImeHelper.DonePressedListener() {
            @Override
            public void onDonePressed() {
                onSendClick();
            }
        });
    }

    @Override
    public void onStart() {
        super.onStart();
        if (isSignedIn()) { attachRecyclerViewAdapter(); }
        FirebaseAuth.getInstance().addAuthStateListener(this);
    }

    @Override
    protected void onStop() {
        super.onStop();
        FirebaseAuth.getInstance().removeAuthStateListener(this);
    }

    @Override
    public void onAuthStateChanged(@NonNull FirebaseAuth auth) {
        mSendButton.setEnabled(isSignedIn());
        mMessageEdit.setEnabled(isSignedIn());

        if (isSignedIn()) {
            attachRecyclerViewAdapter();
        } else {
            Toast.makeText(this, R.string.signing_in, Toast.LENGTH_SHORT).show();
            auth.signInAnonymously().addOnCompleteListener(new BlaBlaBlaChatSignInHolder(this));
        }
    }

    private boolean isSignedIn() {
        return FirebaseAuth.getInstance().getCurrentUser() != null;
    }

    private void attachRecyclerViewAdapter() {
        final RecyclerView.Adapter adapter = newAdapter();

        // Scroll to bottom on new messages
        adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
            @Override
            public void onItemRangeInserted(int positionStart, int itemCount) {
                mRecyclerView.smoothScrollToPosition(adapter.getItemCount());
            }
        });

        mRecyclerView.setAdapter(adapter);
    }

    @OnClick(R.id.sendButton)
    public void onSendClick() {
        String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
        String name = "User " + uid.substring(0, 6);

        onAddMessage(new BlaBlaBlaChatAbstractExtend(name, mMessageEdit.getText().toString(), uid));

        mMessageEdit.setText("");
    }

    protected RecyclerView.Adapter newAdapter() {
        FirestoreRecyclerOptions<BlaBlaBlaChatAbstractExtend> options =
                new FirestoreRecyclerOptions.Builder<BlaBlaBlaChatAbstractExtend>()
                        .setQuery(sChatQuery, BlaBlaBlaChatAbstractExtend.class)
                        .setLifecycleOwner(this)
                        .build();

        return new FirestoreRecyclerAdapter<BlaBlaBlaChatAbstractExtend, BlaBlaBlaChatHolder>(options) {
            @Override
            public BlaBlaBlaChatHolder onCreateViewHolder(ViewGroup parent, int viewType) {
                return new BlaBlaBlaChatHolder(LayoutInflater.from(parent.getContext())
                        .inflate(R.layout.message, parent, false));
            }

            @Override
            protected void onBindViewHolder(@NonNull BlaBlaBlaChatHolder holder, int position, @NonNull BlaBlaBlaChatAbstractExtend model) {
                holder.bind(model);
            }

            @Override
            public void onDataChanged() {
                // If there are no chat messages, show a view that invites the user to add a message.
                mEmptyListMessage.setVisibility(getItemCount() == 0 ? View.VISIBLE : View.GONE);
            }
        };
    }

    protected void onAddMessage(BlaBlaBlaChatAbstractExtend chat) {
        sChatCollection.add(chat).addOnFailureListener(this, new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                Log.e(TAG, "Failed to write message", e);
            }
        });
    }

这是xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.balblabla.BlaBlaBlaChat">

    <TextView
        android:id="@+id/emptyTextView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="16dp"
        android:text="@string/start_chatting" />

    <android.support.v7.widget.RecyclerView
        android:id="@+id/messagesList"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_above="@+id/footer"
        android:clipToPadding="false"
        android:padding="16dp"
        tools:listitem="@layout/ireland_chat_message" />

    <LinearLayout
        android:id="@+id/footer"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentBottom="true"
        android:paddingStart="16dp"
        android:paddingEnd="16dp"
        android:paddingLeft="16dp"
        android:orientation="horizontal">

        <EditText
            android:id="@+id/messageEdit"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:imeOptions="actionDone"
            android:inputType="text" />

        <Button
            android:id="@+id/sendButton"
            style="@style/Widget.AppCompat.Button.Borderless.Colored"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|end"
            android:text="@string/send" />

    </LinearLayout>

</RelativeLayout>

来自logcat:

01-12 18:07:36.443 31599-31599/com.example.carlo.blablabla E/UncaughtException: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.carlo.blablabla/com.example.carlo.blablabla.BlaBlaBlaChat}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.widget.RecyclerView.setHasFixedSize(boolean)' on a null object reference
                                                                                    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2724)
                                                                                    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2789)
                                                                                    at android.app.ActivityThread.-wrap12(ActivityThread.java)
                                                                                    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1527)
                                                                                    at android.os.Handler.dispatchMessage(Handler.java:110)
                                                                                    at android.os.Looper.loop(Looper.java:203)
                                                                                    at android.app.ActivityThread.main(ActivityThread.java:6251)
                                                                                    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)
                                                                                 Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.widget.RecyclerView.setHasFixedSize(boolean)' on a null object reference
                                                                                    at com.example.carlo.blablabla.BlaBlaBlaChat.onCreate(BlaBlaBlaChat.java:73)
                                                                                    at android.app.Activity.performCreate(Activity.java:6681)
                                                                                    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
                                                                                    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2677)
                                                                                    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2789) 
                                                                                    at android.app.ActivityThread.-wrap12(ActivityThread.java) 
                                                                                    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1527) 
                                                                                    at android.os.Handler.dispatchMessage(Handler.java:110) 
                                                                                    at android.os.Looper.loop(Looper.java:203) 
                                                                                    at android.app.ActivityThread.main(ActivityThread.java:6251) 
                                                                                    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) 
01-12 18:07:36.715 31599-31599/com.example.carlo.blablabla E/AndroidRuntime: FATAL EXCEPTION: main
                                                                             Process: com.example.carlo.blablabla, PID: 31599
                                                                             java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.carlo.blablabla/com.example.carlo.blablabla.BlaBlaBlaChat}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.widget.RecyclerView.setHasFixedSize(boolean)' on a null object reference
                                                                                 at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2724)
                                                                                 at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2789)
                                                                                 at android.app.ActivityThread.-wrap12(ActivityThread.java)
                                                                                 at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1527)
                                                                                 at android.os.Handler.dispatchMessage(Handler.java:110)
                                                                                 at android.os.Looper.loop(Looper.java:203)
                                                                                 at android.app.ActivityThread.main(ActivityThread.java:6251)
                                                                                 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)
                                                                              Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.widget.RecyclerView.setHasFixedSize(boolean)' on a null object reference
                                                                                 at com.example.carlo.blablabla.BlaBlaBlaChat.onCreate(BlaBlaBlaChat.java:73)
                                                                                 at android.app.Activity.performCreate(Activity.java:6681)
                                                                                 at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
                                                                                 at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2677)
                                                                                 at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2789) 
                                                                                 at android.app.ActivityThread.-wrap12(ActivityThread.java) 
                                                                                 at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1527) 
                                                                                 at android.os.Handler.dispatchMessage(Handler.java:110) 
                                                                                 at android.os.Looper.loop(Looper.java:203) 
                                                                                 at android.app.ActivityThread.main(ActivityThread.java:6251) 
                                                                                 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) 

Gradle项目

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
        google()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.1'
        classpath 'com.google.gms:google-services:3.1.0'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
        google()
        maven {
            url "https://maven.google.com" // Google's Maven repository
        }
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

Gradle APP:

apply plugin: 'com.android.application'


android {
    compileSdkVersion 27
    buildToolsVersion '26.0.2'
    defaultConfig {
        applicationId "com.example.blablabla.albalbalb"
        minSdkVersion 19
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:27.0.2'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    testCompile 'junit:junit:4.12'
    compile 'com.google.android.gms:play-services-location:11.8.0'
    compile 'com.google.android.gms:play-services-maps:11.8.0'
    compile 'com.google.firebase:firebase-core:11.8.0'
    compile 'com.google.firebase:firebase-auth:11.8.0'
    compile 'com.google.firebase:firebase-firestore:11.8.0'
    compile 'com.google.firebase:firebase-storage:11.8.0'
    implementation 'com.android.support:cardview-v7:27.0.2'
    implementation 'com.android.support:recyclerview-v7:27.0.2'
    compile 'de.hdodenhof:circleimageview:1.3.0'
    compile 'com.google.android.gms:play-services-appinvite:11.8.0'
    compile 'com.google.firebase:firebase-messaging:11.8.0'
    compile 'com.google.android.gms:play-services-ads:11.8.0'
    compile 'com.google.firebase:firebase-appindexing:11.8.0'
    compile 'com.google.firebase:firebase-crash:11.8.0'
    compile 'com.google.firebase:firebase-analytics:11.8.0'
    compile 'com.android.support:design:27.0.2'
    compile 'com.github.bumptech.glide:glide:4.3.1'
    compile 'com.google.firebase:firebase-database:11.8.0'
    compile 'com.google.firebase:firebase-config:11.8.0'
    compile 'com.firebaseui:firebase-ui-database:3.1.3'
    compile 'com.firebaseui:firebase-ui-auth:3.1.3'
    implementation 'com.firebaseui:firebase-ui-firestore:3.1.3'
    implementation 'com.firebaseui:firebase-ui-storage:3.1.3'
    compile 'com.google.android.gms:play-services-auth:11.8.0'
    implementation 'com.jakewharton:butterknife:8.8.1'
    // Testing dependencies

    androidTestCompile 'com.android.support.test:runner:1.0.1'
    androidTestCompile 'com.android.support:support-annotations:27.0.2'

}

apply plugin: 'com.google.gms.google-services'

代码只是来自Github代码的剪切/粘贴,但出了点问题。

2 个答案:

答案 0 :(得分:1)

看起来您没有正确地将ButterKnife库添加到项目中。

在您应用的build.gradle文件中,您必须在implementation "com.jakewharton:butterknife:8.8.1"之后添加annotationProcessor,如下所示: annotationProcessor "com.jakewharton:butterknife-compiler:8.8.1"

在你的项目的build.gradle文件中,将ButterKnife插件添加到你的buildscript中:

dependencies {
        classpath 'com.android.tools.build:gradle:3.0.1'
        classpath 'com.google.gms:google-services:3.1.0'
        classpath 'com.jakewharton:butterknife-gradle-plugin:8.8.1'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }

答案 1 :(得分:0)

您正在使用永远不会初始化的mRecyclerView,这就是您收到该错误的原因。为了解决这个问题,您必须先使用它进行初始化。假设您RecyclerView的ID为recycler_view,请在onCreate()方法中使用以下代码:

RecyclerView mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);