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));
33 if (pattern->PreloadListEmpty()) {
34 return;
35 }
36
37 pattern->SetCacheLayoutAlgo(Claim(this));
38 if (taskRegistered) {
39 return;
40 }
41 PostIdleTask(frameNode);
42 }
43
GeneratePreloadList(const RefPtr<WaterFlowLayoutInfoBase> & info,LayoutWrapper * host,int32_t cacheCount)44 std::list<int32_t> WaterFlowLayoutBase::GeneratePreloadList(
45 const RefPtr<WaterFlowLayoutInfoBase>& info, LayoutWrapper* host, int32_t cacheCount)
46 {
47 std::list<int32_t> preloadList;
48 const int32_t endBound = std::min(info->ItemCnt(host->GetTotalChildCount()) - 1, info->endIndex_ + cacheCount);
49 for (int32_t i = info->endIndex_ + 1; i <= endBound; ++i) {
50 if (!host->GetChildByIndex(info->NodeIdx(i), true)) {
51 preloadList.emplace_back(i);
52 }
53 }
54
55 const int32_t startBound = std::max(0, info->startIndex_ - cacheCount);
56 for (int32_t i = info->FirstIdx() - 1; i >= startBound; --i) {
57 if (!host->GetChildByIndex(info->NodeIdx(i), true)) {
58 preloadList.emplace_back(i);
59 }
60 }
61 return preloadList;
62 }
63
PostIdleTask(const RefPtr<FrameNode> & frameNode)64 void WaterFlowLayoutBase::PostIdleTask(const RefPtr<FrameNode>& frameNode)
65 {
66 auto* context = frameNode->GetContext();
67 CHECK_NULL_VOID(context);
68 context->AddPredictTask([weak = WeakPtr(frameNode)](int64_t deadline, bool canUseLongPredictTask) {
69 auto host = weak.Upgrade();
70 CHECK_NULL_VOID(host);
71 auto pattern = host->GetPattern<WaterFlowPattern>();
72 CHECK_NULL_VOID(pattern);
73
74 auto&& algo = pattern->GetCacheLayoutAlgo();
75 CHECK_NULL_VOID(algo);
76 algo->StartCacheLayout();
77
78 bool needMarkDirty = false;
79 auto items = pattern->MovePreloadList();
80 for (auto it = items.begin(); it != items.end(); ++it) {
81 if (GetSysTimestamp() > deadline) {
82 pattern->SetPreloadList(std::list<int32_t>(it, items.end()));
83 PostIdleTask(host);
84 break;
85 }
86 ACE_SCOPED_TRACE("Preload FlowItem %d", *it);
87 ScopedLayout scope(host->GetContext());
88 needMarkDirty |= algo->AppendCacheItem(RawPtr(host), *it, deadline);
89 }
90 if (needMarkDirty) {
91 host->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
92 }
93 algo->EndCacheLayout();
94 });
95 }
96
GetUpdateIdx(LayoutWrapper * host,int32_t footerIdx)97 int32_t WaterFlowLayoutBase::GetUpdateIdx(LayoutWrapper* host, int32_t footerIdx)
98 {
99 int32_t updateIdx = host->GetHostNode()->GetChildrenUpdated();
100 if (updateIdx > 0 && footerIdx == 0) {
101 --updateIdx;
102 }
103 return updateIdx;
104 }
105 } // namespace OHOS::Ace::NG
106