Reputation: 337
I have implemented the MVVM architecture in my app. I have my activity, viewmodel, repository, DAO, and database classes. The database holds objects that contain different lists that I want to switch between and have my RecyclerView show the currently selected list. My understanding is that row IDs in SQLite start at 1, but the insert method in my repository (which calls the @Insert method in my DAO) always starts with a row ID of 0. For testing purposes, I'm using LiveData to get all the objects in the database and when I log their IDs, they properly begin with 1 and go all the way to n. I don't want to maintain a list of all the objects in the database in memory, only the single object that contains the currently selected list. When a user creates a new list (or selects an existing list), I want to have my RecyclerView display its contents and observe any changes to that list. I can't start observing an object without its proper corresponding ID.
How do I propagate the proper ID to MainActivity? If my ViewModel and Activity code are needed please tell me and I will edit the post.
When I log the ID from the Repository
When I log the LiveData in MainActivity the proper IDs show
My Database class
@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;
}
My DAO
@Dao
public interface ListContainerDao {
@Insert
long insertListContainer(ListContainer container);
... // other database queries
}
My Repository
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;
}
}
Upvotes: 0
Views: 1538
Reputation: 5103
You should consider the asynchronity of your code here:
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;
}
If you want to get result of asynchronous operation in Java you can use:
Upvotes: 1