未验证 提交 cfe8675f 编写于 作者: C Chris Yang 提交者: GitHub

Delay platform view removal to submitFrame. (#8380)

Remove platform views inside OnDispose might cause issue if it happens before SubmitFrame and the active_composition_order has not been updated.
We will be left at a situation where the active_composition_order still contains the old view, but the view is actually removed from the UIView hierarchy.

We now cache the views need to be removed in OnDispose and actually remove them in SubmitFrame. At the same time, we remove stop detaching the subviews if they were disposed. 

As a side effect, this update will also fix flutter/flutter#30220
上级 c9916474
......@@ -100,12 +100,8 @@ void FlutterPlatformViewsController::OnDispose(FlutterMethodCall* call, FlutterR
details:[NSString stringWithFormat:@"view id: '%lld'", viewId]]);
return;
}
UIView* touch_interceptor = touch_interceptors_[viewId].get();
[touch_interceptor removeFromSuperview];
views_.erase(viewId);
touch_interceptors_.erase(viewId);
overlays_.erase(viewId);
// We wait for next submitFrame to dispose views.
views_to_dispose_.insert(viewId);
result(nil);
}
......@@ -213,6 +209,8 @@ void FlutterPlatformViewsController::Reset() {
bool FlutterPlatformViewsController::SubmitFrame(bool gl_rendering,
GrContext* gr_context,
std::shared_ptr<IOSGLContext> gl_context) {
DisposeViews();
bool did_submit = true;
for (size_t i = 0; i < composition_order_.size(); i++) {
int64_t view_id = composition_order_[i];
......@@ -265,12 +263,30 @@ void FlutterPlatformViewsController::DetachUnusedLayers() {
for (int64_t view_id : active_composition_order_) {
if (composition_order_set.find(view_id) == composition_order_set.end()) {
if (touch_interceptors_.find(view_id) == touch_interceptors_.end()) {
continue;
}
[touch_interceptors_[view_id].get() removeFromSuperview];
[overlays_[view_id]->overlay_view.get() removeFromSuperview];
}
}
}
void FlutterPlatformViewsController::DisposeViews() {
if (views_to_dispose_.empty()) {
return;
}
for (int64_t viewId : views_to_dispose_) {
UIView* touch_interceptor = touch_interceptors_[viewId].get();
[touch_interceptor removeFromSuperview];
views_.erase(viewId);
touch_interceptors_.erase(viewId);
overlays_.erase(viewId);
}
views_to_dispose_.clear();
}
void FlutterPlatformViewsController::EnsureOverlayInitialized(int64_t overlay_id) {
if (overlays_.count(overlay_id) != 0) {
return;
......
......@@ -91,6 +91,10 @@ class FlutterPlatformViewsController {
GrContext* overlays_gr_context_;
SkISize frame_size_;
// Method channel `OnDispose` calls adds the views to be disposed to this set to be disposed on
// the next frame.
std::unordered_set<int64_t> views_to_dispose_;
// A vector of embedded view IDs according to their composition order.
// The last ID in this vector belond to the that is composited on top of all others.
std::vector<int64_t> composition_order_;
......@@ -106,6 +110,8 @@ class FlutterPlatformViewsController {
void OnRejectGesture(FlutterMethodCall* call, FlutterResult& result);
void DetachUnusedLayers();
// Dispose the views in `views_to_dispose_`.
void DisposeViews();
void EnsureOverlayInitialized(int64_t overlay_id);
void EnsureGLOverlayInitialized(int64_t overlay_id,
std::shared_ptr<IOSGLContext> gl_context,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册