1.为什么领取奖励逻辑在 SubView,而充值任务逻辑在 MainView?
FirstCharge_SubView 是整个首充功能的外层容器,负责管理所有首充二级页签、当前选中状态、子页面创建和红点,因此它监听 GET_TASK_REWARD 并处理的并不是“如何领取奖励”,而是奖励领取成功后的全局刷新:保留当前页签,重新读取首充任务和配置数据,重建页签状态及当前内容页,并更新相关红点;真正的充值和领奖业务则放在 FirstCharge_MainView 及奖励 Cell 中,因为它们持有当前页签的任务数组和具体 UI 控件,负责判断充值任务是否完成、切换“充值/奖励已解锁”状态、响应充值按钮、展示每条任务对应的奖励以及发起领奖请求。简单来说,MainView 负责当前页签内部“如何充值、如何展示和领取奖励”,SubView 负责领奖成功后“如何让整个首充模块的页签、页面和红点保持同步”
FirstCharge_SubView
├─ 构建左侧页签
├─ 选择当前页签
└─ 创建当前内容页
├─ FirstCharge_MainView
└─ FirstChagre_SixCharge_SubVIew
FirstCharge_SubView:
#一、整体职责
这份代码主要完成5件事:
请求首充任务数据;
读取首充配置 Map 和任务 Map;
根据配置生成左侧二级页签;
决定默认选中哪个页签;
根据当前页签动态创建对应的内容子页面。
1 2 3 4 5 6
| FirstCharge_SubView ├─ 左侧页签:w_list_GiftTag └─ 内容插槽:w_nameSlot_SubView ├─ 普通首充页面 └─ SixCharge师徒页面
|
我按照四个部分的调用链进行拆解
第一个部分页面被打开的初始化OnOpen()
第二个部分用户切换页签触发的事件OnSecondTabChanged
第三个部分用户领取完奖励触发的事件OnReqNewData
第四个部分首充奖励返回OnFirstChargeInfoReady
四条调用链对比
| 调用链 |
触发来源 |
重新读取Model |
重建页签 |
重建内容页 |
保留当前页签 |
| OnOpen |
页面打开 |
是 |
是 |
是 |
首次通常没有 |
| OnSecondTabChanged |
用户点击页签 |
否 |
否,只更新选中 |
是 |
切到指定页签 |
| OnReqNewData |
领取任务奖励 |
是 |
是 |
是 |
是 |
| OnFirstChargeInfoReady |
首充数据返回 |
是 |
是 |
是 |
有则保留 |
OnOpen调用链:界面打开开始按顺序执行,创建页面(默认的界面)并且读取配置数据同时初始化ItemTab
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| OnOpen(Data) ├─ 保存外部参数 ├─ OnInitializedEvent() ├─ InitData() ├─ InitEvent() └─ InitUI() ├─ ReqFirstChargeTaskInfo() └─ RefreshFirstChargeUI() ├─ InitTaskData() ├─ 校验任务Map ├─ 校验配置Map ├─ InitSecondTabUI() │ ├─ 清空旧状态 │ ├─ BuildSecondTabListData() --将获取的数据读取到并且存入到本地表中,方便使用 │ ├─ SetSelectedSecondId() --选择默认页签,默认是第一个 │ ├─ 更新页签选中状态 │ └─ 刷新左侧页签ListView ├─ SwitchSubView() │ ├─ 删除旧子页面,传入角色预览等 │ ├─ 查找蓝图/Lua路径 │ └─ 创建当前内容子页面 └─ 更新首充红点
|
OnSecondTabChanged调用链:点击切换Item,清楚就Widget,切换新界面,并且执行新界面的OnOpen调用链
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 用户点击左侧页签 → 派发SecondTabChanged(secondTagId) → OnSecondTabChanged(secondTagId) ├─ 检查ID ├─ 从TagInfoMap查找页签 ├─ 判断是否重复点击 ├─ 更新SelectedSecondId ├─ 更新CurTabInfo ├─ 更新所有页签isSelected ├─ 刷新左侧页签ListView └─ SwitchSubView() ├─ 删除旧内容页 └─ 创建新内容页
|
OnReqNewData调用链:任务奖励领取成功后调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| 用户领取首充奖励 → 服务端返回任务奖励结果 → 派发GET_TASK_REWARD → OnReqNewData() ├─ 记录当前页签ID └─ RefreshFirstChargeUI(selectedId) ├─ InitTaskData()重新读取任务Map和配置Map ├─ 校验任务Map ├─ 校验配置Map ├─ InitSecondTabUI()重建左侧页签数据 │ ├─ 清空旧状态 │ ├─ BuildSecondTabListData() │ ├─ SetSelectedSecondId() │ ├─ 更新页签选中状态 │ └─ 刷新左侧页签ListView ├─ SwitchSubView() │ ├─ 删除旧子页面,传入角色预览等 │ ├─ 查找蓝图/Lua路径 │ └─ 创建当前内容子页面 └─ 更新首充红点
|
OnFirstChargeInfoReady调用链:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| OnOpen → ReqFirstChargeTaskInfo() → 服务端返回首充数据 → FirstChargeModel整理配置和任务Map → 派发GET_FIRST_CHARGE_INFO → OnFirstChargeInfoReady() └─ RefreshFirstChargeUI(SelectedSecondId) ├─ 重新读取任务Map ├─ 重新读取配置Map ├─ 校验数据 ├─ InitSecondTabUI()重建左侧页签数据 │ ├─ 清空旧状态 │ ├─ BuildSecondTabListData() │ ├─ SetSelectedSecondId() │ ├─ 更新页签选中状态 │ └─ 刷新左侧页签ListView ├─ SwitchSubView() │ ├─ 删除旧子页面,传入角色预览等 │ ├─ 查找蓝图/Lua路径 │ └─ 创建当前内容子页面 └─ 更新首充红点
|
FirstCharge_TabItem
FirstCharge_TabItem.lua 是 FirstCharge_SubView 左侧二级页签 ListView 中的单个页签 Cell,负责接收一个 tagInfo、显示页签图标/名称/红点/选中效果,并在用户点击时把当前页签 ID 通过事件传回外层 FirstCharge_SubView。它不负责创建内容页面,也不负责处理首充任务或奖励。ListView Cell:只负责单条页签数据的显示和点击事件,不管理整个页签列表。
OnOpen调用链:这是每个页签 Cell 被 ListView 创建时执行的初始化入口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| FirstCharge_SubView构造页签数据 → ListSetDatas(w_list_GiftTag, SubTabDataList) → ListView创建FirstCharge_TabItem → FirstCharge_TabItem:OnOpen(tagInfo) ├─ 保存tagInfo ├─ OnInitializedEvent() │ └─ 绑定页签按钮 ├─ InitData() │ ├─ 取得页签ID │ ├─ 取得页签名称 │ └─ 取得选中状态 ├─ InitEvent() └─ InitUI() └─ RefreshUI() ├─ 设置页签图标 ├─ 设置图标显隐 ├─ 设置页签名称 ├─ 设置选中效果 └─ 初始化红点
|
FirstCharge_SixCharge_SubView
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| 1.FirstCharge_SubView:SwitchSubView(): self.CurSubView = self:AddWidgetAndLua(assetPath,luaPath,self.bp.w_nameSlot_SubView,self.CurTabInfo) 2.调用继承的父类的Open,其中SixCharge 重写了OnInitializedEvent(),实际是自己的按钮绑定 3.执行父类InitUI,包含InitTaskData,InitItemUI,InitListUI,SetRechargeBtnVisibility,InitModelUI 4.提取当前的页签数据InitTaskData self.FirstChargeDataMap = self.Data.firstChargeData self.FirstChargeConfigData = self.Data.firstChargeConfigData 5.动态调用SixCharge的InitListUI,重写了父类的逻辑,所以走自己的逻辑 6.构造UI数据并判断首充状态 遍历任务数组for i = 1, count do local taskData = self.FirstChargeDataMap[i] 判断任务是否完成 7.填充列表
完整流程: 打开 SixCharge 页面后,执行继承自 FirstCharge_MainView 的 OnOpen 和初始化流程。 父类 InitUI 从页签参数中取得当前首充配置对应的任务数组,然后动态调用 SixCharge 重写的 InitListUI。 SixCharge 根据任务数量选择三日分组布局或普通列表布局,遍历任务数组构造 ListView UI 数据,同时根据任务状态判断是否显示充值按钮。 三日布局再按照 2/4/2 拆分 UI 数据,并分别填充三个 ListView。 每个奖励 Cell 最后从对应任务对象的 GetTaskRewards() 中取得奖励内容并展示。
|
FirstChagre_MainView
FirstCharge_MainView 接收到的是当前页签的 CurTabInfo,包含id = 当前首充配置ID,firstChargeData = 当前配置对应的任务数组,firstChargeConfigData = 当前首充配置,previewActor = 3D预览角色。
OnOpen调用链:首充包含2个界面,默认是这个界面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| FirstCharge_MainView:OnOpen(Data) ├─ 保存外层传入的当前页签数据 ├─ OnInitializedEvent() ├─ InitData() ├─ InitEvent() └─ InitUI() ├─ InitTaskData() ├─ InitItemUI() ├─ InitListUI() │ ├─ InitListData() │ ├─ 判断是否已完成充值任务 │ └─ 填充奖励ListView ├─ SetRechargeBtnVisibility() └─ InitModelUI() └─ SetModelAnim()
|
OnReceiveSameValueRewards调用链:在用户点击领取奖励时调用(说明首充的充值任务已经完成),用户点击奖励,传入taskValue代表奖励挡位,同时遍历任务列表3重条件进行检查是否完成,然后执行领取。点击一个奖励,批量全部领取
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 奖励Item:OnClickedBtnGetReward() ├─ 获取任务条件目标值TaskValue └─ 派发FirstChargeModel_ReceiveSameValueRewards ↓ FirstCharge_MainView:OnReceiveSameValueRewards(TaskValue) ├─ 遍历当前页签任务数组 ├─ 查找相同TaskValue的任务 ├─ 筛选已经完成、可以领取的任务 └─ TaskSystemModel:ReqGetTaskRewards(TaskIdList) ↓ 服务端返回领取结果 └─ FirstCharge_SubView:OnReqNewData()
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| TaskSystem派发TASK_INFO_MAP_UPDATE_NOTICE ├─ FirstCharge_MainView:OnUpdateTaskInfo() │ ├─ 检查当前页签是否有任务变化 │ └─ 更新首充页签和充值入口红点 │ └─ 奖励Item:RefreshRewardItem() ├─ 刷新奖励领取状态 └─ 派发FirstChargeModel_RefreshReward ↓ FirstCharge_MainView:RefreshRechargeBtnVisibility() ├─ IsShowRechargeBtn = false └─ SetRechargeBtnVisibility()
|
1 2 3 4 5 6 7 8 9 10 11 12
| 头像弹窗关闭 └─ 派发ON_CLOSE_WINDOW_IMMEDIATELY(WndName) ↓ FirstCharge_MainView:OnCloseWindowImmediately(WndName) ├─ 判断是否为头像相关弹窗 └─ SetModelAnim() ├─ RefreshPreviewUI() │ ├─ 恢复首充套装 │ └─ 恢复Camera_Recharge相机 ├─ ClearAnimTimer() └─ 根据配置恢复角色动画
|
本文从 LearnByCompany 原始文档 自动同步。