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

Android Room database@Insert方法返回从0开始的行id

彭涵衍
2023-03-14

我已经在我的应用程序中实现了MVVM架构。我有我的活动、视图模型、存储库、DAO和数据库类。数据库保存包含不同列表的对象,我想在这些列表之间切换,并让我的RecycraView显示当前选定的列表。我的理解是SQLite中的行ID从1开始,但是我的存储库中的插入方法(在我的DAO中调用@插入方法)总是从0开始。出于测试目的,我使用LiveData获取数据库中的所有对象,当我记录它们的ID时,它们正确地从1开始,一直到n。我不想在内存中维护数据库中所有对象的列表,只维护包含当前选定列表的单个对象。当用户创建一个新列表(或选择一个现有列表)时,我希望我的回收站视图显示其内容,并观察该列表的任何更改。没有相应的ID,我无法开始观察对象。

如何将正确的ID传播到MainActivity?如果需要我的ViewModel和活动代码,请告诉我,我将编辑此帖子。

当我从存储库中记录ID时

当我在MainActivity中记录LiveData时,会显示正确的ID

我的数据库类

@TypeConverters({ArrayListConverter.class}) // List converter for database
@Database(entities = ListContainer.class, version = 1, exportSchema = false)
public abstract class ListContainerDatabase extends RoomDatabase {

  private static ListContainerDatabase dbInstance;
  private static final String DB_NAME = "list_container_db";
  private static final int NUM_THREADS = 4;

  final static ExecutorService executor = Executors.newFixedThreadPool(NUM_THREADS);

  public abstract ListContainerDao getDao();

  public static synchronized ListContainerDatabase getInstance(Context context) {
    if(dbInstance == null) {
      dbInstance = Room.databaseBuilder(
              context.getApplicationContext(),
              ListContainerDatabase.class, DB_NAME)
              .fallbackToDestructiveMigration()
              .build();
    }
    return dbInstance;
  }

  public static Executor getExecutor() {
    return executor;
}

我的DAO

@Dao
public interface ListContainerDao {

  @Insert
  long insertListContainer(ListContainer container);

... // other database queries

}

我的资源库

public class Repository {

  private static final String TAG = "Repository";

  private ListContainerDao listContainerDao;
  private long id;

  private Executor executor = ListContainerDatabase.getExecutor();

  public Repository(Application application) {
    ListContainerDatabase containerDb = ListContainerDatabase.getInstance(application);
    listContainerDao = containerDb.getDao();
  }

  public long insertListContainer(ListContainer container) {
    executor.execute(new Runnable() {
      @Override
      public void run() {
        id = listContainerDao.insertListContainer(container);  // this returns ID starting at 0
      }
    });
    Log.i(TAG, "insertListContainer: from Repository id is :" + id);
    return id;
  }
}

共有1个答案

阎慈
2023-03-14

您应该在这里考虑代码的异步性:

private long id;

public long insertListContainer(ListContainer container) {
    // Timestamp #1. This started, first time id is not initialised, equals to 0
    executor.execute(new Runnable() { 
    @Override
      public void run() {
        id = listContainerDao.insertListContainer(container);  
        // Timestamp #3. This returns you id = 1, but with some delay, so this value changed id and will be returned only next time you call the method 
      }
    });
    // Timestamp #2. Main thread isn't blocked, so it doesn't wait for runnable to be executed as well and returns first time id = 0, next time - changed value - 1, and so on
    Log.i(TAG, "insertListContainer: from Repository id is :" + id); 
    return id;
  }

如果你想在Java得到异步操作的结果,你可以使用:

  • 回调(类似于此答案)
  • RxJava/CompletableFuture
 类似资料:
  • 问题内容: 在阅读了大量的主题,教程和其他内容之后-我想在这里发布信息,希望有人能为我提供帮助。我尝试了所有可能得到的建议,但仍然没有用。 这是我的代码: 我总是得到“ c-> 0”……但是已经有输出了……所以我在做什么错呢?:/ 问题答案: 您需要在访问属性之前调用该方法。 来自对PHP手册文档的评论: 如果不使用,并在执行准备好的语句后立即调用此函数,则该函数通常将返回0,因为它无法知道结果集

  • 问题内容: 我试图计算一个字符串中有多少个匹配模式。我是使用java.util.regex的新手,我正计划使用matcher.groupCount()来获取匹配组的数量。由于根据文档,它返回捕获组的数量。 返回此匹配器模式中的捕获组数。 零组按照惯例表示整个模式。它不包括在此计数中。 保证小于或等于此方法返回的值的任何非负整数都是该匹配器的有效组索引。 这是我的问题的简化示例: 输出为0。我误解了

  • 问题内容: 现在在phpMyAdmin中工作: 表结构: 该表当前有4行数据,具有不同的OrderID。 SQL: 结果: 我期待第四行-只是一个数字,但是phpMyAdmin中的每一行都有一个0。 问题答案: 返回最后插入的行的ID,并且未绑定到任何表。因此,如果您创建一个新行: 它将返回最后一个id(新主键具有的任何值)。 有关详细信息,请查看 手册 : LAST_INSERT_ID()(不带

  • 问题内容: 这段代码在PHP 5.2.5中始终以微秒返回0: 输出: 有任何想法吗? 问题答案: 这似乎可行,尽管http://us.php.net/date记录微秒说明符似乎并不合逻辑,但实际上并不支持它:

  • 问题内容: 我正在尝试从存储过程中获取返回值,但它始终返回0。 C#代码 SP 在所有情况下,它都返回0。我不知道问题所在。 问题答案: 我尝试了类似您的代码,并且可以按预期工作。 但是,您的代码中两次调用ExecuteNonQuery。 首次调用时,将按预期插入记录,然后为返回值添加参数并再次执行命令。但是现在记录已存在,并且存储过程始终落在else块中,因此始终返回零。

  • 我知道(-0==0)是真的。我很想知道为什么-0 当我在stackoverflow执行上下文中运行这段代码时,它返回。 但是当我在浏览器控制台中运行相同的代码时,它返回。那是为什么呢?我试图在谷歌上搜索它,但没有找到任何有用的东西。这个问题可能不会给某个人的实际例子增加价值,我想了解JS是如何计算它的。