Skip to content

Commit

Permalink
fix: Fixed an issue with flutterEngine not being destroyed properly
Browse files Browse the repository at this point in the history
  • Loading branch information
Dev-hwang committed Oct 2, 2024
1 parent 7dd7203 commit fdcd6eb
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -71,31 +71,35 @@ class ForegroundTask(

override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
when (call.method) {
"start" -> callSafely { start() }
"start" -> start()
else -> result.notImplemented()
}
}

private fun start() {
val serviceAction = serviceStatus.action
val starter = if (serviceAction == ForegroundServiceAction.API_START ||
serviceAction == ForegroundServiceAction.API_RESTART ||
serviceAction == ForegroundServiceAction.API_UPDATE) {
FlutterForegroundTaskStarter.DEVELOPER
} else {
FlutterForegroundTaskStarter.SYSTEM
}
runIfNotDestroyed {
runIfCallbackHandleExists {
val serviceAction = serviceStatus.action
val starter = if (serviceAction == ForegroundServiceAction.API_START ||
serviceAction == ForegroundServiceAction.API_RESTART ||
serviceAction == ForegroundServiceAction.API_UPDATE) {
FlutterForegroundTaskStarter.DEVELOPER
} else {
FlutterForegroundTaskStarter.SYSTEM
}

backgroundChannel.invokeMethod(ACTION_TASK_START, starter.ordinal) {
callSafely { startRepeatTask() }
backgroundChannel.invokeMethod(ACTION_TASK_START, starter.ordinal) {
runIfNotDestroyed {
startRepeatTask()
}
}
taskLifecycleListener.onTaskStart(starter)
}
}

taskLifecycleListener.onTaskStart(starter)
}

private fun invokeTaskRepeatEvent() {
backgroundChannel.invokeMethod(ACTION_TASK_REPEAT_EVENT, null)

taskLifecycleListener.onTaskRepeatEvent()
}

Expand Down Expand Up @@ -134,35 +138,49 @@ class ForegroundTask(
}

fun invokeMethod(method: String, data: Any?) {
callSafely(onlyCheckDestroyed = true) {
runIfNotDestroyed {
backgroundChannel.invokeMethod(method, data)
}
}

fun update(taskEventAction: ForegroundTaskEventAction) {
callSafely {
this.taskEventAction = taskEventAction
startRepeatTask()
runIfNotDestroyed {
runIfCallbackHandleExists {
this.taskEventAction = taskEventAction
startRepeatTask()
}
}
}

fun destroy() {
callSafely(onlyCheckDestroyed = true) {
runIfNotDestroyed {
stopRepeatTask()

backgroundChannel.setMethodCallHandler(null)
backgroundChannel.invokeMethod(ACTION_TASK_DESTROY, null) {
if (taskData.callbackHandle == null) {
taskLifecycleListener.onEngineWillDestroy()
flutterEngine.destroy()
} else {
backgroundChannel.invokeMethod(ACTION_TASK_DESTROY, null) {
flutterEngine.destroy()
}
taskLifecycleListener.onTaskDestroy()
taskLifecycleListener.onEngineWillDestroy()
}

taskLifecycleListener.onTaskDestroy()
taskLifecycleListener.onEngineWillDestroy()
isDestroyed = true
}
}

private fun callSafely(onlyCheckDestroyed: Boolean = false, call: () -> Unit = {}) {
if (isDestroyed || (!onlyCheckDestroyed && taskData.callbackHandle == null)) {
private fun runIfCallbackHandleExists(call: () -> Unit) {
if (taskData.callbackHandle == null) {
return
}
call()
}

private fun runIfNotDestroyed(call: () -> Unit) {
if (isDestroyed) {
return
}
call()
Expand Down
71 changes: 45 additions & 26 deletions ios/Classes/service/ForegroundTask.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,31 +72,35 @@ class ForegroundTask {
func onMethodCall(call: FlutterMethodCall, result: @escaping FlutterResult) {
switch call.method {
case "start":
callSafely { start() }
start()
default:
result(FlutterMethodNotImplemented)
}
}

private func start() {
let serviceAction = serviceStatus.action
let starter: FlutterForegroundTaskStarter
if serviceAction == .API_START || serviceAction == .API_RESTART || serviceAction == .API_UPDATE {
starter = .DEVELOPER
} else {
starter = .SYSTEM
}

backgroundChannel?.invokeMethod(ACTION_TASK_START, arguments: starter.rawValue) { _ in
self.callSafely { self.startRepeatTask() }
runIfNotDestroyed {
runIfCallbackHandleExists {
let serviceAction = serviceStatus.action
let starter: FlutterForegroundTaskStarter
if serviceAction == .API_START || serviceAction == .API_RESTART || serviceAction == .API_UPDATE {
starter = .DEVELOPER
} else {
starter = .SYSTEM
}

backgroundChannel?.invokeMethod(ACTION_TASK_START, arguments: starter.rawValue) { _ in
self.runIfNotDestroyed {
self.startRepeatTask()
}
}
taskLifecycleListener.onTaskStart(starter: starter)
}
}

taskLifecycleListener.onTaskStart(starter: starter)
}

private func invokeTaskRepeatEvent() {
backgroundChannel?.invokeMethod(ACTION_TASK_REPEAT_EVENT, arguments: nil)

taskLifecycleListener.onTaskRepeatEvent()
}

Expand Down Expand Up @@ -126,36 +130,51 @@ class ForegroundTask {
}

func invokeMethod(_ method: String, arguments: Any?) {
callSafely(onlyCheckDestroyed: true) {
runIfNotDestroyed {
backgroundChannel?.invokeMethod(method, arguments: arguments)
}
}

func update(taskEventAction: ForegroundTaskEventAction) {
callSafely {
self.taskEventAction = taskEventAction
startRepeatTask()
runIfNotDestroyed {
runIfCallbackHandleExists {
self.taskEventAction = taskEventAction
startRepeatTask()
}
}
}

func destroy() {
callSafely(onlyCheckDestroyed: true) {
runIfNotDestroyed {
stopRepeatTask()

backgroundChannel?.setMethodCallHandler(nil)
backgroundChannel?.invokeMethod(ACTION_TASK_DESTROY, arguments: nil) { _ in
self.flutterEngine?.destroyContext()
self.flutterEngine = nil
if taskData.callbackHandle == nil {
taskLifecycleListener.onEngineWillDestroy()
flutterEngine?.destroyContext()
flutterEngine = nil
} else {
backgroundChannel?.invokeMethod(ACTION_TASK_DESTROY, arguments: nil) { _ in
self.flutterEngine?.destroyContext()
self.flutterEngine = nil
}
taskLifecycleListener.onTaskDestroy()
taskLifecycleListener.onEngineWillDestroy()
}

taskLifecycleListener.onTaskDestroy()
taskLifecycleListener.onEngineWillDestroy()
isDestroyed = true
}
}

private func callSafely(onlyCheckDestroyed: Bool = false, call: () -> Void = {}) {
if isDestroyed || (!onlyCheckDestroyed && taskData.callbackHandle == nil) {
private func runIfCallbackHandleExists(call: () -> Void) {
if taskData.callbackHandle == nil {
return
}
call()
}

private func runIfNotDestroyed(call: () -> Void) {
if isDestroyed {
return
}
call()
Expand Down

0 comments on commit fdcd6eb

Please sign in to comment.