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