Cha*_*dra 12 android dependency-injection kotlin android-workmanager dagger-hilt
WorkManagerInitializer需要配置 setWorkerFactory 以将依赖项注入到Worker类中。[文档][1] 解释了 AppStartup 时的 workManager 初始化,但没有提供有关如何配置 setWorkerFactory 的任何见解。如果有人可以提出任何解决方案或解决方法,那将非常有帮助。问题是我无法将自己的依赖项注入到workerClass中。我在下面列出了两个场景来解释这种情况:`工作场景#1:
// 这个调用工作正常。
class AppWorker @WorkerInject constructor(
@Assisted context: Context,
@Assisted workerParams: WorkerParameters
) : Worker(context, workerParams) {
companion object {
val workType = "WorkType"
}
override fun doWork(): Result {
return Result.success()
}
}
Run Code Online (Sandbox Code Playgroud)
失败场景#2:
// Initializes WorkManager.
class WorkManagerInitializer : Initializer<WorkManager> {
override fun create(context: Context): WorkManager {
// How to get workFactory required for configuration.
var workerFactory: HiltWorkerFactory? = null
val configuration = Configuration.Builder()
.setWorkerFactory(workerFactory)
.build()
WorkManager.initialize(context, configuration)
return WorkManager.getInstance(context)
}
override fun dependencies(): List<Class<out Initializer<*>>> {
// No dependencies on other libraries.
return emptyList()
}
}
@HiltAndroidApp
class BaseApp: Application(),Configuration.Provider{
@Inject lateinit var workerFactory: HiltWorkerFactory
override fun getWorkManagerConfiguration() =
Configuration.Builder()
.setWorkerFactory(workerFactory)
.build()
init {
Thread.setDefaultUncaughtExceptionHandler(ThreadExceptionalHandler())
}
override fun onCreate() {
super.onCreate()
if (BuildConfig.DEBUG) {
Timber.plant(DebugTree())
}
}
}
Run Code Online (Sandbox Code Playgroud)
清单.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.baseapp">
<application
android:name="com.example.baseapp.startup.BaseApp"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MyApp"
>
<activity android:name="com.example.baseapp.gui.activities.MainActivity"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<meta-data android:name="com.example.baseapp.startup.AppServicesInitializer"
android:value="androidx.startup" />
</provider>
<provider
android:name="androidx.work.impl.WorkManagerInitializer"
android:authorities="${applicationId}.workmanager-init"
tools:node="remove"/>
</application>
</manifest>
Run Code Online (Sandbox Code Playgroud)
// 应用程序符合并成功运行,但无法调用 doWork()
[1]: https://developer.android.com/topic/libraries/app-startup
The AppWorker class dowork() method is not getting called with WorkManagerInitializer defined at AppStartup. Here is the error in logcat:
2020-09-24 19:38:41.811 23803-23863/com.example.baseapp E/WM-WorkerFactory: Could not instantiate com.example.baselib.services.local.work_manager.worker.AppWorker
java.lang.NoSuchMethodException: com.example.baselib.services.local.work_manager.worker.AppWorker.<init> [class android.content.Context, class androidx.work.WorkerParameters]
at java.lang.Class.getConstructor0(Class.java:2332)
at java.lang.Class.getDeclaredConstructor(Class.java:2170)
at androidx.work.WorkerFactory.createWorkerWithDefaultFallback(WorkerFactory.java:95)
at androidx.work.impl.WorkerWrapper.runWorker(WorkerWrapper.java:242)
at androidx.work.impl.WorkerWrapper.run(WorkerWrapper.java:136)
at androidx.work.impl.utils.SerialExecutor$Task.run(SerialExecutor.java:91)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:923)
Run Code Online (Sandbox Code Playgroud)
对于使用 Hiltandroidx.work-*版本2.6.0-alpha01或更高版本的人:
从发行说明来看,该版本开始在内部使用新的androidx.startupjetpack 库。WorkManager因此,删除的默认初始值设定项的方式AndroidManifest.xml发生了一些变化。
androidx.startup如果您在应用程序的其他地方使用,请将旧的更改替换为:
<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.impl.WorkManagerInitializer"
android:value="androidx.startup"
tools:node="remove" />
</provider>
Run Code Online (Sandbox Code Playgroud)
否则,您可以androidx.startup通过将旧更改替换为以下内容来完全禁用:
<!-- If you want to disable androidx.startup completely. -->
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
tools:node="remove">
</provider>
Run Code Online (Sandbox Code Playgroud)
这样,您HiltWorker将再次在子类应用程序中使用工厂。不幸的是,您将失去延迟启动的(明显的)好处。
小智 6
我们可以直接使用 HiltWorkerFactory Initializer。这是例子:
class CustomWorkManagerInitializer : Initializer<WorkManager> {
override fun create(context: Context): WorkManager {
val workerFactory = getWorkerFactory(appContext = context.applicationContext)
val config = Configuration.Builder()
.setWorkerFactory(workerFactory)
.build()
WorkManager.initialize(context, config)
return WorkManager.getInstance(context)
}
override fun dependencies(): MutableList<Class<out Initializer<*>>> = mutableListOf()
private fun getWorkerFactory(appContext: Context): HiltWorkerFactory {
val workManagerEntryPoint = EntryPointAccessors.fromApplication(
appContext,
WorkManagerInitializerEntryPoint::class.java
)
return workManagerEntryPoint.hiltWorkerFactory()
}
@InstallIn(SingletonComponent::class)
@EntryPoint
interface WorkManagerInitializerEntryPoint {
fun hiltWorkerFactory(): HiltWorkerFactory
}
}
Run Code Online (Sandbox Code Playgroud)
删除应用程序中的 HiltWorkerFactory 注入。
@HiltAndroidApp
class BaseApp : Application() {
override fun onCreate() {
super.onCreate()
AppInitializer.getInstance(this).initializeComponent(CustomWorkManagerInitializer::class.java)
}
}
Run Code Online (Sandbox Code Playgroud)
还禁用默认WorkManager初始化程序并在清单中添加我们的自定义。
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<!-- disable default -->
<meta-data
android:name="androidx.work.WorkManagerInitializer"
android:value="@string/androidx_startup"
tools:node="remove" />
<!-- enable custom -->
<meta-data
android:name="com.acme.app.initializer.CustomWorkManagerInitializer"
android:value="androidx.startup" />
</provider>
Run Code Online (Sandbox Code Playgroud)
您可以通过使用如下所示的注释来简单地注入依赖项@WorkerInject并摆脱您的工厂:
class ExampleWorker @WorkerInject constructor(
@Assisted appContext: Context,
@Assisted workerParams: WorkerParameters,
dependency: YourClassDependency
) : Worker(appContext, workerParams) { ... }
Run Code Online (Sandbox Code Playgroud)
然后,让您的Application类实现该Configuration.Provider接口,注入 的实例HiltWorkFactory,并将其传递到WorkManager配置中,如下所示:
@HiltAndroidApp
class ExampleApplication : Application(), Configuration.Provider {
@Inject lateinit var workerFactory: HiltWorkerFactory
override fun getWorkManagerConfiguration() =
Configuration.Builder()
.setWorkerFactory(workerFactory)
.build()
}
Run Code Online (Sandbox Code Playgroud)
请注意,您还必须从以下位置删除默认初始值设定项AndroidManifest.xml:
<application>
<provider
android:name="androidx.work.impl.WorkManagerInitializer"
android:authorities="${applicationId}.workmanager-init"
tools:node="remove" />
</application>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6653 次 |
| 最近记录: |