简体   繁体   English

WorkManager - 当我们同时使用默认初始化和自定义初始化时,我们是否应该删除默认初始化程序?

[英]WorkManager - Should we remove the default initializer, when we use both Default initialization and Custom initialization?

I'm getting the following new error, when I upgrade WorkManager from "2.2.0" to "2.3.0-rc01"当我将 WorkManager 从“2.2.0”升级到“2.3.0-rc01”时,出现以下新错误

The error occurs when I'm exporting APK.当我导出 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.

I'm not sure why I didn't get such error in 2.2.0, as "On-Demand Initialization" is introduced since 2.1.0.我不知道为什么我在 2.2.0 中没有收到这样的错误,因为从 2.1.0 开始引入了“按需初始化”。

According to https://developer.android.com/topic/libraries/architecture/workmanager/advanced/custom-configuration#remove-default根据https://developer.android.com/topic/libraries/architecture/workmanager/advanced/custom-configuration#remove-default

I'm not kinna sure, whether it is a right thing to include the following in my AndroidManifest.xml .我不确定在我的AndroidManifest.xml包含以下内容是否正确。

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

Currently, the following is my Application class.目前,以下是我的Application类。

MyApplication class MyApplication 类

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();
    }
}

How I construct WorkManager我如何构建 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);
    }
}

It seems that there is rare chance that "Default initialization" ( WorkManager.getInstance() ) is being executed too, when the Application class is null.Application类为空时,似乎也很少有机会执行“默认初始化”( WorkManager.getInstance() )。

I can easily eliminate error during APK exporting, by including the following provider .通过包含以下provider ,我可以轻松消除 APK 导出过程中的错误。 But, is that a right thing to to so?但是,这样做是对的吗?

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

We introduced this lint rule in WorkManager 2.3.0-* .我们在 WorkManager 2.3.0-*引入了这个 lint 规则。 The problem we are trying to address with this Lint rule is that if you have both the WorkManagerInitializer ContentProvider and your Application subtype implements Configuration.Provider (for on-demand initialization) - the ContentProvider will always take precedence.我们试图通过此 Lint 规则解决的问题是,如果您同时拥有WorkManagerInitializer ContentProvider并且您的Application子类型实现了Configuration.Provider (用于按需初始化) - ContentProvider始终优先。

This might be unexpected, especially when you have additional Configuration which will not take effect because the ContentProvider always uses the default configuration.这可能出乎意料,尤其是当您有额外的Configuration不会生效时,因为ContentProvider始终使用默认配置。

All you really need to do is to remove the default provider.您真正需要做的就是删除默认提供程序。 That way initialization will no longer be eager, but be on-demand.这样初始化将不再是急切的,而是按需进行的。

Yes you need to remove the default work manager initializer as you did if you want to use on-demand initialization , so keep the following piece of code in your manifest:是的,如果您想使用按需初始化,您需要删除默认的工作管理器初始化程序,因此请在清单中保留以下代码:

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

Also the above documentation clearly state that you should not be calling WorkManager.getInstance() (without the Context argument):此外,上述文档明确指出您不应调用WorkManager.getInstance() (没有Context参数):

Note: If you call the deprecated no-parameter WorkManager.getInstance() method before WorkManager has been initialized, the method throws an exception.注意:如果在 WorkManager 初始化之前调用已弃用的无参数 WorkManager.getInstance() 方法,该方法将引发异常。 You should always use the WorkManager.getInstance(Context) method, even if you're not customizing WorkManager.您应该始终使用 WorkManager.getInstance(Context) 方法,即使您没有自定义 WorkManager。

After looking at the androix/work changelog you will see that a new feature was added in version 2.3.0-beta02 :查看 androix/work 更新日志后,您会看到在2.3.0-beta02版本中添加了一个新功能:

  • Added a lint rule which ensures that the content provider androidx.work.impl.WorkManagerInitializer is removed from the AndroidManifest.xml when using on demand initialization.添加了 lint 规则,以确保在使用按需初始化时从 AndroidManifest.xml 中删除内容提供程序 androidx.work.impl.WorkManagerInitializer。 ( aosp/1167007 ) ( aosp/1167007 )

The reason why you have this error after upgrading from version 2.2.0 to 2.3.0.rc1 is because, the android team added a RemoveWorkManagerInitializerDetector that would throw the exception you got in the following pull request at build time.从版本 2.2.0 升级到 2.3.0.rc1 后出现此错误的原因是,android 团队添加了一个RemoveWorkManagerInitializerDetector ,它会在构建时抛出您在以下拉取请求中遇到的异常。

Now about the source code, I suggest you tight the getWorkManager method to the application directly like below:现在关于源代码,我建议您将getWorkManager方法直接与应用程序紧密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);
    }
}

And just call App.getWorkManager() whenever you need to in the app source code只要您需要在应用程序源代码中调用App.getWorkManager()

You could do something equivalent for your ContentProvider if there is any.如果有的话,您可以为您的 ContentProvider 做一些等效的事情。

PS: Interesting codelabs tutorials exits for java or kotlin PS:有趣的 codelabs 教程退出javakotlin

WorkManagerInitializer is used to provide a context to WorkManager . WorkManagerInitializer用于提供一个上下文WorkManager This happens because content providers are initialized before the Application (See this question ).发生这种情况是因为内容提供程序在Application之前初始化(请参阅此问题)。 This is the reason you need to provide the context yourself if you do custom initialization.如果您进行自定义初始化,这就是您需要自己提供上下文的原因。 So if you use the custom initialization, you shouldn't need it.因此,如果您使用自定义初始化,则不需要它。

If you're calling the getWorkManager method from a content provider then your application instance will be null .如果您从内容提供者调用getWorkManager方法,那么您的应用程序实例将为null To resolve this issue just pass the context as a parameter to the method by calling getContext inside the content provider:要解决此问题,只需通过在内容提供程序中调用getContext将上下文作为参数传递给方法:

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

If you are getting this error after updating to WorkManager 2.6.0 or higher, you have to use this snippet in your manifest:如果您在更新到WorkManager 2.6.0 或更高版本后收到此错误,则必须在清单中使用此代码段:

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

    <meta-data
        android:name="androidx.work.WorkManagerInitializer"
        android:value="androidx.startup"
        tools:node="remove" />

</provider>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用 ContentLoadingProgressBar 以及何时应该使用它而不是默认的 ProgressBar? - How to use ContentLoadingProgressBar and when should we use it instead of the default ProgressBar? WorkManager 自定义初始化抱怨 WorkManager#initialize - WorkManager custom initialization complains about WorkManager#initialize 我们可以使用默认的SMS通知来接收自定义生成的消息吗? - Can we use default SMS Notification for Incoming custom generated Message? WorkManager 的二次初始化 - Second initialization of WorkManager 为什么要实现/使用看门狗而不是Linux默认看门狗? - Why should we implement/use our watchdog instead of Linux default watchdog? 在Android中从包裹中读取对象时,何时我们不想使用默认的ClassLoader? - When reading an object from a parcel in Android, when we not want to use the default ClassLoader? 我们如何删除默认的Android设备颜色 - How can we remove default Android Device colour 我们什么时候应该使用OnCompleteListener()进行查询 - when should we use the OnCompleteListener() for queries 我们什么时候应该在布局中使用dp或sp? - When should we use dp or sp in layout? 我们什么时候应该在Android中使用Looper? - When should we use Looper in Android?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM