IllegalStateException: WorkManager is already initialized

人走茶凉 提交于 2020-02-24 04:31:37

问题


Having these dependencies:

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

When running this code for the second time:

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

this.workManager = WorkManager.getInstance();

I get this error message:

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.

and it also throws a segmentation fault on the native side:

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

This would be the documentation for WorkManager#initialize(Context, Configuration).


The intent is to prevent the crash during manual initialization (in order to change the log level). How to disable the WorkManagerInitializer? If possible, I do not want to use the static keyword.


回答1:


WorkManager is a singleton, it needs to be configured before being used and you cannot change it's configuration without restarting the application.

A second call to initialize throws an exception to indicate that it cannot use that configuration if WorkManager has already been initialized. This was a design decision taken during the initial alpha releases to avoid to fail silently (workmanager-1.0.0-alpha11).

WorkManager v2.1 adds an on-demand way to initialize the library, so you can move the actual initialization out from the hot-start sequence of your app. However you still have the constraints that WorkManager can only be configured once.

With the new on-demand configuration, you've to add a Configuration.Provider interface to your application like here:

class MyApplication : Application(), Configuration.Provider {

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

Then, when you need to use WorkManager, instead of using WorkManager#getInstance() (that is now deprecated), you should use the new:

WorkManager#getInstance(context)

In this case, the getInstance method, check if WorkManager it's already initialized or not. If it's not yet initialized, it retrieves the configuration using the getWorkManagerConfiguration() method and then it initializes WorkManager. In this way, you don't call anymore WorkManager#initialize() completely avoiding the problem.

The official documentation has been updated with these additional details.

If you think that WorkManager should allows to update it's configuration after it has been initialized, you should add a feature request to the library's issue tracker.




回答2:


This is how to substitute provider 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>

Source: Custom Work Manager initialization (in Kotlin).


Unless registering another provider, this gives a:

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.

And the ContentProvider registered in the 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;
    }
    ...
}



回答3:


You can control when you called workManager

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



回答4:


If you want to initialize the WorkerManager you must put this in the onCreate of your custom Application class, so this only be called once. After that you can only get the instance when you need it without worries. It is not recommended to initialize the Worker Manager. Why do you need that?



来源:https://stackoverflow.com/questions/55875198/illegalstateexception-workmanager-is-already-initialized

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!