1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "core/components_ng/pattern/waterflow/layout/water_flow_layout_algorithm_base.h"
17
18 #include "core/components_ng/pattern/waterflow/water_flow_pattern.h"
19
20 namespace OHOS::Ace::NG {
PreloadItems(LayoutWrapper * host,const RefPtr<WaterFlowLayoutInfoBase> & info,int32_t cacheCount)21 void WaterFlowLayoutBase::PreloadItems(
22 LayoutWrapper* host, const RefPtr<WaterFlowLayoutInfoBase>& info, int32_t cacheCount)
23 {
24 if (cacheCount <= 0) {
25 return;
26 }
27 auto frameNode = host->GetHostNode();
28 CHECK_NULL_VOID(frameNode);
29 auto pattern = frameNode->GetPattern<WaterFlowPattern>();
30 CHECK_NULL_VOID(pattern);
31 const bool taskRegistered = !pattern->PreloadListEmpty();
32 pattern->SetPreloadList(GeneratePreloadList(info, host, cacheCount, false));
33 if (pattern->PreloadListEmpty()) {
34 return;
35 }
36
37 pattern->SetCacheLayoutAlgo(Claim(this));
38 if (taskRegistered) {
39 return;
40 }
41 PostIdleTask(frameNode);
42 }
43
SyncPreloadItems(LayoutWrapper * host,const RefPtr<WaterFlowLayoutInfoBase> & info,int32_t cacheCount)44 void WaterFlowLayoutBase::SyncPreloadItems(
45 LayoutWrapper* host, const RefPtr<WaterFlowLayoutInfoBase>& info, int32_t cacheCount)
46 {
47 auto list = GeneratePreloadList(info, host, cacheCount, true);
48 if (list.empty()) {
49 return;
50 }
51
52 StartCacheLayout();
53 for (auto&& item : list) {
54 SyncPreloadItem(host, item);
55 }
56 EndCacheLayout();
57 }
58
GeneratePreloadList(const RefPtr<WaterFlowLayoutInfoBase> & info,LayoutWrapper * host,int32_t cacheCount,bool force)59 std::list<int32_t> WaterFlowLayoutBase::GeneratePreloadList(
60 const RefPtr<WaterFlowLayoutInfoBase>& info, LayoutWrapper* host, int32_t cacheCount, bool force)
61 {
62 std::list<int32_t> preloadList;
63 const int32_t endBound = std::min(info->ItemCnt(host->GetTotalChildCount()) - 1, info->endIndex_ + cacheCount);
64 for (int32_t i = info->endIndex_ + 1; i <= endBound; ++i) {
65 if (force || !host->GetChildByIndex(info->NodeIdx(i), true)) {
66 preloadList.emplace_back(i);
67 }
68 }
69
70 const int32_t startBound = std::max(0, info->startIndex_ - cacheCount);
71 for (int32_t i = info->startIndex_ - 1; i >= startBound; --i) {
72 if (force || !host->GetChildByIndex(info->NodeIdx(i), true)) {
73 preloadList.emplace_back(i);
74 }
75 }
76 return preloadList;
77 }
78
PostIdleTask(const RefPtr<FrameNode> & frameNode)79 void WaterFlowLayoutBase::PostIdleTask(const RefPtr<FrameNode>& frameNode)
80 {
81 auto* context = frameNode->GetContext();
82 CHECK_NULL_VOID(context);
83 context->AddPredictTask([weak = WeakPtr(frameNode)](int64_t deadline, bool canUseLongPredictTask) {
84 auto host = weak.Upgrade();
85 CHECK_NULL_VOID(host);
86 auto pattern = host->GetPattern<WaterFlowPattern>();
87 CHECK_NULL_VOID(pattern);
88
89 auto&& algo = pattern->GetCacheLayoutAlgo();
90 CHECK_NULL_VOID(algo);
91 algo->StartCacheLayout();
92
93 bool needMarkDirty = false;
94 auto items = pattern->MovePreloadList();
95 for (auto it = items.begin(); it != items.end(); ++it) {
96 if (GetSysTimestamp() > deadline) {
97 pattern->SetPreloadList(std::list<int32_t>(it, items.end()));
98 PostIdleTask(host);
99 break;
100 }
101 ACE_SCOPED_TRACE("Preload FlowItem %d", *it);
102 ScopedLayout scope(host->GetContext());
103 needMarkDirty |= algo->PreloadItem(RawPtr(host), *it, deadline);
104 }
105 if (needMarkDirty) {
106 host->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
107 }
108 algo->EndCacheLayout();
109 });
110 }
111
GetUpdateIdx(LayoutWrapper * host,int32_t footerIdx)112 int32_t WaterFlowLayoutBase::GetUpdateIdx(LayoutWrapper* host, int32_t footerIdx)
113 {
114 int32_t updateIdx = host->GetHostNode()->GetChildrenUpdated();
115 if (updateIdx > 0 && footerIdx == 0) {
116 --updateIdx;
117 }
118 return updateIdx;
119 }
120 } // namespace OHOS::Ace::NG
121