• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef FRAMEWORKS_BRIDGE_CJ_FRONTEND_CPP_VIEW_NATIVE_VIEW_H
17 #define FRAMEWORKS_BRIDGE_CJ_FRONTEND_CPP_VIEW_NATIVE_VIEW_H
18 
19 #include <list>
20 #include <unordered_set>
21 
22 #include "ffi_remote_data.h"
23 
24 #include "base/utils/macros.h"
25 #include "bridge/cj_frontend/cppview/view_abstract.h"
26 #include "bridge/cj_frontend/interfaces/cj_ffi/cj_macro.h"
27 #include "core/components_ng/base/view_partial_update_model.h"
28 
29 namespace OHOS::Ace::Framework {
30 
31 class NativeView;
32 
33 ACE_EXPORT bool LoadNativeView(const sptr<NativeView>& view);
34 
35 ACE_EXPORT std::string GetProcessViewId(int64_t id);
36 
37 /**
38  * delegate for cj view object
39  */
40 class RemoteView : public FFI::RemoteData {
41     CJ_REMOTE_CLASS(RemoteView)
42 
43 public:
44     void OnShow();
45     void OnHide();
46     bool OnBackPress();
47     void UpdateWithJson(const std::string&);
48     void OnAppear();
49     void OnTransition();
50     void OnAboutToRender();
51     void Render();
52     void Rerender();
53     void OnAfterRender();
54     void OnDisappear();
55     void OnAboutToBeDeleted();
56     void Reload(bool deep);
57     void OnDidBuild();
58     void AboutToReuse(const std::string&);
59     void AboutToRecycle();
60     void RecycleSelf(const std::string&);
61 
62 private:
63     void VoidCallback(void (*cjFunc)(int64_t), const char* funcName);
64 };
65 
66 /**
67  * NativeView render process have 3 steps
68  *  1. create ComposedComponent, set build children callback
69  *  2. ComposedComponent create ComposedElement and PerformBuild
70  *  3. build children component by CallRenderFunction(set by step 1)
71  *
72  *  why can't build children component on step 1, because `InternalRender` is not reentrant.
73  *  When a NativeView contains a NativeView child, that will cause unexpected result.
74  *
75  *  how `InternalRender` can't reentrant, see `ViewStackProcessor::GetInstance()->Finish();`,
76  *  ViewStackProcessor has a global component tree, and `Finish()` will wrap the whole tree to a Component,
77  *  meanwhile clear the tree. when build a tree in the middle of another tree building process,
78  *  when subtree finish building by `ViewStackProcessor::GetInstance()->Finish();`, the subtree will be wrap at
79  *  wrong start, and the previous tree will lose some nodes.
80  */
81 class ACE_EXPORT NativeView : public ViewAbstract {
82     DECL_TYPE(NativeView, ViewAbstract)
83     using UpdateFuncResult = std::tuple<int32_t, RefPtr<Component>, RefPtr<Component>>;
84 
85 public:
86     explicit NativeView(sptr<RemoteView> cjView);
87     ~NativeView() override;
88 
89     void Destroy();
90 
91     RefPtr<AceType> CreateUI();
92     RefPtr<AceType> InitialUIRender();
93 
94     void SyncInstanceId();
95     void RestoreInstanceId();
96     void MarkNeedUpdate();
97     void FlushReload();
NeedsUpdate()98     bool NeedsUpdate() const
99     {
100         return needsUpdate_;
101     }
IsFullUpdate()102     bool IsFullUpdate() const
103     {
104         return !useNewPipeline_;
105     }
106 
SetRenderDoneCallback(std::function<void ()> callback)107     void SetRenderDoneCallback(std::function<void()> callback)
108     {
109         onRenderDone_ = std::move(callback);
110     }
111 
112     /**
113      * Views which do not have a state can mark static.
114      * The element will be reused and re-render will be skipped.
115      */
MarkStatic()116     void MarkStatic()
117     {
118         isStatic_ = true;
119     }
IsStatic()120     bool IsStatic() const
121     {
122         return isStatic_;
123     }
124 
IsFirstRender()125     bool IsFirstRender() const
126     {
127         return isFirstRender_;
128     }
129 
IsUseNewPipeline()130     bool IsUseNewPipeline() const
131     {
132         return useNewPipeline_;
133     }
134 
135     /**
136      * During render function execution, the child customview with same id will
137      * be recycled if they exist already in our child map. The ones which are not
138      * recycled needs to be cleaned. So After render function execution, clean the
139      * abandoned child customview.
140      */
141     void CleanUpAbandonedChild();
142 
143     void FireOnShow();
144     void FireOnHide();
145     bool FireOnBackPress();
146     void FireOnTransition();
147     void ExecuteUpdateWithValueParams(const std::string& jsonData);
148 
149     static void Create(const sptr<NativeView>& view);
150     static void CreateRecycle(
151         const sptr<NativeView>& view, bool isRecycling, const std::string& nodeName, std::function<void()> callback);
152 
153     /**
154      * Last step of executing an partial update function
155      * get the result component from ViewStackProcessor
156      * add it to the queue to [elmtId, Component] to
157      * execute an local update on in the UI thread
158      * parameters
159      * elmtId of the Component/Element that's updated
160      * removedElementId : Array<number>  ids of Elements that were removed while updating
161      * caused by if condition toggle or ForEach array deleted / replaced items
162      * return boolean - true means success
163      */
164     void FinishUpdateFunc(int32_t elmtId);
165 
166     // The process of Component to Element sync leads to Elements being
167     // deleted. ElementRegister keeps track of these deletions
168     // before the framework can forget about these elmtIds
169     // these need to be removed from its own book keeping
170     // state variables keep track of dependent elmtIds and
171     // View objects keep a map elmtId -> update function,
172     // both on TS side.
173     // View.purgeDeletedElmtIds cleans both state variables
174     // and update function map from deleted ElmtIds
175     // afterwards it informs the ElementRegister that elmtIds
176     // it was able to purge.
177     // only then ElementRegister can forget about these elmtIds
178     void GetDeletedElemtIds(std::vector<int64_t>& vec);
179 
180     // JS signature: View.deletedElmtIdsHaveBeenPurged(elmtIds : number[])
181     // inform ElementRegister that given deleted eltIds
182     // have been deleted from partial updates book keeping
183     // at this point ElementRegister can forget about the,
184     void DeletedElmtIdsHaveBeenPurged(std::vector<int64_t>& vec);
185 
GetInstanceId()186     int32_t GetInstanceId() const
187     {
188         return instanceId_;
189     }
190 
GetViewNode()191     RefPtr<AceType> GetViewNode() const
192     {
193         return node_.Upgrade();
194     }
195 
ResetRecycleCustomNode()196     void ResetRecycleCustomNode()
197     {
198         recycleCustomNode_.Reset();
199     }
200 
SetRecycleCustomNode(const RefPtr<NG::CustomNodeBase> & recycleNode)201     void SetRecycleCustomNode(const RefPtr<NG::CustomNodeBase>& recycleNode)
202     {
203         recycleCustomNode_ = recycleNode;
204     }
205 
GetCachedRecycleNode()206     RefPtr<NG::CustomNodeBase> GetCachedRecycleNode()
207     {
208         auto node = RefPtr<NG::CustomNodeBase>(recycleCustomNode_);
209         recycleCustomNode_.Reset();
210         return node;
211     }
212 
GetRecycleCustomNodeName()213     const std::string& GetRecycleCustomNodeName()
214     {
215         return recycleCustomNodeName_;
216     }
217 
SetRecycleCustomNodeName(const std::string & recycleCustomNodeName)218     void SetRecycleCustomNodeName(const std::string& recycleCustomNodeName)
219     {
220         recycleCustomNodeName_ = recycleCustomNodeName;
221     }
222 
SetIsRecycleRerender(bool isRecycleRerender)223     void SetIsRecycleRerender(bool isRecycleRerender)
224     {
225         isRecycleRerender_ = isRecycleRerender;
226     }
227 
GetIsRecycleRerender()228     bool GetIsRecycleRerender()
229     {
230         return isRecycleRerender_;
231     }
232 
233 private:
234     /**
235      * cjView is the delegate for cj_custom_view object, it should be assigned once NativeView is created
236      * and release after NativeView is released. It's possible to reuse a NativeView to bind several cj_custom_view
237      * objects, but it should not, just keep things simple. One NativeView bind one cj_custom_view, never bind
238      * a second object, keep it that way.
239      */
240     sptr<RemoteView> cjView_;
241 
242     // view id for custom view itself
243     std::string viewId_;
244 
245     int32_t instanceId_ = -1;
246     int32_t restoreInstanceId_ = -1;
247 
248     bool needsUpdate_ = false;
249     bool isStatic_ = false;
250 
251     std::function<void()> onRenderDone_ = nullptr;
252     bool useNewPipeline_ = false;
253     bool isFirstRender_ = true;
254     WeakPtr<AceType> node_ = nullptr;
255 
256     /* list of update function result is a triple (tuple with three entries)
257     <0> elmtId
258     <1> outmost wrapping Component
259     <2> main Component
260     */
261     std::list<UpdateTask> pendingUpdateTasks_;
262 
263     RefPtr<NG::CustomNodeBase> recycleCustomNode_;
264     std::string recycleCustomNodeName_;
265     bool isRecycleRerender_ = false;
266 };
267 
268 } // namespace OHOS::Ace::Framework
269 #endif // FRAMEWORKS_BRIDGE_CJ_FRONTEND_CPP_VIEW_NATIVE_VIEW_H
270