简体   繁体   中英

Should I check VisualElement.IsVisible before setting it?

Visual elements in Xamarin Forms are made visible/invisible by setting their IsVisible property. Changing some properties or data on visual elements can cause the interface to redraw, which can be expensive.

I'm trying to improve performance on my app so I've introduced caching and tried to make some layout simplifications, but I have to make a lot of visual elements visible/invisible and wondered wht the best way would be to optimise this.

Which is the more efficient operation?

var myButton.IsVisible = true;

Or:

if(!myButton.IsVisible) myButton.IsVisible = true;

If Xamarin already checks the state and decides whether to redraw then the second option is redundant and therefore inefficient. If a redraw happens every time the property is set then it will be more efficient. I can't find any documentation to tell me which is the case.

Any good implementation of a DependencyProperty (or INotifyPropertyChanged ) member should ignore successive set s if that value is the same. For that reason let IsVisible work out what to do rather than place responsiblity on callers.

If Xamarin already checks the state and decides whether to redraw then the second option is redundant and therefore inefficien

That's right. Xamarin, like other XAML-based implemenations, are visually-efficient (unlike WinForms) so setting a visual property is not likely to immediately cause a screen refresh. Additonally, the entire app window is rendered in a single blit to avoid flicker.

In Xamarin, setting button.IsVisible for example makes it way down to BindableObject.SetValueActual ( Button has BindableObject in its inheritance graph) where checks are made for sameness. The new value is only applied if the value is different or if SetValueFlags.RaiseOnEqual is set.

OnPropertyChanged and PropertyChanged are called on different values or if RaiseOnEqual is set.

Xamarin source code from GitHub : (my comments)

void SetValueActual(BindableProperty property, BindablePropertyContext context, object value, bool currentlyApplying, SetValueFlags attributes, bool silent = false)
{
    object original = context.Value;
    bool raiseOnEqual = (attributes & SetValueFlags.RaiseOnEqual) != 0;
    bool clearDynamicResources = (attributes & SetValueFlags.ClearDynamicResource) != 0;
    bool clearOneWayBindings = (attributes & SetValueFlags.ClearOneWayBindings) != 0;
    bool clearTwoWayBindings = (attributes & SetValueFlags.ClearTwoWayBindings) != 0;

    bool same = ReferenceEquals(context.Property, BindingContextProperty) ? ReferenceEquals(value, original) : Equals(value, original);
    if (!silent && (!same || raiseOnEqual))
    {
        property.PropertyChanging?.Invoke(this, original, value);

        OnPropertyChanging(property.PropertyName);
    }

    if (!same || raiseOnEqual)
    {
        context.Value = value; // <---------- assignment
    }
.
.
.
    if (!silent && (!same || raiseOnEqual)) // <------- notifications guard
    {
        if (binding != null && !currentlyApplying)
        {
            _applying = true;
            binding.Apply(true);
            _applying = false;
        }

        OnPropertyChanged(property.PropertyName);

        property.PropertyChanged?.Invoke(this, original, value);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM