fix the problem of LazyForEach deleted function

Signed-off-by: yan-shuifeng <yanshuifeng@huawei.com>
Change-Id: I6ad038d3c8f0d9a3041cdb2904f7e4010b563f4c
This commit is contained in:
yan-shuifeng
2022-03-31 16:43:54 +08:00
parent bf0bae2610
commit 19e3e717f3
4 changed files with 85 additions and 26 deletions
@@ -293,11 +293,15 @@ public:
auto viewStack = ViewStackProcessor::GetInstance();
auto multiComposed = AceType::MakeRefPtr<MultiComposedComponent>(key, "LazyForEach");
viewStack->Push(multiComposed);
if (parentView_) {
parentView_->MarkLazyForEachProcess(key);
}
viewStack->PushKey(key);
itemGenFunc_->Call(JSRef<JSObject>(), 1, &result);
viewStack->PopKey();
if (parentView_) {
parentView_->ResetLazyForEachProcess();
}
auto component = viewStack->Finish();
ACE_DCHECK(multiComposed == component);
@@ -243,13 +243,22 @@ void JSView::DestructorCallback(JSView* view)
void JSView::DestroyChild(JSView* parentCustomView)
{
LOGD("JSView::DestroyChild start");
for (auto child : customViewChildren_) {
for (auto&& child : customViewChildren_) {
auto* view = child.second->Unwrap<JSView>();
if (view != nullptr) {
view->Destroy(this);
}
child.second.Reset();
}
customViewChildren_.clear();
for (auto&& lazyChild : customViewChildrenWithLazy_) {
auto* view = lazyChild.second->Unwrap<JSView>();
if (view != nullptr) {
view->Destroy(this);
}
lazyChild.second.Reset();
}
customViewChildrenWithLazy_.clear();
LOGD("JSView::DestroyChild end");
}
@@ -287,50 +296,64 @@ JSRef<JSObject> JSView::GetChildById(const std::string& viewId)
ChildAccessedById(id);
return found->second;
}
auto lazyItem = customViewChildrenWithLazy_.find(id);
if (lazyItem != customViewChildrenWithLazy_.end()) {
return lazyItem->second;
}
return {};
}
std::string JSView::AddChildById(const std::string& viewId, const JSRef<JSObject>& obj)
{
auto id = ViewStackProcessor::GetInstance()->ProcessViewId(viewId);
customViewChildren_.emplace(id, obj);
ChildAccessedById(id);
JSView* jsview = nullptr;
if (isLazyForEachProcessed_) {
auto result = customViewChildrenWithLazy_.try_emplace(id, obj);
if (!result.second) {
jsview = result.first->second->Unwrap<JSView>();
result.first->second = obj;
}
lazyItemGroups_[lazyItemGroupId_].emplace_back(id);
} else {
auto result = customViewChildren_.try_emplace(id, obj);
if (!result.second) {
jsview = result.first->second->Unwrap<JSView>();
result.first->second = obj;
}
ChildAccessedById(id);
}
if (jsview != nullptr) {
jsview->Destroy(this);
}
return id;
}
void JSView::RemoveChildGroupById(const std::string& viewId)
{
JAVASCRIPT_EXECUTION_SCOPE_STATIC;
if (viewId.empty()) {
auto removeView = customViewChildren_.find(viewId);
if (removeView != customViewChildren_.end()) {
LOGD("RemoveChildGroupById in lazy for each case: %{public}s", viewId.c_str());
auto iter = lazyItemGroups_.find(viewId);
if (iter == lazyItemGroups_.end()) {
LOGI("can not find this groud to delete: %{public}s", viewId.c_str());
return;
}
std::vector<std::string> removedViewIds;
for (auto&& item : iter->second) {
auto removeView = customViewChildrenWithLazy_.find(item);
if (removeView != customViewChildrenWithLazy_.end()) {
auto* view = removeView->second->Unwrap<JSView>();
if (view != nullptr) {
view->Destroy(this);
}
removeView->second.Reset();
customViewChildren_.erase(removeView);
removedViewIds.emplace_back(item);
}
return;
}
auto startIter = customViewChildren_.begin();
auto endIter = customViewChildren_.end();
std::vector<std::string> removedViewIds;
while (startIter != endIter) {
if (StartWith(startIter->first, viewId)) {
removedViewIds.emplace_back(startIter->first);
auto* view = startIter->second->Unwrap<JSView>();
if (view != nullptr) {
view->Destroy(this);
}
startIter->second.Reset();
}
++startIter;
}
for (auto&& removeId : removedViewIds) {
customViewChildren_.erase(removeId);
customViewChildrenWithLazy_.erase(removeId);
}
lazyItemGroups_.erase(iter);
}
void JSView::ChildAccessedById(const std::string& viewId)
@@ -114,6 +114,18 @@ public:
jsViewFunction_->ExecuteUpdateWithValueParams(jsonData);
}
void MarkLazyForEachProcess(const std::string& groudId)
{
isLazyForEachProcessed_ = true;
lazyItemGroupId_ = groudId;
}
void ResetLazyForEachProcess()
{
isLazyForEachProcessed_ = false;
lazyItemGroupId_ = "";
}
/**
* New CustomView child will be added to the map.
* and it can be reterieved for recycling in next render function
@@ -153,6 +165,8 @@ private:
WeakPtr<OHOS::Ace::ComposedElement> element_ = nullptr;
bool needsUpdate_ = false;
bool isStatic_ = false;
bool isLazyForEachProcessed_ = false;
std::string lazyItemGroupId_;
RefPtr<ViewFunctions> jsViewFunction_;
@@ -161,6 +175,15 @@ private:
// hold handle to the native and javascript object to keep them alive
// until they are abandoned
std::unordered_map<std::string, JSRef<JSObject>> customViewChildren_;
// hold handle to the native and javascript object to keep them alive
// until they are abandoned used by lazyForEach
std::unordered_map<std::string, JSRef<JSObject>> customViewChildrenWithLazy_;
// hold js view ids by lazy item ground.
// until they are abandoned used by lazyForEach
std::unordered_map<std::string, std::list<std::string>> lazyItemGroups_;
// a set of valid viewids on a renderfuntion excution
// its cleared after cleaning up the abandoned child.
std::unordered_set<std::string> lastAccessedViewIds_;
@@ -163,7 +163,16 @@ private:
class LazyForEachElementProxy : public ElementProxy, public DataChangeListener {
public:
explicit LazyForEachElementProxy(const WeakPtr<ElementProxyHost>& host) : ElementProxy(host) {}
~LazyForEachElementProxy() override = default;
~LazyForEachElementProxy() override
{
for (auto&& item : children_) {
auto viewId = item.second->GetId();
if (lazyForEachComponent_) {
lazyForEachComponent_->ReleaseChildGroupByComposedId(viewId);
}
}
children_.clear();
}
void Update(const RefPtr<Component>& component, size_t startIndex) override
{