【问题标题】:Return an autogenerated id from Room using AsyncTask and onPostExecute using MVVM使用 AsyncTask 从 Room 中返回自动生成的 id,使用 MVVM 返回 onPostExecute
【发布时间】:2020-01-22 15:16:12
【问题描述】:

我正在尝试从 Room 数据库中获取自动生成的 id,但我正在努力解决如何在所有层中使用 MVVM 来实现。我是 Android 编程新手。我相信 onPostExecute 是关键,但不知道如何将 id 返回到 UI。

我有这门课:

@Entity
public class Scenario {

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

    public Scenario(String name) {this.name = name;}

    public void setId(@NonNull int id) {this.id = id;}
    @NonNull
    public int getId() {return id;}
    public String getName() {return name;}
}

还有这个DAO(只显示插入相关代码):

@Dao
public interface ScenarioDao {

    @Insert
    Long insert(Scenario scenario);

}

使用此存储库(仅显示插入相关代码):

public class ScenarioRepository {

    private ScenarioDao scenarioDao;
    private LiveData<List<Scenario>> allScenarios;


    public ScenarioRepository(Application application) {

        AppDatabase database = AppDatabase.getInstance(application);
        scenarioDao = database.scenarioDao();
        allScenarios = scenarioDao.getAllScenarios();
    }


    public void insert (Scenario scenario) {
        new InsertScenarioAsyncTask(scenarioDao).execute(scenario);
    }

    private static class InsertScenarioAsyncTask extends AsyncTask<Scenario, Void, Long> {
        private ScenarioDao scenarioDao;

        private InsertScenarioAsyncTask (ScenarioDao scenarioDao) {
            this.scenarioDao = scenarioDao;
        }

        //protected Void doInBackground(Scenario... scenarios) {
        @Override
        protected Long doInBackground(Scenario... scenarios) {
            return scenarioDao.insert(scenarios[0]);
        }

       //protected void onPostExecute(Void aVoid) {
        @Override
        protected void onPostExecute(Long insertId) {
            super.onPostExecute(insertId);
            //onScenarioInserted(insertId, scenario);
        }
    }
}

还有这个 ViewModel:

public class ScenarioDetailViewModel extends AndroidViewModel {

    private ScenarioRepository repository;

    public ScenarioDetailViewModel(@NonNull Application application) {
        super(application);
        repository = new ScenarioRepository(application);
    }

    public void insert(Scenario scenario) {
        repository.insert(scenario);
    }
}

此函数在从按钮 OnClickListener 调用的片段中调用:

private void saveScenario() {

    String name = editTextName.getText().toString();

    if (name.isEmpty()) {
        Toast.makeText(getActivity(), "Please enter scenario name.", Toast.LENGTH_SHORT).show();
        return;
    }

    Scenario scenario = new Scenario(name);
    scenarioDetailViewModel.insert(scenario);

}

更新 感谢下面的 cmets。

    public class ScenarioRepository {

    private ScenarioDao scenarioDao;
    private LiveData<List<Scenario>> allScenarios;


    public ScenarioRepository(Application application) {

        AppDatabase database = AppDatabase.getInstance(application);
        scenarioDao = database.scenarioDao();
        allScenarios = scenarioDao.getAllScenarios();
    }


    public void insert (MutableLiveData<Long> id, Scenario scenario) {
        new InsertScenarioAsyncTask(scenarioDao).execute(id, scenario);
    }

    private static class InsertScenarioAsyncTask extends AsyncTask<Scenario, Void, Long> {
        private ScenarioDao scenarioDao;
    private MutableLiveData<Long> id;

        private InsertScenarioAsyncTask (MutableLiveData<Long> id, ScenarioDao scenarioDao) {
            this.scenarioDao = scenarioDao;
    this.id=id;
        }

        //protected Void doInBackground(Scenario... scenarios) {
        @Override
        protected Long doInBackground(Scenario... scenarios) {
            return scenarioDao.insert(scenarios[0]);
        }

       //protected void onPostExecute(Void aVoid) {
        @Override
        protected void onPostExecute(Long insertId) {
    id.postValue(insertId);
            super.onPostExecute(insertId);
        }

        @Override
        protected void onCancelled() {
            id.postValue(new Long(0));
            super.onCancelled();
        }
    }
}

