安卓 Room 数据库问题

3
我正在完成一个课堂练习,使用Room Database保存数据,并在ListView中显示信息。
这个应用程序是关于一名球员的。该球员有4个字段(ID、姓名、位置、进球数)。
第一个保存的球员的ID应该是#1,第二个球员的ID应该是#2,以此类推。
用户必须通过EditText字段输入球员的姓名。
然后有三个单选按钮,用户必须选择其中一个以选择他们的位置(守门员、后卫、前锋)。最后,用户必须通过使用EditText字段输入此球员已打入的进球数。
最后,用户必须通过使用EditText字段输入此球员已打入的进球数。
当用户点击“保存”按钮时,之前选择的所有字段都将被清除,并且会显示一个快速的弹窗消息,显示球员的ID号码。
为了查看所有保存的数据,用户必须点击“查看全部”按钮,这将带他们到第二个活动并在下一个活动中显示球员的姓名、位置和进球数。
我不太熟悉Room,所以每当我按“保存”按钮时,我的应用程序就会崩溃。任何帮助都将不胜感激,谢谢!
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 主活动界面的xml文件,可通过上述链接查看。
activity_second.xml: https://www.codepile.net/pile/2vbYzXq3 第二个活动界面的xml文件,可通过上述链接查看。

处理 崩溃 最重要的方面是查看日志以了解崩溃的原因。您应该在问题中包含此信息。请参阅 调试应用,从日志中提取堆栈跟踪,并编辑您的问题以包含该信息。 - MikeT
2个回答

1

看起来你有一些问题:

你需要为Player类的所有成员添加getter。

这些已经被添加(以及setter):

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;
}

核心问题在于尝试从saveData中查找视图返回了null,因此您会收到空指针异常(NPE),因为这些视图不存在于SAVE按钮中。
解决方案是查找视图(即在onCreate方法中使用findViewById)。
还存在数据验证不足的问题。以下版本的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);
        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);
    }
}

此外,PlayerDao.java 已更改,如果玩家名称重复,将不会失败,并且在插入、删除或更新时也将返回有用的值。这是:-
@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();

}

0

首先,在您的Player.java类中为id使用autoGenerate = true会更好:

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

通过这种方式,您不必为玩家分配ID,房间将为您完成这项工作。

至于在保存时应用程序崩溃的问题,您必须检查日志并查看是什么导致应用程序崩溃。更新您的问题,以便用户可以帮助您。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接