简体   繁体   中英

Android Room Database Issues

I'm trying to complete this small in class exercise where we have to save data using Room Database and then display that information in a ListView.

This app is about a player. The player has 4 fields (Id, Name, Position, Number of Goals scored).

  • The ID of the very first player saved should be #1, #2 for the second player and so on.

  • The user must enter the name of the player through the EditText field.

  • There are then three radio buttons of which, the user has to select one in order to choose their position (Goalie, Defence, Forward). Finally, the last field the user must enter the number of goals this player has scored through the use of the EditText field.

  • Finally, the last field the user must enter the number of goals this player has scored through the use of the EditText field.

Once the user clicks the "SAVE" button, all the fields previously selected will be cleared and their will be a quick toast message displaying the ID# of the player.

In order to view all the saved data the user must click the "VIEW ALL" button which will take them to the second activity and display the Name of the Player, Position, Number of Goals scored in the next activity.

I'm not too familiar with room so whenever I press the "Save"Save button my app crashes. Any help would be greatly appreciated, Thanks!

MainActivity.Java

public class MainActivity extends AppCompatActivity {

private EditText playerEdt, goalsEdt;
private int id = 0;

private RadioGroup groupRad;
private RadioButton radioButton;

private MyDatabase myDb;

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

    playerEdt = findViewById(R.id.edtPlayer);
    goalsEdt = findViewById(R.id.edtGoals);

    myDb = MyDatabase.getInstance(MainActivity.this);


}

public void saveData(View view) {
    id++;
    String name = playerEdt.getText().toString();

    groupRad = findViewById(R.id.radGroup);

    int selectedId = groupRad.getCheckedRadioButtonId();

    radioButton  = findViewById(selectedId);

    String position = radioButton.getText().toString();

    String goalsString = goalsEdt.getText().toString();

    int goals = Integer.valueOf(goalsString);

    Player player = new Player(id, name, position, goals);

    myDb.playerDao().insert(player);

    playerEdt.setText("");
    goalsEdt.setText("");
    groupRad.clearCheck();



}

public void viewData(View view) {
    Intent intent = new Intent(MainActivity.this, SecondActivity.class);

    startActivity(intent);
}
}

SecondActivity.Java

public class SecondActivity extends AppCompatActivity {

ListView listView;
MyDatabase database;

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

    listView = findViewById(R.id.listView);

    database = MyDatabase.getInstance(SecondActivity.this);

    List<Player> players = database.playerDao().getAll();

    ArrayAdapter adapter = new ArrayAdapter(SecondActivity.this, android.R.layout.simple_list_item_1, players);

    listView.setAdapter(adapter);
}
}

Player.Java

@Entity
public class Player {
@PrimaryKey
private int id;

@ColumnInfo(name = "player_name")
private String name;

@ColumnInfo(name = "player_position")
private String position;

@ColumnInfo(name = "player_goals")
private int goals;

public Player(int id, String name, String position, int goals) {
    this.id = id;
    this.name = name;
    this.position = position;
    this.goals = goals;
}

public int getId() {
    return id;
}

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

public String getName() {
    return name;
}

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

public String getPosition() {
    return position;
}

public void setPosition(String position) {
    this.position = position;
}

public int getGoals() {
    return goals;
}

public void setGoals(int goals) {
    this.goals = goals;
}
}

PlayerDao.java

@Dao
public abstract class  PlayerDao {
@Insert
public abstract void insert (Player player);

@Delete
public abstract void delete (Player player);

@Update
public abstract void update (Player player);


@Query("select * from Player")
public abstract List<Player> getAll();


}

MyDatabase.Java

@Database(entities = Player.class, version = 1)
public abstract class MyDatabase extends RoomDatabase {

public abstract PlayerDao playerDao();

private static MyDatabase instance;

public  static MyDatabase getInstance(Context context){

    if( instance == null){
        instance = Room.databaseBuilder(context, MyDatabase.class, "PlayerDb")
                .allowMainThreadQueries()
                .build();

    }

    return instance;
}
}

activity_main.xml: https://www.codepile.net/pile/d5rq8mx2

activity_second.xml: https://www.codepile.net/pile/2vbYzXq3

It would appear that you have a number of issues:-

You need to have getters for all the members of the Player class.

These were added (and setters):-

public int getGoals() {
    return goals;
}

public void setGoals(int goals) {
    this.goals = goals;
}

public String getPosition() {
    return position;
}

public void setPosition(String position) {
    this.position = position;
}

The core issue is that the attemps to find the views in the saveData is returning nulls and hence you are getting a null pointer exception (NPE) because the views don't exist within the SAVE button.

The solution is to find the views (ie use findViewById in the onCreate method).

There is also a lack of data verification which will causes issue. The following version of MainActivity.java handles the issues:-

public class MainActivity extends AppCompatActivity {

    private EditText playerEdt, goalsEdt;
    private int id = 0;

    private RadioGroup groupRad;
    private RadioButton radioButton;
    private MyDatabase myDb;

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

        playerEdt = findViewById(R.id.edtPlayer);
        goalsEdt = findViewById(R.id.edtGoals);
        groupRad = findViewById(R.id.radGroup);
        myDb = MyDatabase.getInstance(MainActivity.this);
    }

    public void saveData(View view) {
        id++;
        String name = playerEdt.getText().toString();
        if (name.length() < 1) {
            Toast.makeText(view.getContext(),"Player Name is blank. Try again.",Toast.LENGTH_SHORT).show();
            playerEdt.requestFocus();
        }
        radioButton = findViewById(groupRad.getCheckedRadioButtonId());
        if (radioButton == null) {
            Toast.makeText(view.getContext(),"You must select Goalie Defence or Forward. Try again",Toast.LENGTH_SHORT).show();
            return;
        }
        String position = radioButton.getText().toString();

        String goalsString = goalsEdt.getText().toString();
        int goals = 0;
        try {
            goals = Integer.valueOf(goalsString);
        } catch (Exception e) {
            Toast.makeText(view.getContext(),"You must give the number of Goals. try again.",Toast.LENGTH_SHORT).show();
            goalsEdt.requestFocus();
        }

        Player player = new Player(id, name, position, goals);
        if (myDb.playerDao().insert(player) < 1) {
            Toast.makeText(view.getContext(),"Player not Added (duplicate)",Toast.LENGTH_SHORT).show();
            return;
        }
        playerEdt.setText("");
        goalsEdt.setText("");
        groupRad.clearCheck();
        Toast.makeText(view.getContext(),"Player Added. Name is " + name + " Position is " + position + " Goals = " + goals,Toast.LENGTH_SHORT).show();
    }

    public void viewData(View view) {
        Intent intent = new Intent(MainActivity.this, SecondActivity.class);
        startActivity(intent);
    }
}

Additionally PlayerDao.java has been changed to not fail if the player name is duplicated and to also return useful values when inserting, deleting or updating. it is:-

@Dao
public abstract class  PlayerDao {
    @Insert(onConflict = OnConflictStrategy.IGNORE)
    public abstract long insert (Player player);

    @Delete
    public abstract int delete (Player player);

    @Update
    public abstract int update (Player player);


    @Query("select * from Player")
    public abstract List<Player> getAll();

}

First of all, it would be better if you use autoGenerate = true in your Player.java class for id :

@Entity
public class Player {
@PrimaryKey(autoGenerate = true)
private int id;  

By doing this you don't have to give your players ids and Room does the job for you.

And for the app crash when saving, you must check the log and see what is causing the app to crash. Update your question with that so users can help you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM