Как получить вставленный идентификатор строки после вставки строки в комнате в основной поток

Я хочу вернуть вставленный идентификатор строки, чтобы использовать его для обновления некоторого значения в той же строке

@Entity(tableName = "course")
public class Course {

    @PrimaryKey(autoGenerate = true)
    private int id;
    private String firebaseId;
}

@Dao
public interface CourseDao {

    @Insert(onConflict = REPLACE)
    long insertCourse(Course course);

    @Query("UPDATE course SET firebaseId = :firebaseId  WHERE id = :id")
     void updateFirebaseId(int id, String firebaseId);


}

проблема в том, что я не могу вернуть идентификатор в основной поток

  public class Repository {
    private static final Object LOCK= new Object();
    private static Repository sInstance;
    private final CourseDao mCourseDao;
    private final AppExecutors mAppExecutors;



    public void insertCourse(final Course course) {
        mAppExecutors.diskIO().execute(new Runnable() {
            @Override
            public void run() {
                mCourseDao.insertCourse(course);
            }
        });
    }
    public void updateCourse(final Course course) {
        mAppExecutors.diskIO().execute(new Runnable() {
            @Override
            public void run() {
                mCourseDao.updateCourse(course);
            }
        });
    }


}

Я пытался использовать liveData, но он не поддерживается при вставке

Error:(34, 20) error: Methods annotated with @Insert can return either void, long, Long, long[], Long[] or List<Long>.

Можно ли вернуть идентификатор курса после завершения вставки без написания отдельного запроса выбора?

1 ответ

LiveData не поддерживается для insert,

Я чувствую, что есть 2 подхода insert работа в фоновом потоке и отправка результата (long) вернуться к деятельности:

  1. С помощью LiveDataМне лично нравится такой подход:

    public class Repository {
    
        private LiveData<Long> insertedId = MutableLiveData()
    
        public void insertCourse(final Course course) {
            mAppExecutors.diskIO().execute(new Runnable() {
                @Override
                public void run() {
                    Long id = mCourseDao.insertCourse(course);
                    insertId.setValue(id);
                }
            });
        }
    }
    
  2. С помощью Rx:

    return Single.fromCallable(() -> mCourseDao.insertCourse(course));
    

    Здесь вы получите Single<Long> который вы можете наблюдать в своем Activity

Замечания: Repository вернусь Long в ViewModel и в вашем ViewModel будет иметь LiveData а также setValue вещи.

Я так сделал на Яве

В среде, где вам нужен идентификатор:

public class MyIdClass {

   ArrayList<Integer> someIds = new ArrayList<>(); //this could be a primitive it doesn't matter

конструктор с репозиторием....{}

   @FunctionalInterface   //desugaring... normal interfaces are ok I guess?
   public interface GetIdFromDao {
       void getId(long id);
   }

   public void insertSomething(
      Something something
   ) {
      someRepository.insertSomething(
         something,
         id -> someIds.add((int)id) //lambda replacement, I think method reference cannot be done because of (int) casting, but if Array is type long it could be done.
      );

   }

}

В абстрактном классе MyDao...: (что-то, что я не могу не подчеркнуть..., работайте с ABSTRACT CLASS DAO, его более гибким)

@Insert(onConflict = OnConflictStrategy.IGNORE)
protected abstract long protectedInsertSomething(Something something);


public void insert(
        Something something,
        MyIdClass.GetIdFromDao getIdFromDao
) {
//get long id with insert method type long
    long newSomethingId = protectedInsertSomething(something);
    getIdFromDao.getId(newSomethingId);
}

Внутри репозитория, если вы используете AsyncTask<X, Y, Z>, вы действительно можете передавать через VarAgrs все, даже прослушиватели, но не забудьте преобразовать их в том порядке, в котором они вставлены, и использовать тип Object или общего предка.

(Something) object[0];
(MyIdClass.GetIdFromDao) object[1];

new InsertAsyncTask<>(dao).execute(
   something, //0
   getIdFromDao  //1
)

Также используйте @SupressWarnings("unchecked"), Ничего не произошло

Теперь, если вы хотите еще большего взаимодействия, вы можете подключить LiveData к слушателю или создать Factory ViewModel... абстрактную factory ViewModel... что было бы интересно. Но я считаю, что у DataBinding есть модель наблюдаемого представления, которую, я думаю, можно использовать (?)... Я действительно не знаю.