4

There is the dialog that saves an object to the Room database. The dialog should wait for saving to the database in order to run a special Worker class, that will retrieve this object from the database by ID and do some work with it.

But this requires synchronous code that is an anti-pattern in Room. I decided that the best option would be to run WorkManager, which will save the object to the database, and then run a special Worker class through the chain. But the problem is that I can't pass an object to save in Data.Builder, only primitive types. Only serialization variant in JSON remains. Is it possible to do without serialization? After all, the size of the serialized JSON, in theory, can exceed the limit of 10240 bytes.

Any help would be greatly appreciated!

proninyaroslav
  • 720
  • 2
  • 7
  • 19

2 Answers2

0

You will need to pass them by reference. So if you have an Room Entity grab its key / id and pass it as an input to the Worker by using setInputData in {OneTime|Periodic}WorkRequest.Builder and you can then query for the actual Room Entity in the implementation of the Worker.

Rahul
  • 19,744
  • 1
  • 25
  • 29
0

As stated in this answer here

You will need to pass them by reference. So if you have a Room Entity grab its key / id and pass it as an input to the Worker by using setInputData in {OneTime|Periodic}WorkRequest.Builder and you can then query for the actual Room Entity in the implementation of the Worker.

in my case, I used it to get a value from the database and perform a task, but it is the same principle.

  @Override
    public Result doWork() {

    final Context applicationContext = getApplicationContext();

    try {

        final String title = getInputData().getString(Constants.TITLE);
        final String msg = getInputData().getString(Constants.MESSAGE);

        final int id = getInputData().getInt(Constants.ID,0);


        Executor myExecutor = Executors.newSingleThreadExecutor();
        myExecutor.execute(new Runnable() {
            @Override
            public void run() {
                Entity entity =  BasicApp.getInstance().getDatabase().entityDao().getEntity(id);

                Timber.tag(TAG).d( "id for Entity %s", entity.getId());

                Utils.doMyTask(new String[] {title, msg}, id, applicationContext);
            }
        });

        return Result.success();

    } catch (Throwable throwable) {
        // Technically WorkManager will return Result.failure()
        // but it's best to be explicit about it.
        // Thus if there were errors, we're return FAILURE
        Timber.tag(TAG).e(throwable, "Error scheduling notification");

        return Result.failure();
    }

}

Create a WorkRequest for the Work manager to do your task

    public void do my task(long delay) {

       OneTimeWorkRequest request =
               new OneTimeWorkRequest.Builder(MyWorker.class)
                       .setInputData(createInputData())
                       .setInitialDelay(delay, TimeUnit.MILLISECONDS)
                       .addTag(Constants.MY_WORK_NAME)
                       .build();

       mWorkManager.enqueue(request);

}

Creates an input data bundle which includes the values @return Data which contains the values details

private Data createInputData() {

    Data.Builder builder = new Data.Builder();

    builder.putString(Constants.TITLE, title);
    builder.putString(Constants.MESSAGE, msg);
    builder.putInt(Constants.ID,id);

    return builder.build();
}
Ayia
  • 146
  • 6
  • The problem arises when it's necessary to save an entity in the database. In this case, you will have to serialize the data, but their size may exceed the limits of MAX_DATA_BYTES – proninyaroslav Feb 22 '21 at 14:34
  • @proninyaroslav Thanks for the insight, I haven't really had an experience where the size exceeds the max data bytes. If you could share the current method you're using, it will go a long way. – Ayia Feb 23 '21 at 09:59
  • Unfortunately I never found a solution. – proninyaroslav Feb 24 '21 at 14:45