Renderer is recreated on view update
See original GitHub issue- Run this example on Android 7.0+: SqueakyApp.zip
- Increment counter multiple times, or use Timer switch
- See Device Log:
Time Device Name Type PID Tag Message
04-21 12:09:04.880 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:09:06.807 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:09:06.772 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:09:06.564 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:09:06.297 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:09:06.045 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:09:05.793 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:09:05.569 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:09:05.336 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:09:05.112 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:09:04.689 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:09:04.649 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:09:04.425 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:09:04.195 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:09:04.016 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:09:03.964 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:09:03.737 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:09:03.504 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:09:03.311 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:09:03.274 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:09:03.042 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:09:02.808 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:09:02.619 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:09:02.577 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:09:02.390 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:09:02.345 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:09:02.119 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:09:01.867 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:09:01.574 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:09:01.308 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:09:01.056 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:09:00.786 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:09:00.534 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:09:00.266 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:09:00.011 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:08:59.747 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:08:59.495 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:08:59.226 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:08:58.977 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:08:58.691 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:08:58.449 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:08:58.191 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:08:57.938 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:08:57.679 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:08:57.436 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:08:57.177 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:08:56.930 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
04-21 12:08:52.979 Google Pixel 3 Info 28526 mono-stdout Create RtcVideoFrameRenderer
The problem occurs when dynamically adding and deleting any element inside the grid (in this case). It seems that all elements in grid disposing and recreating even if they were not deleted by condition. I found workaround for this bug. You can set fixBug
value to true
and the problem will go away. As you can see in code below I just change element visibility with fixBug
value what does not delete element itself.
let view (model: Model) dispatch =
let vis = model.Count % 2 = 0
let fixBug = false
View.ContentPage(
content = View.StackLayout(padding = Thickness 20.0, verticalOptions = LayoutOptions.Center,
children = [
View.Label(text = sprintf "%d" model.Count, horizontalOptions = LayoutOptions.Center, width=200.0, horizontalTextAlignment=TextAlignment.Center)
View.Button(text = "Increment", command = (fun () -> dispatch Increment), horizontalOptions = LayoutOptions.Center)
View.Button(text = "Decrement", command = (fun () -> dispatch Decrement), horizontalOptions = LayoutOptions.Center)
View.Label(text = "Timer", horizontalOptions = LayoutOptions.Center)
View.Switch(isToggled = model.TimerOn, toggled = (fun on -> dispatch (TimerToggled on.Value)), horizontalOptions = LayoutOptions.Center)
View.Slider(minimumMaximum = (0.0, 10.0), value = double model.Step, valueChanged = (fun args -> dispatch (SetStep (int (args.NewValue + 0.5)))), horizontalOptions = LayoutOptions.FillAndExpand)
View.Label(text = sprintf "Step size: %d" model.Step, horizontalOptions = LayoutOptions.Center)
View.Grid(
padding = Thickness(0.),
rowSpacing = 0.,
rowdefs = [
Dimension.Star
Dimension.Absolute 64.
Dimension.Auto
Dimension.Auto
Dimension.Star
Dimension.Absolute 64.
Dimension.Absolute 20.
],
children = [
if fixBug then
View.AbsoluteLayout(
horizontalOptions = LayoutOptions.Fill,
verticalOptions = LayoutOptions.Fill,
isVisible = vis,
children = [
]
) |> rowSpan 6
if not fixBug && vis then
View.AbsoluteLayout(
horizontalOptions = LayoutOptions.Fill,
verticalOptions = LayoutOptions.Fill,
children = [
]
) |> rowSpan 6
View.RtcVideoFrame(
automationId = "RemoteVideoFrame",
margin = Thickness(0.),
ref = model.VideoRef,
horizontalOptions = LayoutOptions.FillAndExpand,
verticalOptions = LayoutOptions.FillAndExpand,
isVisible = vis
) |> rowSpan 6
]
)
if model.Count % 2 = 0 then
View.Button(text = "Reset", horizontalOptions = LayoutOptions.Center, command = (fun () -> dispatch Reset), commandCanExecute = (model <> initModel))
]))
Issue Analytics
- State:
- Created 3 years ago
- Reactions:2
- Comments:8 (3 by maintainers)
Top Results From Across the Web
Updating Environment makes view re-render with all his ...
I have an @Environment who store all share data for my views. One of my views use one of its variables to present...
Read more >Understanding how and when SwiftUI decides to redraw ...
The view model is an observable object and whenever one of its items changes, it will update its @Published list of items.
Read more >How to correctly force a Vue component to re-render
As recommended by the official Vue documentation, the built-in forceUpdate method is one of the best ways to manually update a component.
Read more >About Updating Legacy Rendering Objects and Settings
Legacy drawings containing AutoShade content and rendering settings need to be updated to be usable when rendering the model to an image.
Read more >Angular Data Grid: Cell Renderer
Events Causing Refresh The grid can refresh the data in the browser, but not every refresh / redraw of the grid results in...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
This is a known issue. It’s linked to how Fabulous reuses controls. A smarter reuse mechanism is required to support this case correctly. See https://github.com/fsprojects/Fabulous/issues/454
To explain a bit: At each update, Fabulous walks the UI tree to check what changed. It only compares controls based on their position (index) inside their parent control.
Let’s say
model.Count = 0
. The Grid will have 2 children: an AbsoluteLayout (index 0) and a RtcVideoFrame (index 1).Now
model.Count = 1
. The new Grid should have only one RtcVideoFrame (index 0).Fabulous will start diff’ing.
Is previous Index 0 (AbsoluteLayout) the same thing than new Index 0 (RtcVideoFrame)? No. Destroy AbsoluteLayout, create RtcVideoFrame.
Does previous Index 1 (RtcVideoFrame) still exist? No. Destroy RtcVideoFrame.
So to avoid that for now, you’ll need to try to keep the same controls at the same indices as much as possible, at least when adding/removing controls at the start of a list. One way to achieve that is by playing with visibility: https://github.com/fsprojects/Fabulous/issues/454#issuecomment-588128782
@TimLariviere , @SergejDK could you please take a look at #721 as rough PoC of key property?