修复目标达成弹窗死机 3223/1 3223/head 3226/target/1
authorCaisking <Casiking@zhihuishixun.com>
Fri, 27 Feb 2026 07:57:40 +0000 (15:57 +0800)
committerCaisking <Casiking@zhihuishixun.com>
Fri, 27 Feb 2026 07:57:40 +0000 (15:57 +0800)
code/sdk/application/wearable/fd272/service/msg_center/src/notify/goal_notification.cpp

index d23a0f1..122be79 100644 (file)
@@ -19,6 +19,7 @@
 #include "goal_notification.h"
 #include "ui_resource_string.h"
 #include "traing/Training_UiConfig.h"
+#include "graphic_service.h"
 
 #include "ConfigModel.h"
 #include "uicomponents/UIComponents.h"
@@ -38,12 +39,13 @@ namespace OHOS
 
 #define BUTTONWINOK "buttom_win"
 
-    /* 与运动目标达成弹窗一致的动画参数 */
+    /* 与运动目标达成弹窗一致的动画参数(与充电动画创建方式一致:路径 + CreateImageInfoArray) */
     static constexpr uint16_t GOAL_WIN_IMAGE_POS_X = 173;
     static constexpr uint16_t GOAL_WIN_IMAGE_POS_Y = 100;
     static constexpr uint16_t GOAL_WIN_IMAGE_SIZE = 120;
     static constexpr uint16_t GOAL_WIN_ANIMATOR_FRAMES = 94;
     static constexpr uint16_t GOAL_WIN_ANIMATOR_SPEED = 30;
+    static constexpr const char *GoalWinAnimationPaths = "/user/res/Training/training_GIF/win/";
 
     static UIScrollView *getView{nullptr};
 
@@ -55,10 +57,9 @@ namespace OHOS
     static UILabelExt *labelpre = nullptr;
     static UILabelButtonExt *buttonok_ = nullptr;
     static UIImageAnimatorView *imageAnimator{nullptr};
-    /* 与运动目标达成弹窗相同的静态动画资源(文件路径 + ImageAnimatorInfo) */
-    static char g_goalWinPaths[GOAL_WIN_ANIMATOR_FRAMES][64];
-    static ImageAnimatorInfo g_goalWinAnimatorInfo[GOAL_WIN_ANIMATOR_FRAMES];
-    static bool g_goalWinAnimatorInfoInited = false;
+    /* 与充电动画一致:CreateImageInfoArray + ImageAnimatorInfo 数组 */
+    static const ImageInfo **GoalAnimationInfoArray{nullptr};
+    static ImageAnimatorInfo GoalAnimationInfo[GOAL_WIN_ANIMATOR_FRAMES];
 
     static osTimerId_t GoalviewShow_timer = NULL;
 
@@ -98,6 +99,11 @@ namespace OHOS
                 delete imageAnimator;
                 imageAnimator = nullptr;
             }
+            if (GoalAnimationInfoArray)
+            {
+                FreeImageInfoArray(GoalAnimationInfoArray, GoalWinAnimationPaths, GOAL_WIN_ANIMATOR_FRAMES);
+                GoalAnimationInfoArray = nullptr;
+            }
             // if (image_goalview)
             // {
             //     delete image_goalview;
@@ -285,38 +291,47 @@ namespace OHOS
         InitLabel(labeltag, 70, 215, 326, 97, "label2", tagString.c_str(),DEFAULT_VECTOR_FONT_FILENAME, 80);
         labeltag->SetTextColor(Color::GetColorFromRGBA(0x4f, 0xc3, 0x4c, 0xff));
         labeltag->SetLineBreakMode(UILabel::LINE_BREAK_OSCILLATION);