在片段中:

    scenarioDetailViewModel = ViewModelProviders.of(this).get(ScenarioDetailViewModel.class);

    final Observer<Long> scenarioIdObserver = new Observer<Long>() {
        @Override
        public void onChanged(Long aLong) {
            Log.d(TAG, "onChanged, scenarioId is " + aLong);
        }
    };

    scenarioDetailViewModel.getCurrentScenarioId().observe(getActivity(),scenarioIdObserver);

这在 ViewModel 中:

public class ScenarioDetailViewModel extends AndroidViewModel {

    private static final String TAG="ScenarioDetailViewModel";
    private ScenarioRepository repository;
    private MutableLiveData<Long> currentId;

    public ScenarioDetailViewModel(@NonNull Application application) {
        super(application);
        currentId = new MutableLiveData<Long>();
        repository = new ScenarioRepository(application);
    }

    public MutableLiveData<Long> getCurrentId() {
        return currentId;
    }

    public void insert(Scenario scenario) {
        Log.d(TAG,"inserting scenario " + scenario.getName());
        repository.insert(currentId,scenario);
    }

    public void update(Scenario scenario) {
        repository.update(scenario);
    }

    public void delete(Scenario scenario) {
        repository.delete(scenario);
    }
}

【问题讨论】:

    标签: android android-asynctask android-room


    【解决方案1】:

    您可以在AsyncTask 中使用LiveData
    ScenarioRepository 看起来像这样:

    public MutableLiveData<Long> insert (Scenario scenario) {
            MutableLiveData<Long> liveData = new MutableLiveData()
            new InsertScenarioAsyncTask(liveData, scenarioDao).execute(scenario);
            return liveData ;
    }
    

    ِ你的 InsertScenarioAsyncTask:

    private static class InsertScenarioAsyncTask extends AsyncTask<Scenario, Void, Long> {
            private ScenarioDao scenarioDao;
            private MutableLiveData<Long> liveData;
    
            private InsertScenarioAsyncTask (MutableLiveData<Long> liveData, ScenarioDao scenarioDao) {
                this.liveData = liveData;
                this.scenarioDao = scenarioDao;
            }
    
            //protected Void doInBackground(Scenario... scenarios) {
            @Override
            protected Long doInBackground(Scenario... scenarios) {
                return scenarioDao.insert(scenarios[0]);
            }
    
           //protected void onPostExecute(Void aVoid) {
            @Override
            protected void onPostExecute(Long insertId) {
                liveData.postValue(insertId);
                super.onPostExecute(insertId);
                //onScenarioInserted(insertId, scenario);
            }
    
             @Override
             protected void onCancelled() {
                liveData.postValue(0);
                super.onCancelled();
             }
        }
    

    在您的片段中:

    liveData.observe(this, insertedId -> {
    // insertedId is the id of the inserted scenario
    // if value is 0 then the task was cancelled
        if(insertedId == 0){
    
        }else{
    
        }
    });
    

    【讨论】:

    • 我没有让它工作。我将此添加到 ViewModel 类中: public MutableLiveData insert(Scenario scenario) { return repository.insert(scenario); } 和这个片段: MutableLiveData scenarioId=scenarioDetailViewModel.insert(scenario); Toast.makeText(getActivity(),"New Id=" + scenarioId.getValue(),Toast.LENGTH_SHORT).show();
    • 我正在阅读您提供的链接,谢谢。在您提供的代码中,您正在存储库中创建 MutableLiveData。是否应该在 ViewModel 中创建并从那里传递到存储库?
    • 最好在 ViewModel 中创建它们。我只是展示了如何使用 LiveData 对象
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-23
    • 2019-06-07
    • 2013-06-17
    • 1970-01-01
    • 2016-06-02
    • 1970-01-01
    相关资源
    最近更新 更多