当前位置: 首页 > 知识库问答 >
问题:

Room数据库:创建新的RecyclerView项后获得两次SELECT MAX()

娄丁雨
2023-03-14

我在Dao中设置了一个@Query来获取MAX(cardId):

Dao
...
@Query("SELECT MAX(cardId) FROM cards")
LiveData<Integer> getMax();

@Insert
void insertCard(Card card);

问题是有两个烤面包机正在烧制。第一个Toast返回先前创建的CardView编号,然后第二个Toast启动并显示刚刚添加的最新CardView编号。例如,Toast将显示CardView编号33,然后第二个Toast将显示刚刚创建的预期CardView编号34(我确认CardViews 33和34都在数据库中,并且是两个最高的项,使用DB Browser For SQLite software)。

AddorUpdateCardActivity
...
private int newMax = -1;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mViewModel = new ViewModelProvider(this).get(cardViewModel.class);        
}

public void onClickSave(View v) {

    // set card data
    // then insert data in database
    mViewModel.insertCard(card1);     

    mViewModel.getMax().observe(this, value -> { newMax = value; Toast.makeText(AddorUpdateCardActivity.this, "card #" + newMax + " was saved to the list", Toast.LENGTH_LONG).show();});
}

ViewModel
...

public cardViewModel(Application application) {
    super(application);
    repository = new cardRepository(application);
    getMax = repository.getMax();
}

public LiveData<Integer> getMax() {
    return getMax;
}

public void insertCard(Card card) {
    repository.insertCard(card);
}

cardRepository

private CardDao cardDao;
private LiveData<Integer> getMax;


public cardRepository(Application application) {
    RoomDatabase db = RoomDatabase.getDatabase(application);
    cardDao = db.cardDao();
}

public LiveData<Integer> getMax() {
    return cardDao.getMax;  
}

public void insertCard(Quickcard newcard) {
    AsyncTask.execute(() -> cardDao.insertCard(newcard));

} 

我错过了什么?如果卡正确地插入到数据库中,那么为什么ViewModel观察者不返回这个新的CardView号而不是两个toast?

public class SQLiteDB extends SQLiteOpenHelper {

    ...
    public int getLastInsertId() {

    int index = 0;
    SQLiteDatabase sdb = getReadableDatabase();
    Cursor cursor = sdb.query(
            "sqlite_sequence",
            new String[]{"seq"},
            "name = ?",
            new String[]{TABLE_NAME},
            null,
            null,
            null,
            null
    );

    sdb.beginTransaction();
    try {
        if (cursor !=null) { 
            if (cursor.moveToLast()) {                    
                index = cursor.getInt(cursor.getColumnIndex("seq"));
            }
        }
    ...
    }         
    return index;
}      

共有1个答案

颛孙建业
2023-03-14

onclicksave中调用的视图模型操作是异步的:

public void onClickSave(View v) {
    mViewModel.insertCard(card1);
    mViewModel.getMax().observe(this, value -> { newMax = value; makeText(AddorUpdateCardActivity.this, "TEXT", .LENGTH_LONG).show();});
}

LiveData的实现记录了数据版本以及观察者看到的最后一个版本。

因此,insertcard开始在工作线程上操作,同时您开始使用新创建的观察器从主线程观察getmax。因此,您将收到当前值以及更新数据库后的新值。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mViewModel = new ViewModelProvider(this).get(cardViewModel.class);
    mViewModel.getMax().observe(this, value -> { newMax = value; makeText(AddorUpdateCardActivity.this, "TEXT", .LENGTH_LONG).show();});
}

public void onClickSave(View v) {
    mViewModel.insertCard(card1);
}
 类似资料:
  • 我试图解决一个问题,但没有成功。每当数据库(数据库室)中特定模型的记录发生变化时,我想更新我的回收器视图。我使用ViewModel来处理模型数据,记录列表存储在LiveData中。 数据库 模型 刀 视图模型 碎片 现在,我的问题是为什么观察者只被调用一次(在片段的开始),然后没有被再次调用?我如何让观察者不断地倾听数据库中的变化(插入,更新,删除),以便我的回收器视图可以立即更新?非常感谢任何建

  • 我正在从ListView迁移到RecyclerView,但是在SQLite中输入一些数据之后,我的列表没有使用notifyDataSetChanged()更新;所以我总是必须调用setAdapter()方法; 回收器ViewAdapter 观赏者 模型

  • 接下来要在本地新建数据库,创建一个名称为「tutorial」的空目录,并把它放在Git管理之下。 下面将以这个目录进行教程讲解。 Windows 首先在任意一个地方创建tutorial目录。若要把tutorial目录放在Git的管理之下,请右击后从菜单中选择「Git 在这里创建版本库」。 接着会显示以下画面。不要勾选‘制作纯版本库’,请直接点击’确定‘。 若创建数据库成功,将显示以下画面。请点击‘

  • 我尝试在D3中创建一个简单的条形图,从数据库中获取数据。其想法是使用参数和国家的选择按钮从数据库中提取年份和值,并以简单条形图的形式显示。我有两个选择按钮和一个提交按钮。代码如下: Foodfiner和Waterfiner是数据库中名为“气候”的表的名称。NPL和IND是国家代码。我的PHP代码(data.php)是这样的: 我的问题是那个折线图。html在使用选择表单之前工作得很好,但这一次,它

  • 问题内容: 我正在使用Java 2 ee开发Web应用程序。我也使用hibernate和MySQL。为了还原备份文件,在我的应用程序中的某个点上,我需要删除当前数据库并重新创建它,我按如下操作: 删除并重新创建后,我需要使用默认用户(Spring Security用户)初始化数据库 但在最后一行应用程序抛出此异常 我知道hibernate在启动时会创建表,但是在这种情况下,它在drop / rec

  • 问题内容: 作为MySQL的新手,我已经安装了最新版本的MySQL Workbench(5.2.33)。我想知道如何使用此应用程序创建数据库。在SQL编辑器的“概述”选项卡中,几乎没有显示“ MySQL模式”,这些模式是现有数据库吗? 问题答案: 启动MySQL Workbench。 在欢迎窗口的左窗格中,在“打开连接以开始查询”下选择要连接的数据库。 查询窗口将打开。在其左窗格上,有一个标题为“