@@ -28,34 +28,40 @@ import deckers.thibault.aves.utils.LogUtils
2828import io.flutter.embedding.engine.FlutterEngine
2929import io.flutter.plugin.common.MethodCall
3030import io.flutter.plugin.common.MethodChannel
31+ import kotlinx.coroutines.CancellableContinuation
32+ import kotlinx.coroutines.CancellationException
3133import kotlinx.coroutines.CoroutineScope
3234import kotlinx.coroutines.Dispatchers
3335import kotlinx.coroutines.SupervisorJob
3436import kotlinx.coroutines.launch
3537import kotlinx.coroutines.runBlocking
36- import kotlin .coroutines.Continuation
38+ import kotlinx .coroutines.suspendCancellableCoroutine
3739import kotlin.coroutines.resume
3840import kotlin.coroutines.resumeWithException
39- import kotlin.coroutines.suspendCoroutine
4041
4142class AnalysisWorker (context : Context , parameters : WorkerParameters ) : CoroutineWorker(context, parameters) {
4243 private val defaultScope = CoroutineScope (SupervisorJob () + Dispatchers .Default )
43- private var workCont: Continuation <Any ?>? = null
44+ private var workCont: CancellableContinuation <Any ?>? = null
4445 private var flutterEngine: FlutterEngine ? = null
4546 private var backgroundChannel: MethodChannel ? = null
4647
4748 override suspend fun doWork (): Result {
4849 Log .i(LOG_TAG , " Start analysis worker $id " )
49- defaultScope.launch {
50- // prevent ANR triggered by slow operations in main thread
51- createNotificationChannel()
52- setForeground(createForegroundInfo())
53- }.join()
54- suspendCoroutine { cont ->
55- workCont = cont
56- onStart()
50+ createNotificationChannel()
51+ val foregroundInfo = createForegroundInfo()
52+ if (! isStopped) {
53+ setForeground(foregroundInfo)
54+ suspendCancellableCoroutine { cont ->
55+ workCont = cont
56+ cont.invokeOnCancellation {
57+ Log .i(LOG_TAG , " Analysis worker got cancelled" )
58+ stopDartAnalysisService()
59+ workCont?.resumeWithException(CancellationException ())
60+ }
61+ onStart()
62+ }
63+ dispose()
5764 }
58- dispose()
5965 return Result .success()
6066 }
6167
@@ -81,17 +87,7 @@ class AnalysisWorker(context: Context, parameters: WorkerParameters) : Coroutine
8187
8288 val preferences = applicationContext.getSharedPreferences(SHARED_PREFERENCES_KEY , Context .MODE_PRIVATE )
8389 val entryIdStrings = preferences.getStringSet(PREF_ENTRY_IDS_KEY , null )
84-
85- runBlocking {
86- FlutterUtils .runOnUiThread {
87- backgroundChannel?.invokeMethod(
88- " start" , hashMapOf(
89- " entryIds" to entryIdStrings?.map { Integer .parseUnsignedInt(it) }?.toList(),
90- " force" to inputData.getBoolean(KEY_FORCE , false ),
91- )
92- )
93- }
94- }
90+ startDartAnalysisService(entryIdStrings)
9591 } catch (e: Exception ) {
9692 Log .e(LOG_TAG , " failed to initialize worker" , e)
9793 workCont?.resumeWithException(e)
@@ -126,6 +122,27 @@ class AnalysisWorker(context: Context, parameters: WorkerParameters) : Coroutine
126122 }
127123 }
128124
125+ private fun startDartAnalysisService (entryIdStrings : Set <String >? ) {
126+ runBlocking {
127+ FlutterUtils .runOnUiThread {
128+ backgroundChannel?.invokeMethod(
129+ " start" , hashMapOf(
130+ " entryIds" to entryIdStrings?.map { Integer .parseUnsignedInt(it) }?.toList(),
131+ " force" to inputData.getBoolean(KEY_FORCE , false ),
132+ )
133+ )
134+ }
135+ }
136+ }
137+
138+ private fun stopDartAnalysisService () {
139+ runBlocking {
140+ FlutterUtils .runOnUiThread {
141+ backgroundChannel?.invokeMethod(" stop" , null )
142+ }
143+ }
144+ }
145+
129146 private fun onMethodCall (call : MethodCall , result : MethodChannel .Result ) {
130147 when (call.method) {
131148 " initialized" -> {
@@ -136,7 +153,7 @@ class AnalysisWorker(context: Context, parameters: WorkerParameters) : Coroutine
136153 " updateNotification" -> defaultScope.launch { safeSuspend(call, result, ::updateNotification) }
137154
138155 " stop" -> {
139- workCont?.resume(null )
156+ workCont?.takeIf { it.isActive }?. resume(null )
140157 result.success(null )
141158 }
142159
0 commit comments