java - 如何从 Worker 获取输出数据?(MVVM + WorkManager + Room)
问题描述
我正在使用 MVVM 并将一名工作人员从我的存储库中排队。工作人员的工作只是将一些数据插入数据库,但我想在后台任务完成后访问一些输出数据,这样我就可以验证数据是否在没有问题的情况下进入数据库。我尝试使用 WorkInfo.State 或使用 getOutputData 获取数据,但由于某种原因它似乎不起作用。关于我如何实现这一目标的任何想法?
这是供参考的代码:
AddWorkoutWorker.java
public class AddWorkoutWorker extends Worker {
public static final String WORK_WORKOUT_NAME = "workout";
public static final String WORK_WORKOUT_TYPE = "type";
public static final String WORK_FAILURE_TAG = "failed";
public static final String WORK_SUCCESS_TAG = "success";
private static final String WORKER_TAG = "Worker Tag";
private WorkoutDAO workoutDAO;
private AppDatabase database;
Boolean workSuccess;
//Worker constructor
public AddWorkoutWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
database = AppDatabase.getInstance(context);
workoutDAO = database.workoutDAO();
}
@NonNull
@Override
public Result doWork() {
//Gets input data
Data inputData = getInputData();
String workoutName = inputData.getString(WORK_WORKOUT_NAME);
String workoutType = inputData.getString(WORK_WORKOUT_TYPE);
if (workoutName != null && workoutType != null){
//Inserts item in database through DAO
Log.d(WORKER_TAG,"Worker data passed: "+workoutName + workoutType);
Workout workout = new Workout(workoutName, workoutType);
workoutDAO.insertSingleWorkout(workout);
}else{
//Returns false if the worker doesn't add the item to the database
workSuccess = false;
Data output = new Data.Builder()
.putBoolean(WORK_FAILURE_TAG,workSuccess)
.build();
return Result.failure(output);
}
//Returns true if the worker adds the item to the database
workSuccess = true;
Data output = new Data.Builder()
.putBoolean(WORK_SUCCESS_TAG, workSuccess)
.build();
return Result.success(output);
}
}
AddWorkoutRepository.java
public class AddWorkoutRepository{
private static final String REPOSITORY_TAG = "REPOSITORY TAG";
public static final String WORKER_QUEUE_TAG = "Importing Single Workout";
public WorkoutDAO workoutDAO;
private final WorkManager workManager;
private AppDatabase database;
//private LiveData<List<Workout>> workouts;
public AddWorkoutRepository(Application application){
database = AppDatabase.getInstance(application);
workoutDAO = database.workoutDAO();
workManager = WorkManager.getInstance(application.getApplicationContext());
//workouts = workoutDAO.getAllWorkoutsLiveData();
}
/*public LiveData<List<Workout>> getAllWorkouts(){
return workouts;
}*/
public void insertWorkout(Workout workout){
String workoutName = workout.getWorkoutName();
String workoutType = workout.getWorkoutType();
Log.d(REPOSITORY_TAG, "Insert Values passed: "+workoutName + workoutType);
Data data = new Data.Builder()
.putString(WORK_WORKOUT_NAME, workoutName)
.putString(WORK_WORKOUT_TYPE, workoutType)
.build();
OneTimeWorkRequest importDataRequest = new OneTimeWorkRequest.Builder(AddWorkoutWorker.class)
.setInputData(data)
.addTag(WORKER_QUEUE_TAG)
.build();
workManager.enqueue(importDataRequest);
Log.d(REPOSITORY_TAG, "After work manager task OK");
}
}
解决方案
好的,所以我想通了。我使用 WorkInfo 提供的 LiveData obj 来获取输出数据和任务状态。
- 我做的第一件事是在我的 ViewModel 中声明 LiveData obj
private LiveData<List<WorkInfo>> workerOutPut;
- 然后在视图模型构造函数中像这样初始化我的 LiveData
workerOutPut = workManager.getWorkInfosByTagLiveData(ADD_WORKOUT_WORKER_QUEUE_TAG);
- 为 LiveData 制作了一个吸气剂(当然在 ViewModel 中)
- 然后我只是简单地在我的活动中创建了一个观察者,它根据我在 Worker 输出数据中设置的布尔值检查 Worker 的状态。
就是这样。我对这一切都很陌生,所以如果有人有什么要补充的,请随时这样做。我将发布其他新“玩家”的完整代码以帮助他们。
工人.java
public class AddWorkoutWorker extends Worker {
public static final String WORK_WORKOUT_NAME = "workout";
public static final String WORK_WORKOUT_TYPE = "type";
public static final String WORK_FAILURE_TAG = "failed";
public static final String WORK_SUCCESS_TAG = "success";
private static final String ADD_WORKOUT_WORKER_TAG = "Worker Tag";
private WorkoutDAO workoutDAO;
private AppDatabase database;
Boolean workSuccess;
//Worker constructor
public AddWorkoutWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
database = AppDatabase.getInstance(context);
workoutDAO = database.workoutDAO();
}
@NonNull
@Override
public Result doWork() {
//Gets input data
Data inputData = getInputData();
String workoutName = inputData.getString(WORK_WORKOUT_NAME);
String workoutType = inputData.getString(WORK_WORKOUT_TYPE);
if (workoutName != null && workoutType != null){
//Inserts item in database through DAO
Log.d(ADD_WORKOUT_WORKER_TAG,"Worker data passed: "+workoutName + workoutType);
Workout workout = new Workout(workoutName, workoutType);
workoutDAO.insertSingleWorkout(workout);
}else{
//Returns false if the worker doesn't add the item to the database
workSuccess = false;
Data output = new Data.Builder()
.putBoolean(WORK_FAILURE_TAG,workSuccess)
.build();
return Result.failure(output);
}
//Returns true if the worker adds the item to the database
workSuccess = true;
Data output = new Data.Builder()
.putBoolean(WORK_SUCCESS_TAG, workSuccess)
.build();
return Result.success(output);
}
}
ViewModel.java
public class AddWorkoutViewModel extends AndroidViewModel {
private static final String WORKOUT_VIEW_MODEL = "Workout View Model";
private AddWorkoutRepository repository;
private AddWorkoutWorker worker;
private WorkManager workManager;
private Boolean check;
private LiveData<List<WorkInfo>> workerOutPut;
//private LiveData<List<Workout>> AllWorkouts;
public AddWorkoutViewModel(@NonNull Application application) {
super(application);
repository = new AddWorkoutRepository(application);
workManager = WorkManager.getInstance(application);
workerOutPut = workManager.getWorkInfosByTagLiveData(ADD_WORKOUT_WORKER_QUEUE_TAG);
//AllWorkouts = repository.getAllWorkouts();
}
/*public LiveData<List<Workout>> getWorkoutList(){
return AllWorkouts;
}*/
public LiveData<List<WorkInfo>> checkWorkerStatus(){
return workerOutPut;
}
public void insertData(Workout workout){
Log.d(WORKOUT_VIEW_MODEL,"View Model Insert Data");
repository.insertWorkout(workout);
}
}
活动内的观察者
//Observes LiveData from WorkManager AddWorkoutWorker to validate if worker functioned correctly
mAddWorkoutViewModel.checkWorkerStatus().observe(this, new Observer<List<WorkInfo>>() {
@Override
public void onChanged(List<WorkInfo> workInfos) {
if(workInfos.isEmpty() || workInfos == null){
Log.d(ADD_WORKOUT_WORKER_EMPTY,"Worker is empty");
}else{
if(workInfos.get(0).getOutputData().getBoolean(WORK_SUCCESS_TAG, false)){
//If works do stuff here
}else{
Toast.makeText(AddWorkoutActivity.this,"Something went wrong. Try again.",Toast.LENGTH_LONG);
}
}
}
});
对于那些可能想知道的人。我使用 workInfos.get(0) 因为我们只有一个正在检查的工人。我假设如果我们同时有多个工人,我们可以为每个工人提出一个案例。
推荐阅读
- mongodb - 过滤掉 mongodb/mongoose 上的内部集合
- c# - RestSharp Google 的 OAuth
- .net - Installshield 2018 中的 .NET 托管 dll 自定义操作
- python - redis 锁定:redispy 与 python-redis-lock
- oracle-apex - 需要重定向到 Oracle 中的文件共享路径
- javascript - 带有复选框的样式下拉列表
- ms-access - 在单个子 MS Access 内的 2 段代码中使用相同的变量
- package - 当我对 Microsoft 包 C++ 一无所知时,如何安装 easyphp?
- flutter - 如果路径或名称文件中存在空格,则无法加载图像 Flutter
- javascript - 将自定义级别添加到 bunyan 实例