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 "bridge/cj_frontend/cppview/lazy_foreach.h"
17
18 #include <functional>
19 #include <set>
20 #include <string>
21
22 #include "base/utils/utils.h"
23 #include "bridge/cj_frontend/cppview/data_change_listener.h"
24 #include "bridge/cj_frontend/cppview/native_view.h"
25 #include "core/common/container_scope.h"
26 #include "core/components_v2/foreach/lazy_foreach_component.h"
27 #include "core/components_ng/base/view_stack_model.h"
28
29 using namespace OHOS::Ace;
30 using namespace OHOS::FFI;
31 using namespace OHOS::Ace::Framework;
32
33 namespace OHOS::Ace::Framework {
34
OnExpandChildrenOnInitialInNG()35 void CJLazyForEachBuilder::OnExpandChildrenOnInitialInNG()
36 {
37 auto totalIndex = cjBuilder_->GetTotalCount();
38 for (auto index = 0; index < totalIndex; index++) {
39 auto key = cjBuilder_->GenerateKey(index);
40 ViewStackModel::GetInstance()->PushKey(key);
41 cjBuilder_->GenerateItem(index);
42 ViewStackModel::GetInstance()->PopKey();
43 }
44 }
45
OnGetChildByIndex(int32_t index,std::unordered_map<std::string,std::pair<int32_t,RefPtr<NG::UINode>>> & cachedItems)46 std::pair<std::string, RefPtr<NG::UINode>> CJLazyForEachBuilder::OnGetChildByIndex(
47 int32_t index, std::unordered_map<std::string, std::pair<int32_t, RefPtr<NG::UINode>>>& cachedItems)
48 {
49 std::pair<std::string, RefPtr<NG::UINode>> result;
50 auto key = cjBuilder_->GenerateKey(index);
51 auto cachedIter = cachedItems.find(key);
52 if (cachedIter != cachedItems.end()) {
53 result.first = key;
54 result.second = cachedIter->second.second;
55 return result;
56 }
57 NG::ScopedViewStackProcessor scopedViewStackProcessor;
58 auto* viewStack = ViewStackModel::GetInstance();
59 cjBuilder_->MarkLazyForEachProcess(key);
60 viewStack->PushKey(key);
61 cjBuilder_->GenerateItem(index);
62 viewStack->PopKey();
63 cjBuilder_->ResetLazyForEachProcess();
64 result.first = key;
65 auto view = ViewStackModel::GetInstance()->Finish();
66 result.second = AceType::DynamicCast<NG::UINode>(view);
67
68 return result;
69 }
70
OnGetChildByIndexNew(int32_t index,std::map<int32_t,NG::LazyForEachChild> & cachedItems,std::unordered_map<std::string,NG::LazyForEachCacheChild> & expiringItems)71 std::pair<std::string, RefPtr<NG::UINode>> CJLazyForEachBuilder::OnGetChildByIndexNew(int32_t index,
72 std::map<int32_t, NG::LazyForEachChild>& cachedItems,
73 std::unordered_map<std::string, NG::LazyForEachCacheChild>& expiringItems)
74 {
75 std::pair<std::string, RefPtr<NG::UINode>> result;
76 auto key = cjBuilder_->GenerateKey(index);
77 auto cachedIter = cachedItems.find(index);
78 if (cachedIter != cachedItems.end()) {
79 result.first = key;
80 result.second = cachedIter->second.second;
81 return result;
82 }
83 auto expiringIter = expiringItems.find(key);
84 if (expiringIter != expiringItems.end()) {
85 result.first = key;
86 result.second = expiringIter->second.second;
87 expiringItems.erase(expiringIter);
88 return result;
89 }
90 NG::ScopedViewStackProcessor scopedViewStackProcessor;
91 auto* viewStack = ViewStackModel::GetInstance();
92 cjBuilder_->MarkLazyForEachProcess(key);
93 viewStack->PushKey(key);
94 cjBuilder_->GenerateItem(index);
95 viewStack->PopKey();
96 cjBuilder_->ResetLazyForEachProcess();
97 result.first = key;
98 auto view = ViewStackModel::GetInstance()->Finish();
99 result.second = AceType::DynamicCast<NG::UINode>(view);
100
101 return result;
102 }
103
ReleaseChildGroupById(const std::string & id)104 void CJLazyForEachBuilder::ReleaseChildGroupById(const std::string& id)
105 {
106 cjBuilder_->RemoveChildGroupById(id);
107 }
108
RegisterDataChangeListener(const RefPtr<V2::DataChangeListener> & listener)109 void CJLazyForEachBuilder::RegisterDataChangeListener(const RefPtr<V2::DataChangeListener>& listener)
110 {
111 if (!listener) {
112 return;
113 }
114 auto listenerManager = weakListenerManager_.promote();
115 if (listenerManager) {
116 listenerManager->AddListener(listener);
117 return;
118 }
119 listenerManager = FFIData::Create<CJDataChangeListener>();
120 listenerManager->AddListener(listener);
121 weakListenerManager_ = listenerManager;
122 cjBuilder_->RegisterListenerFunc(listenerManager);
123 }
124
UnregisterDataChangeListener(V2::DataChangeListener * listener)125 void CJLazyForEachBuilder::UnregisterDataChangeListener(V2::DataChangeListener* listener)
126 {
127 if (!listener) {
128 LOGW("CJLazyForEachBuilder listener is null");
129 return;
130 }
131 auto listenerManager = weakListenerManager_.promote();
132 if (!listenerManager) {
133 // this would happen before first RegisterDataChangeListener called
134 // this would happen after cj released listenerManager
135 LOGW("LazyForEach::UnregisterDataChangeListener fail, listenerManager is null.");
136 return;
137 }
138 listenerManager->RemoveListener(WeakClaim(listener));
139 }
140
141 } // namespace OHOS::Ace::Framework
142