question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Renderer is recreated on view update

See original GitHub issue
  1. Run this example on Android 7.0+: SqueakyApp.zip
  2. Increment counter multiple times, or use Timer switch
  3. 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:closed
  • Created 3 years ago
  • Reactions:2
  • Comments:8 (3 by maintainers)

github_iconTop GitHub Comments

2reactions
TimLarivierecommented, Apr 21, 2020

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

0reactions
vshapenkocommented, Apr 24, 2020

@TimLariviere , @SergejDK could you please take a look at #721 as rough PoC of key property?

Read more comments on GitHub >

github_iconTop 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 >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found