WorkManager - Должны ли мы удалить инициализатор по умолчанию, когда мы используем инициализацию по умолчанию и пользовательскую инициализацию? - PullRequest
6 голосов
/ 13 января 2020

Я получаю следующую новую ошибку при обновлении WorkManager с «2.2.0» до «2.3.0-rc01»

Ошибка возникает при экспорте APK.

C:\app: Error: Remove androidx.work.impl.WorkManagerInitializer from your AndroidManifest.xml when using on-demand initialization. [RemoveWorkManagerInitializer]

   Explanation for issues of type "RemoveWorkManagerInitializer":
   If an android.app.Application implements
   androidx.work.Configuration.Provider,
   the default androidx.work.impl.WorkManagerInitializer needs to be removed
   from the
   AndroidManifest.xml file.

Я не уверен, почему я не получил такую ​​ошибку в 2.2.0, так как «Инициализация по требованию» введена с 2.1.0.

Согласно https://developer.android.com/topic/libraries/architecture/workmanager/advanced/custom-configuration#remove -default

Я не уверен, что правильно ли включать следующее в мой AndroidManifest.xml.

<provider
    android:name="androidx.work.impl.WorkManagerInitializer"
    android:authorities="${applicationId}.workmanager-init"
    tools:node="remove" />

В настоящее время Вот мой Application класс.

MyApplication class

public class MyApplication extends MultiDexApplication implements Configuration.Provider {
    private static MyApplication me;

    @Override
    public void onCreate() {
        super.onCreate();

        me = this;
    }

    public static MyApplication instance() {
        return me;
    }

    @NonNull
    @Override
    public Configuration getWorkManagerConfiguration() {
        return new Configuration.Builder()
                .build();
    }
}

Как я создаю WorkManager

public static WorkManager getWorkManager() {
    MyApplication myApplication = MyApplication.instance();
    if (myApplication == null) {
        // Very rare edge case. Not sure how it happens. But, it happens :)
        return WorkManager.getInstance();
    } else {
        return WorkManager.getInstance(myApplication);
    }
}

Кажется, что есть редкий шанс, что " Инициализация по умолчанию "(WorkManager.getInstance()) также выполняется, когда класс Application равен нулю.

Я легко могу устранить ошибку при экспорте APK, добавив следующую строку provider. Но так ли это?

<provider
    android:name="androidx.work.impl.WorkManagerInitializer"
    android:authorities="${applicationId}.workmanager-init"
    tools:node="remove" />

Ответы [ 3 ]

2 голосов
/ 17 января 2020

Да, вам нужно удалить инициализатор диспетчера работ по умолчанию, как вы это сделали, если хотите использовать инициализация по требованию , поэтому сохраните следующий фрагмент кода в манифесте:

<provider
   android:name="androidx.work.impl.WorkManagerInitializer"
   android:authorities="${applicationId}.workmanager-init"
   tools:node="remove" />

Также в приведенной выше документации четко указано, что вы не должны вызывать WorkManager.getInstance() (без аргумента Context):

Примечание: если вы вызываете устаревший без параметров WorkManager.getInstance () метод до инициализации WorkManager, метод вызывает исключение. Вы всегда должны использовать метод WorkManager.getInstance (Context), даже если вы не настраиваете WorkManager.

После просмотра журнала изменений androix / work вы увидите, что в версию была добавлена ​​новая функция 2.3.0-beta02 :

  • Добавлено правило lint, обеспечивающее удаление поставщика контента androidx.work.impl.WorkManagerInitializer из AndroidManifest. xml при использовании в инициализация запроса. ( aosp / 1167007 )

Причина появления этой ошибки после обновления с версии 2.2.0 до 2.3.0.rc1 заключается в том, что команда android добавила RemoveWorkManagerInitializerDetector , который будет выдавать исключение, которое вы получили в следующем запросе на получение во время сборки.

Теперь по поводу исходного кода, я предлагаю вам жесткий метод getWorkManager непосредственно к приложению, как показано ниже:

import androidx.annotation.NonNull;
import androidx.work.Configuration;
import androidx.work.WorkManager;

public class App extends MultiDexApplication implements Configuration.Provider {
    private static App APP_INSTANCE;

    @Override
    public void onCreate() {
        super.onCreate();
        APP_INSTANCE = this;
    }

    public static App getInstance() {
        return APP_INSTANCE;
    }

    @NonNull
    @Override
    public Configuration getWorkManagerConfiguration() {
        return new Configuration.Builder()
                .build();
    }

    public static WorkManager getWorkManager() {
        return WorkManager.getInstance(APP_INSTANCE);
    }
}

И просто звоните App.getWorkManager() всякий раз, когда вам нужно в исходном коде приложения

Вы можете сделать что-то эквивалентное для вашего ContentProvider, если таковой имеется.

PS: интересные учебные пособия по codelabs для java или kotlin

1 голос
/ 16 января 2020

Мы ввели это правило lint в WorkManager 2.3.0-*. Проблема, которую мы пытаемся решить с помощью этого правила Lint, заключается в том, что если у вас есть оба типа WorkManagerInitializer ContentProvider и ваш подтип Application Configuration.Provider (для инициализации по требованию) - ContentProvider будет всегда имеет приоритет.

Это может быть неожиданно, особенно если у вас есть дополнительные Configuration, которые не будут вступать в силу, потому что ContentProvider всегда использует конфигурация по умолчанию.

Все, что вам действительно нужно сделать, это удалить провайдера по умолчанию. Таким образом, инициализация больше не будет стремиться, а будет выполняться по требованию.

0 голосов
/ 15 января 2020

WorkManagerInitializer используется для предоставления контекста для WorkManager. Это происходит потому, что поставщики контента инициализируются до Application (см. этот вопрос ). По этой причине вам нужно предоставить контекст самостоятельно, если вы делаете пользовательскую инициализацию. Поэтому, если вы используете пользовательскую инициализацию, она вам не понадобится.

Если вы вызываете метод getWorkManager из провайдера контента , тогда ваш экземпляр приложения будет null , Чтобы решить эту проблему, просто передайте контекст как параметр методу, вызвав getContext внутри провайдера контента:

public static WorkManager getWorkManager(Context context) {
    return WorkManager.getInstance(context);
}
public class MyContentProvider extends ContentProvider {
    @Override
    public boolean onCreate() {
        WorkManager workManager = getWorkManager(getContext());
        ...
    }
    ...
}
...