Java 从 Room 数据库查询用户时出现 NullPointerException

Java NullPointerException when querying user from Room database

我正在尝试处理登录
我的 android 项目

中有这个实体
@Entity(tableName = "users")
public class UserEntity {
    @PrimaryKey(autoGenerate = true)
    private int id;
    private String username;
    private String password;
    private String email;
}

在userDao中

@Query("SELECT * FROM users WHERE username= :usr AND password= :pwd LIMIT 1")
LiveData < UserEntity > getuserLogin(String usr, String pwd);

我正在使用 MVVM 架构。
在我的主视图中,我添加了一个空的 UserEntity 用户,并使用方法 LiveData<UserEntity> getuserLogin(String usr,String pwd) 观察视图模型中的 LiveData,我在主视图中设置了一个空用户,并在每次用户单击按钮时将其与输入进行比较.

但是每次我得到 NullPointerException。

这是代码:
用户实体

import androidx.room.Entity;
import androidx.room.Ignore;
import androidx.room.PrimaryKey;

import java.util.Date;

@Entity(tableName = "users")
public class UserEntity {
    @PrimaryKey(autoGenerate = true)
    private int id;
    private String username;
    private String password;
    private String email;

    public UserEntity(int id, String username, String password, String email) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.email = email;
    }
    @Ignore
    public UserEntity(String username, String password, String email) {
        this.username = username;
        this.password = password;
        this.email = email;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

UserDao

import androidx.lifecycle.LiveData;
import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Query;
import androidx.room.Update;

import java.util.List;

@Dao
public interface UserDao {
    @Query("SELECT * FROM users")
    LiveData < List < UserEntity >> getAll();
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    void insertUser(UserEntity userEntity);
    @Update(onConflict = OnConflictStrategy.REPLACE)
    void updateUser(UserEntity userEntity);
    @Delete
    void deleteUser(UserEntity userEntity);
    @Query("DELETE FROM users")
    void deleteAll();
    @Query("SELECT * FROM users WHERE username= :usr AND password= :pwd LIMIT 1")
    LiveData < UserEntity > getuserLogin(String usr, String pwd);
}

用户资料库

import android.app.Application;
import android.os.AsyncTask;

import androidx.lifecycle.LiveData;

import java.util.List;

public class UserRepositery {
    private UserDao userDao;
    private LiveData < List < UserEntity >> allusers;

    public UserRepositery(Application application) {
        AppDatabase database = AppDatabase.getsInstance(application);

        this.userDao = database.userDao();
        this.allusers = userDao.getAll();
    }

    public void insert(UserEntity userEntity) {
        new insertUserAsyncTask(userDao).execute(userEntity);
    }

    public void update(UserEntity userEntity) {
        new updateUserAsyncTask(userDao).execute(userEntity);
    }

    public void deleteUser(UserEntity userEntity) {
        new deleteUserAsyncTask(userDao).execute(userEntity);
    }

    public void deleteAllUsers() {
        new deleteAllUserAsyncTask(userDao).execute();
    }

    public LiveData < List < UserEntity >> getAllusers() {
        return allusers;
    }
    LiveData < UserEntity > getuserLogin(String usr, String pwd) {
        return userDao.getuserLogin(usr, pwd);
    }

    public static class insertUserAsyncTask extends AsyncTask < UserEntity, Void, Void > {
        private UserDao userDao;

        public insertUserAsyncTask(UserDao userDao) {
            this.userDao = userDao;
        }

        @Override
        protected Void doInBackground(UserEntity...userEntities) {
            userDao.insertUser(userEntities[0]);

            return null;
        }

    }

    public static class updateUserAsyncTask extends AsyncTask < UserEntity, Void, Void > {
        private UserDao userDao;

        public updateUserAsyncTask(UserDao userDao) {
            this.userDao = userDao;
        }

        @Override
        protected Void doInBackground(UserEntity...userEntities) {
            userDao.updateUser(userEntities[0]);

            return null;
        }

    }

    public static class deleteUserAsyncTask extends AsyncTask < UserEntity, Void, Void > {
        private UserDao userDao;

        public deleteUserAsyncTask(UserDao userDao) {
            this.userDao = userDao;
        }

        @Override
        protected Void doInBackground(UserEntity...userEntities) {
            userDao.deleteUser(userEntities[0]);

            return null;
        }

    }

    public static class deleteAllUserAsyncTask extends AsyncTask < UserEntity, Void, Void > {
        private UserDao userDao;

        public deleteAllUserAsyncTask(UserDao userDao) {
            this.userDao = userDao;
        }

        @Override
        protected Void doInBackground(UserEntity...userEntities) {
            userDao.deleteAll();

            return null;
        }

    }
}

UserViewModel

import android.app.Application;

import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.ViewModel;

import java.util.List;

public class UserViewModel extends AndroidViewModel {
    private UserRepositery repositery;
    private LiveData < List < UserEntity >> allusers;


    public UserViewModel(@NonNull Application application) {
        super(application);
        this.repositery = new UserRepositery(application);
        this.allusers = repositery.getAllusers();
    }
    public void insert(UserEntity userEntity) {
        repositery.insert(userEntity);

    }
    LiveData < UserEntity > getuserLogin(String usr, String pwd) {
        return repositery.getuserLogin(usr, pwd);
    }
    public void update(UserEntity userEntity) {
        repositery.update(userEntity);
    }
    public void delete(UserEntity userEntity) {
        repositery.deleteUser(userEntity);
    }
    public void deleteAll() {
        repositery.getAllusers();
    }

    public LiveData < List < UserEntity >> getAllusers() {
        return allusers;
    }
}

MainActivity

import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelProviders;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import java.util.Date;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    Button login;
    Button register;
    EditText usinp;
    EditText passinp;
    UserViewModel viewModel;
    UserEntity user;
    List < UserEntity > allo;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        usinp = (EditText) findViewById(R.id.user_inp);
        passinp = (EditText) findViewById(R.id.pass_inp);
        login = (Button) findViewById(R.id.login_but);

        register = (Button) findViewById(R.id.register_but);
        viewModel = ViewModelProviders.of(this).get(UserViewModel.class);
        //initializing an input to try something
        String username = "user";
        String password = "user";
        viewModel.getuserLogin(username, password).observe(this, new Observer < UserEntity > () {
            @Override
            public void onChanged(UserEntity userEntity) {
                user.setUsername(userEntity.getUsername());
                user.setEmail(userEntity.getEmail());
                user.setPassword(userEntity.getPassword());
            }
        });
        login.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //Comparing the inputs with user object and oppening other activity
            }
        });
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    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=".MainActivity">
    <TextView
            android:id="@+id/textView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello Please Sign in"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:textSize="32sp"
            android:textStyle="bold"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintHorizontal_bias="0.496"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.023" />
    <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="69dp"
            android:text="TextView"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="@+id/textView2"
            app:layout_constraintTop_toBottomOf="@+id/textView2"
            app:layout_constraintVertical_bias="0.0" />
    <EditText
            android:id="@+id/user_inp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="9dp"
            android:ems="10"
            android:inputType="textPersonName"
            android:text="aw"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.0"
            app:layout_constraintStart_toStartOf="@+id/textView"
            app:layout_constraintTop_toBottomOf="@+id/textView"
            app:layout_constraintVertical_bias="0.0" />
    <TextView
            android:id="@+id/textView3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="220dp"
            android:text="TextView"
    
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.186"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/textView2"
            app:layout_constraintVertical_bias="0.0" />
    <EditText
            android:id="@+id/pass_inp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="12dp"
            android:ems="10"
            android:inputType="textPassword"
            android:text="aw"
            app:layout_constraintStart_toStartOf="@+id/textView3"
            app:layout_constraintTop_toBottomOf="@+id/textView3" />
    <Button
            android:id="@+id/login_but"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="68dp"
            android:text="Log in"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.383"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/pass_inp"
            app:layout_constraintVertical_bias="0.33" />
    <Button
            android:id="@+id/register_but"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Register"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="@+id/login_but"
            app:layout_constraintHorizontal_bias="0.0"
            app:layout_constraintStart_toStartOf="@+id/login_but"
            app:layout_constraintTop_toBottomOf="@+id/login_but"
            app:layout_constraintVertical_bias="0.355" />
