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