【问题标题】:SQLite MVVM return & obtain rowId in ActivitySQLite MVVM在Activity中返回&获取rowId
【发布时间】:2020-02-04 11:06:54
【问题描述】:

我有一个使用 MVVM 构建的应用程序。我让应用程序成功插入 SQLite 数据库。我现在尝试在插入完成后获取数据库中的 rowId,以便可以对该行进行后续活动更新。

我完全理解我们在 DAO 中将 Void 更改为 Long 的部分,但我不知道如何在活动级别实际访问该 long 并将其保存到可以使用 Intent.PUTEXTRA 从活动发送到活动的变量中.下面的代码示例。

表/实体类:

@Entity(tableName = "CbtTable")
public class CbtTable {

@PrimaryKey(autoGenerate = true)
private long cbtId;

存储库类:

public class CbtRepository {

private CbtDao cbtDao;
private LiveData<List<CbtTable>> cbtData;
private FeelingFitDatabase mFeelingFitDatabase;

public CbtRepository(Application application) {
    mFeelingFitDatabase = FeelingFitDatabase.getInstance(application);
    cbtDao = mFeelingFitDatabase.getCbtDao();
    cbtData = cbtDao.getCbtData();
}


public void insertCbt(CbtTable cbtTable){

    new InsertCbtAsyncTask(cbtDao).execute(cbtTable);

}

道

@Dao
public interface CbtDao {

@Insert(onConflict = REPLACE)
public long insertAutoThought(CbtTable cbtTable);

@Query("UPDATE CbtTable SET automaticThought = :automaticThought WHERE cbtId = :cbtId")
void updateAutoThought(long cbtId, String automaticThought);

@Query ("UPDATE CbtTable SET twistedThinking = :twistedThinking WHERE cbtId = :cbtId")
void updateTwistedThinking(long cbtId, int twistedThinking);

ViewModel 类:

public class CbtViewModel extends AndroidViewModel {

private CbtRepository cbtRepository;
private LiveData<List<CbtTable>> cbtData;

public CbtViewModel(@NonNull Application application) {
    super(application);
    cbtRepository = new CbtRepository(application);
    cbtData = cbtRepository.getCbtData();
}

public void insert(CbtTable cbtTable){
    cbtRepository.insertCbt(cbtTable);
}

public void updateTwistedThinking(CbtTable cbtTable){
    cbtRepository.updateTwistedThinking(cbtTable);
}

异步任务类:

public class InsertCbtAsyncTask extends AsyncTask<CbtTable, Void, Void> {

private CbtDao mCbtDao;

public InsertCbtAsyncTask(CbtDao cbtDao){
    mCbtDao = cbtDao;
}


@Override
protected Void doInBackground(CbtTable... cbtTables) {
    mCbtDao.insertAutoThought(cbtTables[0]);
    return null;
}

活动方式:

 private void saveAutomaticThought(){

    CbtTable cbtTable = new CbtTable(userId, automaticThoughtString, twistedThinking, challengeThoughtString, rationalThoughtString, postedWorkout);
    cbtViewModel.insert(cbtTable);
    long cbtId = cbtTable.getCbtId();

    // Sends the user to the WorkoutAutomaticThoughtActivity page
    Intent intent = new Intent(this, WorkoutTwistedThinkingActivity.class);
    intent.putExtra("cbtId", cbtId);

使用 Activity 中的上述代码,cbtId 存储为 0,因此无法正常工作。这是我正在开发的免费心理健康应用程序,旨在帮助人们,因此我越早解决这个问题,我就能越早推出该应用程序。我将非常感谢调试此问题并使其正常工作的任何帮助。

【问题讨论】:

  • 我真的建议你停止使用 AsynTask。如果你使用它,你可以让那个类接收一个回调函数并在 onPostExecute 中调用它。目前,您忽略了 mCbtDao.insertAutoThought 的结果。只需将其存储在 AsynTask 类中的变量中,稍后在 onPostExecute 方法中使用它。
  • 你能帮我写代码吗?我是新手,不知道如何构造onPostExecute方法来获取我需要的信息并在activity/fragment中访问。

标签: java android sqlite mvvm android-room


【解决方案1】:

我不推荐你使用 AsynTask。但是你可以这样做。

让您的 InsertCbtAsyncTask 接受一个回调作为参数,并在它具有插入的 ID 后调用它:

public class InsertCbtAsyncTask extends AsyncTask<CbtTable, Void, Void> {
    private CbtDao mCbtDao;
    private long id;
    private DoWithId callback;

    public InsertCbtAsyncTask(CbtDao cbtDao, DoWithId callback){
        mCbtDao = cbtDao;
        this.callback = callback;
    }

    @Override
    protected Void doInBackground(CbtTable... cbtTables) {
        id = mCbtDao.insertAutoThought(cbtTables[0]);
        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        callback.doWithId(id);
    }

    interface DoWithId {
        public void doWithId(long id);
    }

}

然后,在调用该类时,您可以将回调作为参数传递。例如:

    DoWithId callback = new DoWithId() {
        @Override
        public void doWithId(long id) {
            launchIntentWithId(id)
        }
    };
    new InsertCbtAsyncTask(cbtDao, callback).execute(cbtTable);

launchIntentWithId() 看起来像这样:

public launchIntentWithId(long cbtId) {
    Intent intent = new Intent(this, WorkoutTwistedThinkingActivity.class);
    intent.putExtra("cbtId", cbtId);
    startActivity(Intent);
}

此代码未经测试,可能不完整,但它应该给你一个完整的想法。

【讨论】:

  • 感谢您帮助编写代码。我一直在关注所有这些,直到最后一种方法。 launchIntentWithId 方法。该方法放在哪里?它不能与执行代码一起放置在存储库中,因为它不能将 startActivity 之类的命令识别为它不是活动或片段。存储库只是一个 POJO。
  • 它必须放在可以调用startActivity的地方,就像Activity一样,在saveAutomaticThought()下面。 saveAutomaticThought() 可以调用该 AsynTask。
  • 不,不幸的是,这不起作用,因为方法调用 launchIntentWithId(id) 无法识别,因为该方法位于不同的类/活动中。要调用它,我必须实例化类来调用方法,这意味着任何变量中都没有数据,因为它是新实例化的,所以它只是抛出了很多空指针
  • 只要把方法放在你需要的地方。试着理解其中的逻辑。不要只是复制代码。
  • 我能够在您提供的答案的基础上完成这项工作。非常感谢您的指导。我真的很感激。
猜你喜欢
  • 1970-01-01
  • 2019-10-09
  • 2022-01-08
  • 1970-01-01
  • 2017-11-22
  • 2019-11-11
  • 1970-01-01
  • 1970-01-01
  • 2015-03-20
相关资源
最近更新 更多