* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FRAMEWORKS_BRIDGE_CJ_FRONTEND_CPP_VIEW_NATIVE_VIEW_H
#define FRAMEWORKS_BRIDGE_CJ_FRONTEND_CPP_VIEW_NATIVE_VIEW_H
#include <list>
#include <unordered_set>
#include "ffi_remote_data.h"
#include "base/utils/macros.h"
#include "bridge/cj_frontend/cppview/view_abstract.h"
#include "bridge/cj_frontend/interfaces/cj_ffi/cj_macro.h"
#include "core/components_ng/base/view_partial_update_model.h"
namespace OHOS::Ace::Framework {
class NativeView;
ACE_EXPORT bool LoadNativeView(const sptr<NativeView>& view);
ACE_EXPORT std::string GetProcessViewId(int64_t id);
* delegate for cj view object
*/
class RemoteView : public FFI::RemoteData {
CJ_REMOTE_CLASS(RemoteView)
public:
void OnShow();
void OnHide();
bool OnBackPress();
void UpdateWithJson(const std::string&);
void OnAppear();
void OnTransition();
void OnAboutToRender();
void Render();
void Rerender();
void OnAfterRender();
void OnDisappear();
void OnAboutToBeDeleted();
void Reload(bool deep);
void OnDidBuild();
void AboutToReuse(const std::string&);
void AboutToRecycle();
void RecycleSelf(const std::string&);
private:
void VoidCallback(void (*cjFunc)(int64_t), const char* funcName);
};
* NativeView render process have 3 steps
* 1. create ComposedComponent, set build children callback
* 2. ComposedComponent create ComposedElement and PerformBuild
* 3. build children component by CallRenderFunction(set by step 1)
*
* why can't build children component on step 1, because `InternalRender` is not reentrant.
* When a NativeView contains a NativeView child, that will cause unexpected result.
*
* how `InternalRender` can't reentrant, see `ViewStackProcessor::GetInstance()->Finish();`,
* ViewStackProcessor has a global component tree, and `Finish()` will wrap the whole tree to a Component,
* meanwhile clear the tree. when build a tree in the middle of another tree building process,
* when subtree finish building by `ViewStackProcessor::GetInstance()->Finish();`, the subtree will be wrap at
* wrong start, and the previous tree will lose some nodes.
*/
class ACE_EXPORT NativeView : public ViewAbstract {
DECL_TYPE(NativeView, ViewAbstract)
using UpdateFuncResult = std::tuple<int32_t, RefPtr<Component>, RefPtr<Component>>;
public:
explicit NativeView(sptr<RemoteView> cjView);
~NativeView() override;
void Destroy();
RefPtr<AceType> CreateUI();
RefPtr<AceType> InitialUIRender();
void SyncInstanceId();
void RestoreInstanceId();
void MarkNeedUpdate();
void FlushReload();
bool NeedsUpdate() const
{
return needsUpdate_;
}
bool IsFullUpdate() const
{
return !useNewPipeline_;
}
void SetRenderDoneCallback(std::function<void()> callback)
{
onRenderDone_ = std::move(callback);
}
* Views which do not have a state can mark static.
* The element will be reused and re-render will be skipped.
*/
void MarkStatic()
{
isStatic_ = true;
}
bool IsStatic() const
{
return isStatic_;
}
bool IsFirstRender() const
{
return isFirstRender_;
}
bool IsUseNewPipeline() const
{
return useNewPipeline_;
}
* During render function execution, the child customview with same id will
* be recycled if they exist already in our child map. The ones which are not
* recycled needs to be cleaned. So After render function execution, clean the
* abandoned child customview.
*/
void CleanUpAbandonedChild();
void FireOnShow();
void FireOnHide();
bool FireOnBackPress();
void FireOnTransition();
void ExecuteUpdateWithValueParams(const std::string& jsonData);
static void Create(const sptr<NativeView>& view);
static void CreateRecycle(
const sptr<NativeView>& view, bool isRecycling, const std::string& nodeName, std::function<void()> callback);
* Last step of executing an partial update function
* get the result component from ViewStackProcessor
* add it to the queue to [elmtId, Component] to
* execute an local update on in the UI thread
* parameters
* elmtId of the Component/Element that's updated
* removedElementId : Array<number> ids of Elements that were removed while updating
* caused by if condition toggle or ForEach array deleted / replaced items
* return boolean - true means success
*/
void FinishUpdateFunc(int32_t elmtId);
void GetDeletedElemtIds(std::vector<int64_t>& vec);
void DeletedElmtIdsHaveBeenPurged(std::vector<int64_t>& vec);
int32_t GetInstanceId() const
{
return instanceId_;
}
RefPtr<AceType> GetViewNode() const
{
return node_.Upgrade();
}
void ResetRecycleCustomNode()
{
recycleCustomNode_.Reset();
}
void SetRecycleCustomNode(const RefPtr<NG::CustomNodeBase>& recycleNode)
{
recycleCustomNode_ = recycleNode;
}
RefPtr<NG::CustomNodeBase> GetCachedRecycleNode()
{
auto node = RefPtr<NG::CustomNodeBase>(recycleCustomNode_);
recycleCustomNode_.Reset();
return node;
}
const std::string& GetRecycleCustomNodeName()
{
return recycleCustomNodeName_;
}
void SetRecycleCustomNodeName(const std::string& recycleCustomNodeName)
{
recycleCustomNodeName_ = recycleCustomNodeName;
}
void SetCjProfilerViewName(const std::string& name)
{
cjProfilerViewName_ = name;
}
const std::string& GetCjProfilerViewName() const
{
return cjProfilerViewName_;
}
void SetIsRecycleRerender(bool isRecycleRerender)
{
isRecycleRerender_ = isRecycleRerender;
}
bool GetIsRecycleRerender()
{
return isRecycleRerender_;
}
private:
* cjView is the delegate for cj_custom_view object, it should be assigned once NativeView is created
* and release after NativeView is released. It's possible to reuse a NativeView to bind several cj_custom_view
* objects, but it should not, just keep things simple. One NativeView bind one cj_custom_view, never bind
* a second object, keep it that way.
*/
sptr<RemoteView> cjView_;
std::string viewId_;
int32_t instanceId_ = -1;
int32_t restoreInstanceId_ = -1;
bool needsUpdate_ = false;
bool isStatic_ = false;
std::function<void()> onRenderDone_ = nullptr;
bool useNewPipeline_ = false;
bool isFirstRender_ = true;
WeakPtr<AceType> node_ = nullptr;
<0> elmtId
<1> outmost wrapping Component
<2> main Component
*/
std::list<UpdateTask> pendingUpdateTasks_;
RefPtr<NG::CustomNodeBase> recycleCustomNode_;
std::string recycleCustomNodeName_;
bool isRecycleRerender_ = false;
std::string cjProfilerViewName_;
int32_t profilerElementId_ = -1;
};
}
#endif