【问题标题】:What Context should i pass on WorkManager.getInstance().enqueue() ? (Using MVVM + Room Database + WorkManager)我应该传递什么上下文 WorkManager.getInstance().enqueue() ? (使用 MVVM + 房间数据库 + WorkManager)
【发布时间】:2021-04-13 17:11:41
【问题描述】:

我试图通过存储库方法将 WorkManager 工作人员排队,以便在我的数据库中插入一些数据,但我似乎无法弄清楚我应该在 getInstance() 中传递什么类型的上下文。显然,我给出的上下文是错误的,因为我得到了 NullPointerException。我是 Android 开发的新手,上下文的概念可能会令人困惑。我已经尝试了一切,但我相信这很简单。我正在使用 MVVM(如果我不应该将 Worker 加入存储库中,请告诉我)+ RoomDatabase。

AddWorkoutRepository.java

public class AddWorkoutRepository {

    private static final String REPOSITORY_TAG = "REPOSITORY TAG";
    private AddWorkoutWorker worker;

    private WorkoutDAO workoutDAO;
    //private LiveData<List<Workout>> workouts;

    public AddWorkoutRepository(Application application){

        AppDatabase database = AppDatabase.getInstance(application);
        workoutDAO = database.workoutDAO();
        //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("Importing Single Workout" + workoutName + " and " + workoutType)
                .build();

        WorkManager.getInstance(worker.getApplicationContext()).enqueue(importDataRequest);

        Log.d(REPOSITORY_TAG, "After work manager task OK");

    }
}

AddWorkoutWorker.java

public class AddWorkoutWorker extends Worker {

    public static final String WORK_WORKOUT_NAME = "workout";
    public static final String WORK_WORKOUT_TYPE = "type";
    private static final String WORKER_TAG = "Worker Tag";
    private WorkoutDAO workoutDAO;

    public AddWorkoutWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
        super(context, workerParams);
    }

    @NonNull
    @Override
    public Result doWork() {

        Data inputData = getInputData();
        String workoutName = inputData.getString(WORK_WORKOUT_NAME);
        String workoutType = inputData.getString(WORK_WORKOUT_TYPE);

        if (workoutName != null && workoutType != null){
            Log.d(WORKER_TAG,"Worker data passed: "+workoutName + workoutType);
            Workout workout = new Workout(workoutName, workoutType);
            workoutDAO.insertSingleWorkout(workout);
        }else{
            return Result.failure();
        }

        return Result.success();
    }
}

如果需要更多代码,请随时问我。非常感谢您提前提供的帮助!

【问题讨论】:

    标签: java android mvvm android-workmanager android-mvvm


    【解决方案1】:

    你在WorkManager.getInstance(worker.getApplicationContext()).enqueue(importDataRequest); 的行中有 NullPointerException 因为 worker 字段没有初始化,它的默认值为 null。 您不应该在每个 insertWorkout(Workout锻炼) 方法调用中获取 WorkManager 的实例。而不是将此传递 WorkManager 实例作为 AddWorkoutRepository 的构造函数中的依赖项。对于上下文,您可以改用活动上下文或应用程序上下文。 如果你不喜欢这种方法,你可以在 AddWorkoutRepository 类中添加 WorkManager 字段,并在 AddWorkoutRepository 构造函数中初始化它,并使用 Application 对象作为上下文。

    更新您的 AddWorkoutRepository 类:

    public class AddWorkoutRepository {
    
    private static final String REPOSITORY_TAG = "REPOSITORY TAG";
    private static final String WORK_WORKOUT_NAME = "work_name";
    private static final String WORK_WORKOUT_TYPE = "work_time";
    private final WorkManager workManager;
    private AddWorkoutWorker worker;
    
    private WorkoutDAO workoutDAO;
    //private LiveData<List<Workout>> workouts;
    
    public AddWorkoutRepository(Application application){
    
        AppDatabase 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("Importing Single Workout" + workoutName + " and " + workoutType)
                .build();
    
        workManager.enqueue(importDataRequest);
    
    
        Log.d(REPOSITORY_TAG, "After work manager task OK");
    
    }
    

    }

    【讨论】:

    • 我不建议将活动用作上下文,尽管它不一定会导致问题,但冒着泄漏的风险是没有意义的。使用应用程序上下文没有缺点..
    • @HenryTwist 是的,你是对的。谢谢指正。传递活动上下文可能会产生泄漏,因为存储库不应依赖于活动生命周期。更好的是使用应用上下文或依赖注入框架。
    • 感谢您的回答。尽管我有点理解你的意思,但我很难实现它。我没有设置任何依赖注入框架,我希望实现您建议的第二种方式,但到目前为止我尝试过的方法都失败了。我确定我正在做一些简单的新错误,我会继续尝试弄清楚,但如果你有时间,你介意更具体一点吗? (如果可能,显示一些代码)谢谢
    • 非常感谢!这让我发疯了。它现在完美无缺。干杯!
    猜你喜欢
    • 1970-01-01
    • 2022-10-12
    • 1970-01-01
    • 2012-06-19
    • 2013-02-02
    • 1970-01-01
    • 2010-09-28
    • 2013-07-26
    • 1970-01-01
    相关资源
    最近更新 更多