</androidx.constraintlayout.widget.ConstraintLayout>

堆栈跟踪

09-09 17:34:22.866 6085-6085/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example2.databse, PID: 6085
java.lang.NullPointerException
    at com.example2.databse.MainActivity.onChanged(MainActivity.java:46)
    at com.example2.databse.MainActivity.onChanged(MainActivity.java:43)
    at androidx.lifecycle.LiveData.considerNotify(LiveData.java:131)
    at androidx.lifecycle.LiveData.dispatchingValue(LiveData.java:149)
    at androidx.lifecycle.LiveData.setValue(LiveData.java:307)
    at androidx.lifecycle.LiveData.run(LiveData.java:91)
    at android.os.Handler.handleCallback(Handler.java:733)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:136)
    at android.app.ActivityThread.main(ActivityThread.java:5426)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:515)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1268)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1084)
    at dalvik.system.NativeStart.main(Native Method)

当然是空指针,因为这个class:

@Entity(tableName = "users")
public class UserEntity {
    @PrimaryKey(autoGenerate = true)
    private int id;
    private String username;
    private String password;
    private String email;

您必须这样编辑:

 @Entity(tableName = "users")
 public class UserEntity {
    @ColumnInfo(name = "id")
    @PrimaryKey(autoGenerate = true)
    private int id;
    @ColumnInfo(name = "username")
    private String username;
    @ColumnInfo(name = "password")
    private String password;
    @ColumnInfo(name = "email")
    private String email;

您可以按照 Google 的教程进行操作:https://codelabs.developers.google.com/codelabs/android-room-with-a-view-kotlin/#0