Search code examples
androidsqliteandroid-sqliteandroid-roomandroid-mvvm

Troubleshooting sqlite login using room and MVVM


Im trying to switch from an external login set up where the users details are stored in the cloud to a local login using room/sqlite inside the android app.

Need some help getting the code to work with MVVM. It's giving me a null pointer error which I will pinpoint in the code snippets below.

ROOM / DATABASE

public static final String DATABASE_NAME = "feelingFitDatabase";

/**
 * Singleton instance of the database.
 */
private static FeelingFitDatabase instance;

/**
 * Get MoodLogModel Access Object
 * @return
 */
public abstract MoodBeforeDao getMoodBeforeDao();

public abstract CbtDao getCbtDao();

public abstract WorkoutLogsDao getWorkoutLogsDao();

public abstract UsersDao getUsersDao();

/**
 * Creates an instance of the database.
 * @param context
 * @return
 */
public static synchronized FeelingFitDatabase getInstance(Context context) {

    if (instance == null) {
        instance = Room.databaseBuilder(
                context.getApplicationContext(),
                FeelingFitDatabase.class,
                DATABASE_NAME
        ).addMigrations(MIGRATION_20_22)
                //.fallbackToDestructiveMigration()
                .addCallback(roomCallBack)
                .build();

    }
    return instance;
}

private static RoomDatabase.Callback roomCallBack = new RoomDatabase.Callback() {
    @Override
    public void onCreate(@NonNull SupportSQLiteDatabase db) {
        super.onCreate(db);
        new PopulateDatabaseAsyncTask(instance).execute();
    }
};

DAO

 @Query("SELECT * FROM usersTable WHERE userName = :userName AND   password = :password")
 LiveData<UsersTable> verifyUserLogin(String userName, String  password);

REPOSITORY

 public LiveData<UsersTable> verifyUserLogin(){

    return feelingFitDatabase.getUsersDao().verifyUserLogin(userName, password);

}


VIEWMODEL

 public LiveData<UsersTable> verifyUserLogin(String userName, String password){

    return verifyUserLogin;
}

ACTIVITY

//sets onclick listener to the login button.
    btnLogin.setOnClickListener(new View.OnClickListener() {

        /**
         * @param v
         */
        @Override
        public void onClick(View v) {

            // Checks if the username and password is valid.
            if (!validateEmail() | !validatePassword()) {
                return;
            }

            stringEmail = etEmail.getText().toString();
            stringPassword = etPassword.getText().toString();

            usersViewModel.verifyUserLogin(stringEmail, stringPassword).observe(LoginActivity.this, new Observer<UsersTable>() {
                @Override
                public void onChanged(UsersTable usersTable) {

                    if (usersTable.getUserName().equals(stringEmail) && usersTable.getPassword().equals(stringPassword)) {
                        Intent intent = new Intent(LoginActivity.this, MainActivity.class);
                        startActivity(intent);
                    }
                }
            });
        }
    });
}

This line: @Override public void onChanged(UsersTable usersTable)

The UsersTable in the observer method above is showing as null. I'm not really sure if I've taken the right approach to checking the users login details they entered match those in the database? Any advice or help with this would be greatly appreciated.


Solution

  • I solved this issue myself by simply doing a standard read all rows from the database and returning the data as a list to the activity using live data. From there I did a for loop to loop through the list and used an if statement to verify if the username and password matches.

    usersViewModel.verifyUserLogin().observe(LoginActivity.this, new Observer<List<UsersTable>>() {
                    @Override
                    public void onChanged(List<UsersTable> usersTables) {
    
                        for (UsersTable ut: usersTables){
    
                            if (ut.getUserName().equals(stringEmail) && ut.getPassword().equals(stringPassword)) {
                                Intent intent = new Intent(LoginActivity.this, MainActivity.class);
                                startActivity(intent);
                            } else {
    
                                Toast.makeText(LoginActivity.this, "Invalid username or password", Toast.LENGTH_SHORT).show();
                            }
                        }
    
    
                    }
                });