【问题标题】:WorkManager - Should we remove the default initializer, when we use both Default initialization and Custom initialization?WorkManager - 当我们同时使用默认初始化和自定义初始化时,我们是否应该删除默认初始化程序?
【发布时间】:2020-01-13 03:42:57
【问题描述】:

当我将 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 类

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

Application 类为空时,似乎很少有机会执行“默认初始化”(WorkManager.getInstance())。

我可以轻松消除 APK 导出期间的错误,包括以下 provider。但是,这样做对吗?

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

【问题讨论】:

  • 在提供者标签内设置以下属性并再次检查。 android:enabled="false" , android:exported="false"
  • 你从哪里给getWorkManager打电话?
  • 似乎tools:node="remove" 是正确的方法。我们团队很早就采用了docs中提到的方法,所以这不是什么新鲜事。

标签: android androidx android-workmanager


【解决方案1】:

我们在 WorkManager 2.3.0-* 中引入了这个 lint 规则。我们试图用这个 Lint 规则解决的问题是,如果你同时拥有 WorkManagerInitializer ContentProviderApplication 子类型实现 Configuration.Provider(用于按需初始化) - ContentProvider总是优先。

这可能出乎意料,尤其是当您有额外的Configuration 时,不会因为ContentProvider 总是使用默认配置而生效。

您真正需要做的就是删除默认提供程序。这样初始化将不再急切,而是按需进行。

【讨论】:

    【解决方案2】:

    是的,如果您想使用on-demand initialization,您需要删除默认的工作管理器初始化程序,因此请在您的清单中保留以下代码:

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

    此外,上述文档明确指出您不应调用 WorkManager.getInstance()(没有 Context 参数):

    注意:如果在 WorkManager 初始化之前调用已弃用的无参数 WorkManager.getInstance() 方法,该方法将引发异常。即使您没有自定义 WorkManager,您也应该始终使用 WorkManager.getInstance(Context) 方法。

    查看 android/work 更改日志后,您会看到 2.3.0-beta02 版本中添加了一个新功能:

    • 添加了一个 lint 规则,可确保在使用按需初始化时从 AndroidManifest.xml 中删除内容提供程序 androidx.work.impl.WorkManagerInitializer。 (aosp/1167007)

    从版本 2.2.0 升级到 2.3.0.rc1 后出现此错误的原因是,android 团队添加了一个RemoveWorkManagerInitializerDetector,它会在构建时抛出您在以下pull request 中遇到的异常.

    现在关于源代码,我建议您将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 教程退出 javakotlin

    【讨论】:

      【解决方案3】:

      如果您在更新到 WorkManager 2.6.0 或更高版本后收到此错误,则必须在清单中使用此 sn-p:

      <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>
      

      【讨论】:

        【解决方案4】:

        WorkManagerInitializer 用于为WorkManager 提供上下文。发生这种情况是因为内容提供者在Application 之前被初始化(请参阅this question)。如果您进行自定义初始化,这就是您需要自己提供上下文的原因。因此,如果您使用自定义初始化,则不需要它。

        如果您从content provider 调用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());
                ...
            }
            ...
        }
        

        【讨论】:

          猜你喜欢
          • 2014-12-29
          • 1970-01-01
          • 1970-01-01
          • 2020-02-08
          • 1970-01-01
          • 1970-01-01
          • 2012-11-29
          • 1970-01-01
          • 2015-02-25
          相关资源
          最近更新 更多