Skip to content

Commit 93053da

Browse files
author
Sebastian Roth
authored
Android: load Flutter engine asynchronously (#276)
* Load Flutter environment asynchronously
1 parent 81e6241 commit 93053da

File tree

4 files changed

+59
-38
lines changed

4 files changed

+59
-38
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# 0.5.0-dev.1
2+
3+
* Android: Load Flutter environment asynchronously in the Worker task
4+
15
# 0.4.1
26

37
* Bumps Android dependencies (Kotlin, AGP, workmanager 2.5.0)

android/src/main/kotlin/be/tramckrijte/workmanager/BackgroundWorker.kt

+53-35
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,22 @@ import androidx.work.WorkerParameters
1010
import com.google.common.util.concurrent.ListenableFuture
1111
import io.flutter.embedding.engine.FlutterEngine
1212
import io.flutter.embedding.engine.dart.DartExecutor
13+
import io.flutter.embedding.engine.loader.FlutterLoader
1314
import io.flutter.embedding.engine.plugins.shim.ShimPluginRegistry
1415
import io.flutter.plugin.common.MethodCall
1516
import io.flutter.plugin.common.MethodChannel
1617
import io.flutter.view.FlutterCallbackInformation
17-
import io.flutter.view.FlutterMain
1818
import java.util.*
1919

2020
/***
2121
* A simple worker that will post your input back to your Flutter application.
2222
*
2323
* It will block the background thread until a value of either true or false is received back from Flutter code.
24-
*
2524
*/
2625
class BackgroundWorker(
27-
private val ctx: Context,
26+
applicationContext: Context,
2827
private val workerParams: WorkerParameters
29-
) : ListenableWorker(ctx, workerParams), MethodChannel.MethodCallHandler {
28+
) : ListenableWorker(applicationContext, workerParams), MethodChannel.MethodCallHandler {
3029

3130
private lateinit var backgroundChannel: MethodChannel
3231

@@ -37,8 +36,11 @@ class BackgroundWorker(
3736
const val DART_TASK_KEY = "be.tramckrijte.workmanager.DART_TASK"
3837
const val IS_IN_DEBUG_MODE_KEY = "be.tramckrijte.workmanager.IS_IN_DEBUG_MODE_KEY"
3938

40-
const val BACKGROUND_CHANNEL_NAME = "be.tramckrijte.workmanager/background_channel_work_manager"
39+
const val BACKGROUND_CHANNEL_NAME =
40+
"be.tramckrijte.workmanager/background_channel_work_manager"
4141
const val BACKGROUND_CHANNEL_INITIALIZED = "backgroundChannelInitialized"
42+
43+
private val flutterLoader = FlutterLoader()
4244
}
4345

4446
private val payload
@@ -51,40 +53,55 @@ class BackgroundWorker(
5153
get() = workerParams.inputData.getBoolean(IS_IN_DEBUG_MODE_KEY, false)
5254

5355
private val randomThreadIdentifier = Random().nextInt()
54-
private lateinit var engine: FlutterEngine
56+
private var engine: FlutterEngine? = null
5557

56-
private var destroying = false
5758
private var startTime: Long = 0
5859
private val resolvableFuture = ResolvableFuture.create<Result>()
5960

6061
override fun startWork(): ListenableFuture<Result> {
6162
startTime = System.currentTimeMillis()
6263

63-
engine = FlutterEngine(ctx)
64-
FlutterMain.ensureInitializationComplete(ctx, null)
64+
engine = FlutterEngine(applicationContext)
6565

66-
val callbackHandle = SharedPreferenceHelper.getCallbackHandle(ctx)
67-
val callbackInfo = FlutterCallbackInformation.lookupCallbackInformation(callbackHandle)
68-
val dartBundlePath = FlutterMain.findAppBundlePath()
69-
70-
if (isInDebug) {
71-
DebugHelper.postTaskStarting(
72-
ctx,
73-
randomThreadIdentifier,
74-
dartTask,
75-
payload,
76-
callbackHandle,
77-
callbackInfo,
78-
dartBundlePath
79-
)
66+
if (!flutterLoader.initialized()) {
67+
flutterLoader.startInitialization(applicationContext)
8068
}
8169

82-
//Backwards compatibility with v1. We register all the user's plugins.
83-
WorkmanagerPlugin.pluginRegistryCallback?.registerWith(ShimPluginRegistry(engine))
84-
engine.dartExecutor.executeDartCallback(DartExecutor.DartCallback(ctx.assets, dartBundlePath, callbackInfo))
70+
flutterLoader.ensureInitializationCompleteAsync(
71+
applicationContext,
72+
null,
73+
Handler(Looper.getMainLooper())
74+
) {
75+
val callbackHandle = SharedPreferenceHelper.getCallbackHandle(applicationContext)
76+
val callbackInfo = FlutterCallbackInformation.lookupCallbackInformation(callbackHandle)
77+
val dartBundlePath = flutterLoader.findAppBundlePath()
78+
79+
if (isInDebug) {
80+
DebugHelper.postTaskStarting(
81+
applicationContext,
82+
randomThreadIdentifier,
83+
dartTask,
84+
payload,
85+
callbackHandle,
86+
callbackInfo,
87+
dartBundlePath
88+
)
89+
}
90+
91+
//Backwards compatibility with v1. We register all the user's plugins.
92+
WorkmanagerPlugin.pluginRegistryCallback?.registerWith(ShimPluginRegistry(engine!!))
8593

86-
backgroundChannel = MethodChannel(engine.dartExecutor, BACKGROUND_CHANNEL_NAME)
87-
backgroundChannel.setMethodCallHandler(this@BackgroundWorker)
94+
backgroundChannel = MethodChannel(engine!!.dartExecutor, BACKGROUND_CHANNEL_NAME)
95+
backgroundChannel.setMethodCallHandler(this@BackgroundWorker)
96+
97+
engine!!.dartExecutor.executeDartCallback(
98+
DartExecutor.DartCallback(
99+
applicationContext.assets,
100+
dartBundlePath,
101+
callbackInfo
102+
)
103+
)
104+
}
88105

89106
return resolvableFuture
90107
}
@@ -98,7 +115,7 @@ class BackgroundWorker(
98115

99116
if (isInDebug) {
100117
DebugHelper.postTaskCompleteNotification(
101-
ctx,
118+
applicationContext,
102119
randomThreadIdentifier,
103120
dartTask,
104121
payload,
@@ -115,11 +132,8 @@ class BackgroundWorker(
115132

116133
// If stopEngine is called from `onStopped`, it may not be from the main thread.
117134
Handler(Looper.getMainLooper()).post {
118-
if (!destroying) {
119-
if (this::engine.isInitialized)
120-
engine.destroy()
121-
destroying = true
122-
}
135+
engine?.destroy()
136+
engine = null
123137
}
124138
}
125139

@@ -134,7 +148,11 @@ class BackgroundWorker(
134148
stopEngine(Result.failure())
135149
}
136150

137-
override fun error(errorCode: String?, errorMessage: String?, errorDetails: Any?) {
151+
override fun error(
152+
errorCode: String?,
153+
errorMessage: String?,
154+
errorDetails: Any?
155+
) {
138156
Log.e(TAG, "errorCode: $errorCode, errorMessage: $errorMessage")
139157
stopEngine(Result.failure())
140158
}

example/android/gradle.properties

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
org.gradle.jvmargs=-Xmx1536M
22

33
android.useAndroidX=true
4-
android.enableJetifier=true
5-
android.enableR8=true
4+
android.enableJetifier=true

pubspec.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: workmanager
22
description: Flutter Workmanager. This plugin allows you to schedule background work on Android and iOS.
3-
version: 0.4.1
3+
version: 0.5.0-dev.1
44
homepage: https://github.com/fluttercommunity/flutter_workmanager
55
repository: https://github.com/fluttercommunity/flutter_workmanager
66
issue_tracker: https://github.com/fluttercommunity/flutter_workmanager/issues

0 commit comments

Comments
 (0)