diff --git a/frameworks/src/core/base/async_task_manager.cpp b/frameworks/src/core/base/async_task_manager.cpp index 5d4edf4..09b95e3 100755 --- a/frameworks/src/core/base/async_task_manager.cpp +++ b/frameworks/src/core/base/async_task_manager.cpp @@ -108,7 +108,7 @@ void AsyncTaskManager::Callback() } } -uint16_t AsyncTaskManager::Dispatch(AsyncTaskHandler handler, void *data) +uint16_t AsyncTaskManager::Dispatch(AsyncTaskHandler handler, void *data, const void *context) { if (handler == nullptr) { HILOG_ERROR(HILOG_MODULE_ACE, "AsyncTaskManager::Dispatch failed: handler is null."); @@ -128,6 +128,7 @@ uint16_t AsyncTaskManager::Dispatch(AsyncTaskHandler handler, void *data) task->handler = handler; task->data = data; task->id = (++uniqueTaskID_); + task->context = context; task->next = nullptr; if (head_ == nullptr) { head_ = task; @@ -169,6 +170,37 @@ void AsyncTaskManager::Cancel(uint16_t taskID) TRY_UNLOCK(); } +void AsyncTaskManager::CancelWithContext(const void *context) +{ + if (context == nullptr) { + HILOG_ERROR(HILOG_MODULE_ACE, "AsyncTaskManager::CancelWithContext failed: null context."); + return; + } + TRY_LOCK(); + AsyncTask *node = head_; + AsyncTask *prev = nullptr; + AsyncTask *next = nullptr; + while (node != nullptr) { + next = node->next; + if (node->context == context) { + if (prev == nullptr) { + head_ = head_->next; + } else { + prev->next = next; + } + if (node == tail_) { + tail_ = prev; + } + delete node; + node = next; + continue; + } + prev = node; + node = next; + } + TRY_UNLOCK(); +} + void AsyncTaskManager::SetFront(bool front) { front_ = front; diff --git a/frameworks/src/core/base/async_task_manager.h b/frameworks/src/core/base/async_task_manager.h index b40e35a..1207302 100755 --- a/frameworks/src/core/base/async_task_manager.h +++ b/frameworks/src/core/base/async_task_manager.h @@ -32,6 +32,7 @@ using AsyncTaskHandler = void (*)(void *); struct AsyncTask final : public MemoryHeap { uint16_t id; + const void *context; AsyncTaskHandler handler; void *data; AsyncTask *next; @@ -49,10 +50,12 @@ public: virtual void Callback() override; - uint16_t Dispatch(AsyncTaskHandler handler, void *data); + uint16_t Dispatch(AsyncTaskHandler handler, void *data, const void *context = nullptr); void Cancel(uint16_t taskID); + void CancelWithContext(const void *context); + void SetFront(bool front); private: @@ -73,4 +76,4 @@ private: }; } // namespace ACELite } // namespace OHOS -#endif \ No newline at end of file +#endif diff --git a/frameworks/src/core/base/event_util.cpp b/frameworks/src/core/base/event_util.cpp index 3da9381..9c0eed6 100755 --- a/frameworks/src/core/base/event_util.cpp +++ b/frameworks/src/core/base/event_util.cpp @@ -109,7 +109,7 @@ JSValue EventUtil::CreateSwipeEvent(UIView &view, const DragEvent &event) } return arg; } -void EventUtil::InvokeCallback(JSValue vm, JSValue callback, JSValue event) +void EventUtil::InvokeCallback(JSValue vm, JSValue callback, JSValue event, const void *context) { auto *params = new CallbackParams(); if (params == nullptr) { @@ -121,7 +121,8 @@ void EventUtil::InvokeCallback(JSValue vm, JSValue callback, JSValue event) params->arg = event; // The views may be destroyed or recreated in conditional or list rendering. // If we directly call the event callback function, the program will crash. - if (DISPATCH_FAILURE == AsyncTaskManager::GetInstance().Dispatch(CallbackExecutor, static_cast(params))) { + if (DISPATCH_FAILURE == + AsyncTaskManager::GetInstance().Dispatch(CallbackExecutor, static_cast(params), context)) { HILOG_ERROR(HILOG_MODULE_ACE, "EventUtil::InvokeCallback failed: Async task dispatch failure."); delete params; params = nullptr; diff --git a/frameworks/src/core/base/event_util.h b/frameworks/src/core/base/event_util.h index e4fa6d0..086ca75 100755 --- a/frameworks/src/core/base/event_util.h +++ b/frameworks/src/core/base/event_util.h @@ -46,7 +46,7 @@ public: /** * @brief Invoke the callback function of event. */ - static void InvokeCallback(JSValue vm, JSValue callback, JSValue event); + static void InvokeCallback(JSValue vm, JSValue callback, JSValue event, const void *context = nullptr); static const char *EVENT_CLICK; static const char *EVENT_LONGPRESS; diff --git a/frameworks/src/core/components/event_listener.cpp b/frameworks/src/core/components/event_listener.cpp index fb8b080..9348f80 100755 --- a/frameworks/src/core/components/event_listener.cpp +++ b/frameworks/src/core/components/event_listener.cpp @@ -146,7 +146,7 @@ bool ViewOnSwipeListener::OnDragEnd(UIView& view, const DragEvent &event) HILOG_DEBUG(HILOG_MODULE_ACE, "OnDragEnd received"); JSValue arg = EventUtil::CreateSwipeEvent(view, event); - EventUtil::InvokeCallback(JSUndefined::Create(), fn_, arg); + EventUtil::InvokeCallback(JSUndefined::Create(), fn_, arg, this); return isStopPropagation_; } diff --git a/frameworks/src/core/components/event_listener.h b/frameworks/src/core/components/event_listener.h index 124b8f7..ae91634 100755 --- a/frameworks/src/core/components/event_listener.h +++ b/frameworks/src/core/components/event_listener.h @@ -17,6 +17,7 @@ #define OHOS_ACELITE_EVENT_LISTENER_H #include "ace_log.h" +#include "async_task_manager.h" #include "event_util.h" #include "js_fwk_common.h" #include "keys.h" @@ -93,6 +94,7 @@ public: ~ViewOnClickListener() { + AsyncTaskManager::GetInstance().CancelWithContext(this); jerry_release_value(fn_); } @@ -106,7 +108,7 @@ public: return isStopPropagation_; } JSValue arg = EventUtil::CreateEvent(EventUtil::EVENT_CLICK, view, event); - EventUtil::InvokeCallback(JSUndefined::Create(), fn_, arg); + EventUtil::InvokeCallback(JSUndefined::Create(), fn_, arg, this); return isStopPropagation_; } @@ -130,6 +132,7 @@ public: ~ViewOnLongPressListener() { + AsyncTaskManager::GetInstance().CancelWithContext(this); jerry_release_value(fn_); } @@ -140,7 +143,7 @@ public: } JSValue arg = EventUtil::CreateEvent(EventUtil::EVENT_LONGPRESS, view, event); - EventUtil::InvokeCallback(JSUndefined::Create(), fn_, arg); + EventUtil::InvokeCallback(JSUndefined::Create(), fn_, arg, this); return isStopPropagation_; } @@ -220,6 +223,7 @@ public: ~ViewOnSwipeListener() { + AsyncTaskManager::GetInstance().CancelWithContext(this); jerry_release_value(fn_); }