IllegalStateException:WorkManager 已经初始化

IllegalStateException: WorkManager is already initialized

具有这些依赖项:

dependencies {
    implementation "androidx.work:work-runtime:2.0.1"
    androidTestImplementation "androidx.work:work-testing:2.0.1"
}

当运行第二次出现此代码时:

Configuration config = new Configuration.Builder().build();
WorkManager.initialize(getApplicationContext(), config);

this.workManager = WorkManager.getInstance();

我收到此错误消息:

java.lang.IllegalStateException: WorkManager is already initialized.
Did you try to initialize it manually without disabling WorkManagerInitializer?
See WorkManager#initialize(Context, Configuration) or the class level Javadoc for more information.

而且它还会在本机端抛出分段错误:

A/libc: Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR),
fault addr 0x878 in tid 10892 (ova.workmanager),
pid 10892 (ova.workmanager)

这将是 WorkManager#initialize(Context, Configuration)documentation


目的是防止手动初始化时崩溃(为了改变日志级别)。如何禁用WorkManagerInitializer?如果可能,我不想使用 static 关键字。

您可以控制何时调用 workManager

if(this.workManager == null){
   Configuration config = new Configuration.Builder().build();
   WorkManager.initialize(getApplicationContext(), config);
   this.workManager = WorkManager.getInstance();
}

这是替换提供商的方法 androidx.work.impl.WorkManagerInitializer:

<application>
    ...

    <!-- disable default provider -->
    <provider
        android:name="androidx.work.impl.WorkManagerInitializer"
        android:authorities="${applicationId}.workmanager-init"
        android:exported="false"
        android:enabled="false"/>

    <!-- register custom provider -->
    <provider
        android:name=".CustomWorkManagerInitializer"
        android:authorities="${applicationId}.WorkManagerInit"/>

</application>

来源:Custom Work Manager initialization(在 Kotlin 中)。


除非注册另一个供应商,否则会出现:

java.lang.IllegalStateException: WorkManager is not initialized properly. The most
likely cause is that you disabled WorkManagerInitializer in your manifest but forgot
to call WorkManager#initialize in your Application#onCreate or a ContentProvider.

ContentProvider注册在src/debug/Manifest.xml

public class WorkManagerInit extends ContentProvider {

    @Override
    public boolean onCreate() {
        if(getContext() != null) {
            Configuration config = new Configuration.Builder().build();
            WorkManager.initialize(getContext().getApplicationContext(), config);
        }
        return true;
    }
    ...
}

如果你想初始化 WorkerManager,你必须把它放在你的自定义应用程序的 onCreate 中 class,这样它只会被调用一次。之后,您可以仅在需要时才可以放心地获取实例。不建议初始化 Worker Manager。为什么需要它?

WorkManager 是一个单例,在使用前需要进行配置,并且在不重启应用程序的情况下无法更改其配置。

第二次调用初始化会抛出异常,表明如果 WorkManager 已经初始化,它就不能使用该配置。这是在初始 alpha 版本期间做出的设计决定,以避免静默失败 (workmanager-1.0.0-alpha11)。

WorkManager v2.1 添加了一种按需初始化库的方式,因此您可以将实际初始化从应用程序的热启动序列中移出。但是,您仍然有 WorkManager 只能配置一次的限制。

使用新的按需配置,您必须向您的应用程序添加一个 Configuration.Provider 接口,如下所示:

class MyApplication : Application(), Configuration.Provider {

   override fun getWorkManagerConfiguration(): Configuration =
       // provide custom configuration
       Configuration.Builder()
               .setMinimumLoggingLevel(android.util.Log.INFO)
               .setWorkerFactory(MyWorkerFactory())
               .build()
}

然后,当您需要使用 WorkManager 时,您应该使用新的:

而不是使用 WorkManager#getInstance()(现已弃用)
WorkManager#getInstance(context)

在这种情况下,getInstance 方法检查 WorkManager 是否已经初始化。如果尚未初始化,它会使用 getWorkManagerConfiguration() 方法检索配置,然后初始化 WorkManager。这样就不用再调用了WorkManager#initialize()完全避免了问题

official documentation 已使用这些附加详细信息进行了更新。

如果您认为 WorkManager 应该允许在初始化后更新其配置,您应该向 library's issue tracker 添加功能请求。

因为 WorkManager 2.6, App Startup 在 WorkManager 内部使用。要提供自定义初始化程序,您需要删除 androidx.startup 节点。

如果您的应用中不使用 App Startup,您可以将其完全删除。

<provider
    android:name="androidx.startup.InitializationProvider"
    android:authorities="${applicationId}.androidx-startup"
    tools:node="remove">
</provider>

否则,仅删除 WorkManagerInitializer 节点。

<provider
    android:name="androidx.startup.InitializationProvider"
    android:authorities="${applicationId}.androidx-startup"
    android:exported="false"
    tools:node="merge">

    <!-- If you are using androidx.startup to initialize other components -->
    <meta-data
        android:name="androidx.work.WorkManagerInitializer"
        android:value="androidx.startup"
        tools:node="remove" />
</provider>

使用早于 2.6 的 WorkManager 版本时,请移除 workmanager-init:

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

用于解决此问题从清单

中禁用默认提供程序
<!-- disable default provider -->
           <provider
            android:name="androidx.work.impl.WorkManagerInitializer"
            android:authorities="${applicationId}.workmanager-init"
            tools:node="remove" />

替换下面的代码

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