-        /* 与运动目标达成弹窗相同的动画绘制:静态 ImageAnimatorInfo + SetImageAnimatorSrc */
-        if (!g_goalWinAnimatorInfoInited)
-        {
-            for (int i = 0; i < GOAL_WIN_ANIMATOR_FRAMES; i++)
-            {
-                snprintf(g_goalWinPaths[i], sizeof(g_goalWinPaths[i]),
-                         "/user/res/Training/training_GIF/win/%d.bin", i + 1);
-                g_goalWinAnimatorInfo[i].imagePath = g_goalWinPaths[i];
-                g_goalWinAnimatorInfo[i].pos.x = GOAL_WIN_IMAGE_POS_X;
-                g_goalWinAnimatorInfo[i].pos.y = GOAL_WIN_IMAGE_POS_Y;
-                g_goalWinAnimatorInfo[i].width = GOAL_WIN_IMAGE_SIZE;
-                g_goalWinAnimatorInfo[i].height = GOAL_WIN_IMAGE_SIZE;
-                g_goalWinAnimatorInfo[i].imageType = IMG_SRC_FILE_PATH;
-            }
-            g_goalWinAnimatorInfoInited = true;
-        }
+        /* 与充电动画一致的创建方式:CreateImageInfoArray + ImageAnimatorInfo(IMG_SRC_IMAGE_INFO) + SetPosition/SetImageAnimatorSrc */
         if (imageAnimator == nullptr)
         {
             imageAnimator = new UIImageAnimatorView();
         }
-        if (imageAnimator != nullptr)
+        if (GoalAnimationInfoArray == nullptr)
+        {
+            GoalAnimationInfoArray = CreateImageInfoArray(GoalWinAnimationPaths, GOAL_WIN_ANIMATOR_FRAMES);
+        }
+        if (GoalAnimationInfoArray != nullptr && imageAnimator != nullptr)
         {
-            imageAnimator->SetImageAnimatorSrc(g_goalWinAnimatorInfo,
+            for (uint8_t i = 0; i < GOAL_WIN_ANIMATOR_FRAMES; i++)
+            {
+                GoalAnimationInfo[i].imageInfo = GoalAnimationInfoArray[i];
+                GoalAnimationInfo[i].imageType = IMG_SRC_IMAGE_INFO;
+                GoalAnimationInfo[i].pos.x = GOAL_WIN_IMAGE_POS_X;
+                GoalAnimationInfo[i].pos.y = GOAL_WIN_IMAGE_POS_Y;
+                GoalAnimationInfo[i].width = GOAL_WIN_IMAGE_SIZE;
+                GoalAnimationInfo[i].height = GOAL_WIN_IMAGE_SIZE;
+            }
+            imageAnimator->SetPosition(GOAL_WIN_IMAGE_POS_X, GOAL_WIN_IMAGE_POS_Y,
+                                      GOAL_WIN_IMAGE_SIZE, GOAL_WIN_IMAGE_SIZE);
+            imageAnimator->SetStyle(STYLE_BACKGROUND_OPA, 0x00);
+            imageAnimator->SetImageAnimatorSrc(GoalAnimationInfo,
                                               GOAL_WIN_ANIMATOR_FRAMES,
                                               GOAL_WIN_ANIMATOR_SPEED);
             imageAnimator->SetRepeat(true);
+            imageAnimator->SetRepeatTimes(0);
+            imageAnimator->SetResizeMode(UIImageView::COVER);
             imageAnimator->Start();
         }
     }
 
     static uint8_t GoalviewShowCallBack_FALG = 0;
 
+    static void GoalviewShowStopNotifyProc(int data)
+    {
+        (void)data;
+        NotificationManager::GetInstance()->StopNotify();
+    }
+
     static void GoalviewShowCallBack(int data)
     {
         GoalviewShowCallBack_FALG--;
@@ -331,7 +346,14 @@ namespace OHOS
         }
         if (GoalviewShowCallBack_FALG == 0)
         {
-            NotificationManager::GetInstance()->StopNotify();
+            /* 避免在定时器回调里直接 StopNotify:会触发 Freegoalview 并 osTimerDelete 当前定时器,易导致死机/崩溃。
+             * 先投递到图形线程执行 StopNotify,回调返回后再在 Freegoalview 中安全删除定时器。 */
+            if (GoalviewShow_timer != nullptr)
+            {
+                osTimerStop(GoalviewShow_timer);
+            }
+            GraphicService::GetInstance()->PostGraphicEvent(
+                std::bind(GoalviewShowStopNotifyProc, 0));
         }
     }