I've been spending a lot of time trying to track down memory leaks in our Xamarin.Forms app on Android. After a lot of blind alleys and false dawns, I think I may have come across something which is causing the problem.
Using Xamarin Profiler, I can see that as soon as I create a Style and apply it to a control (or in fact just an implicit style), we get Multiple WeakReferences remaining 'Live' - i.e. not garbage collected.
Note that I assume that the objects to which they refer have been GC'd (because the reference to the object is weak), but the WeakReferences themselves are remaining.
Now of course WeakReferences are small I know - but when you have hundreds created on every iteration of a page push/pop, then the memory adds up and we have a significant leak.
Here are the details.
Using Xamarin.Forms 2.3.4.270 (we haven't upgraded because we want to keep with known issues!)
Running on Android - physical device.
App.xaml:
<?xml version="1.0" encoding="utf-8"?>
<Application xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:ProfiledFormsApp2;assembly=ProfiledFormsApp2"
x:Class="ProfiledFormsApp2.App">
<Application.Resources>
<ResourceDictionary>
<Style TargetType="Label">
<Setter Property="FontSize" Value="Large" />
<Setter Property="TextColor" Value="Blue" />
</Style>
</ResourceDictionary>
</Application.Resources>
</Application>
Page XAML:
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage Title="Plain Page" xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="ProfiledFormsApp2.PlainPage">
<ContentPage.Content>
<StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="Core Navigation"/>
<Label Text="Number of items:" />
<Label Text="{Binding ItemsCount}" />
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>
When I navigate to the above page and back 3 times, we have the following WeakReference (and related) classes created - the screenshot below is from a Profiler snapshot.
Note we have 55 WeakReferences. Drilling into these shows:
What is interesting is that these WeakReferences seem to be created as part of Behavior and Trigger attaching. Looking at the call tree for the top one gives:
So it appears that the WeakReference was created as part of setting a BindableObject's value and the subsequent setting of the Style.
And it also appears that the WeakReference is still in memory and being referenced by something - the Behavior collection?
Using Profiler, I'm can see that we don't have Labels remaining un GC'd. It seems to be something in the Theme/Behavior/Trigger processing.
I haven't looked at the Xamarin.Forms code on GitHub yet - that might have to be my next action.
Has anyone observed this or got a solution?
I am not sure about the implicit styles to the controls but for the explicit styles you can remove them while page is out of scope OR disappearing.
Example, we applied an explicit style to button
<Button x:Name="btnSave" Style="{StaticResource SaveButtonStyle}" Content="Save"/>
protected override void OnDisappearing()
{
btnSave.Style = null;
base.OnDisappearing();
}
Same can be done with Triggers and Behaviors as well (You can clear them).
I think for the implicit styles, there is something within the code of framework only. We can not identify how default style of control is attached with control as default.
Related
I have just recently started using .Net MAUI. But now I'm wondering how to use a piece of code, e.g. a self-made navigation bar on all my pages, because it doesn't make sense to write the same code on all 10 pages. I like to know if there is a way to create a component that can be reused like in React or Angular?
PS: This question is not specific to a navigation bar but to the general reuse of code in .NET MAUI.
I have so far watched various videos & articles on this topic, however, it is more about custom controls and did not help me. Most articles corresponded to what was conveyed in this video. I also came across this article, but it didn't help me either.
Thanks for your help :)
First, you can create a new .xaml file named Name.xaml. You can write some codes in it.
<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="CusComponents.Name">
<ContentView.Content>
<StackLayout Padding="10">
<Label Text="Name" FontAttributes="Bold" />
<Label Text="First name" />
<Entry x:Name="FirstName" Placeholder="First name" />
<Label Text="Last name" />
<Entry x:Name="LastName" Placeholder="Last name" />
</StackLayout>
</ContentView.Content>
</ContentView>
Second, you can use it in the page you want like this. You need to add an xmlns reference to the top of the XML file– this is like a using statement in a C# file. Using the namespace structure for the sample project, this will be xmlns:custom_components="clr-namespace:CusComponents".
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:custom_components="clr-namespace:CusComponents"
x:Class="CusComponents.MainPage">
<custom_components:Name />
</ContentPage>
Here is the view of the code:
I'm having a problem creating a viewmodel grid manually in Catel for a Catel usercontrol. The documentation implies that by naming the content grid "__catelInnerWrapper" that the content will not be wrapped with another grid by the ViewModelWrapperService and will use my grid instead. I'd like to do so for visual state management purposes. Using Snoopwpf I can see that the usercontrol is still being wrapped.
(https://i.imgur.com/teSu9La.png)
I tried creating a new Catel project template using Catel 5.8.0 and also 5.9.0 beta 0 using .NET 4.6.1 with a single usercontrol in the mainwindow to test a simplified application and saw the same behavior.
<catel:UserControl x:Class="CatelTest.Views.MyUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:catel="http://schemas.catelproject.com">
<Grid x:Name="__catelInnerWrapper">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label Grid.Row="0" Content="{Binding Title}" />
<Label Grid.Row="1" Content="My User Control" />
</Grid>
</catel:UserControl>
In stepping through ViewModelWrappingService.xaml.cs code it seems the usercontrol content Name property is always resolving to null and thus isn't matched with the InnerWrapperName. Do you know why this might be happening? Thank you
When looking at the source, you are doing the correct thing. If you are 100% sure that:
You are using a correct build (e.g. fully rebuilt app, not a
wrong configuration)
Snoop is correct
Then please report an issue (with minimal repro) at https://github.com/catel/catel/ and we will make sure it will be fixed in Catel 5.9 (currently in beta, about to be released but we will wait for this one).
I'm getting started learning MVVM and Catel and have i have problem how to load two user controls with data from a database.
In short, my mainwindow.xaml contains this two rows, (MainViewModel is "empty")
<catel:StackGrid x:Name="LayoutRoot" Margin="5">
<views:View1 Grid.Row="1" Grid.Column="0" Height="Auto" />
<views:View2 Grid.Row="1" Grid.Column="1" Height="Auto"/>
</catel:StackGrid>
My View1ViewModel loads fine, gets data from database and it displays in View1, however my View2ViewModel does not load.
Should i load my secondview from the firstview or should my rows above do the thing and the error is related to binding in my View2?
Any hints would be nice to get to a newbie.
There is no difference between VM1 and VM2. I see you are using a stackgrid without actually defining any rows / columns. Make sure to define those as well so the view gets actually loaded.
There is no need for you to do anything differently for view 2.
We use one theme for our desktop web page and another for responsive/mobile version of the site. But for mobile we don't always want to show images and it would be good if we can restrict it from the template, not just hiding it with CSS (because it still loads the image, just does not show it).
For that I need to get liferay current active theme ID or name so I can add simple if statement in the template.
#if(${themename} == "desktopTheme")
<img src="foo.jpg"/>
#end
Does anyone has ideas how to get it? I searched and checked lots of liferay's forums, but didn't find anything.
Thanks!
My advice would be to not hardcode the theme's name, but use theme settings that are readily available. Just configure your theme to be "desktop" or "mobile" style and check for this property. This way you can cover many different themes without hardcoding particular ones.
Also, the various ThemeDisplay.getTheme*() methods will help you to get the required information almost anywhere you are.
Here's some untested pseudo code for your themes (I just typed it here, never compiled/deployed, you might want to add null-checks for the VM stuff)
<?xml version="1.0"?>
<!DOCTYPE look-and-feel PUBLIC "-//Liferay//DTD Look and Feel 6.0.0//EN" "http://www.liferay.com/dtd/liferay-look-and-feel_6_0_0.dtd">
<look-and-feel>
<compatibility>
<version>6.1.0+</version>
</compatibility>
<theme id="my-desktop-1" name="My First Desktop Theme">
<settings>
<setting key="mobile" value="false" />
</settings>
</theme>
</look-and-feel>
<?xml version="1.0"?>
<!DOCTYPE look-and-feel PUBLIC "-//Liferay//DTD Look and Feel 6.0.0//EN" "http://www.liferay.com/dtd/liferay-look-and-feel_6_0_0.dtd">
<look-and-feel>
<compatibility>
<version>6.1.0+</version>
</compatibility>
<theme id="my-mobile-1" name="My First Mobile Theme">
<settings>
<setting key="mobile" value="true" />
</settings>
</theme>
</look-and-feel>
And then, in VM or JSPs or other code:
#if( ! $themeDisplay.getSetting("mobile"))
## more resources, desktop only, here.
#end
#if( $themeDisplay.getSetting("mobile")
## mobile only stuff here.
#end
And finally you might also want to consider to use the Device Detection API to determine the current device's actual capabilities on a far finer granularity
Suggest you to use themeId whis is also unique. its something the following:
xxx_WAR_xxxtheme
#if($themeDisplay.getThemeId().equalsIgnoreCase("<dektop theme id>"))
### your logic here
#end
HTH
I have a requirement for an application in a Domino version 9.x deployment for a carousel like interface similar to what Netflix and others use to allow continuous scrolling. I got the jQuery jCarousel code working from here. But that lacks the pizzazz the user wants since the swiping feature is not available. I also used 100% computed HTML instead of being able to intersperse XPages controls within the carousel code.
So I found dojox/mobile/carousel (examples here) but all implementations, including the basic examples are not working well. The number of elements does not seem to be flexible and the positioning of them is much lower than I would think the should be. I fiddled with the CSS to see if I could fix things but have not found the right combination.
Here is the entire custom control I am using for this test (I captured the images from the demo and added them as image resources):
<?xml version="1.0" encoding="UTF-8"?>
<xp:view
xmlns:xp="http://www.ibm.com/xsp/core"
dojoParseOnLoad="true">
<xp:this.resources>
<xp:metaData
name="viewport"
content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no">
</xp:metaData>
<xp:metaData
name="apple-mobile-web-app-capable"
content="yes">
</xp:metaData>
<xp:styleSheet
href="/.ibmxspres/dojoroot/dojox/mobile/themes/iphone/iphone.css">
</xp:styleSheet>
<xp:dojoModule
name="dojox/mobile"></xp:dojoModule>
<xp:dojoModule
name="dojox/mobile/parser"></xp:dojoModule>
<xp:dojoModule
name="dojox/mobile/Carousel"></xp:dojoModule>
</xp:this.resources>
<xp:panel>Above it</xp:panel>
<div
id="carousel1"
data-dojo-type="dojox/mobile/Carousel"
data-dojo-props='height:"150px", navButton:false, numVisible:2, title:"Category"'>
<!-- View #1 -->
<div
data-dojo-type="dojox/mobile/SwapView">
<div
data-dojo-type="dojox/mobile/CarouselItem"
data-dojo-props='src:"dish1.jpg", value:"dish", headerText:"dish"'></div>
<div
data-dojo-type="dojox/mobile/CarouselItem"
data-dojo-props='src:"glass1.jpg", value:"glass", headerText:"glass"'></div>
</div>
<!-- View #2 -->
<div
data-dojo-type="dojox/mobile/SwapView">
<div
data-dojo-type="dojox/mobile/CarouselItem"
data-dojo-props='src:"stone1.jpg", value:"stone", headerText:"stone"'></div>
<div
data-dojo-type="dojox/mobile/CarouselItem"
data-dojo-props='src:"shell1.jpg", value:"shell", headerText:"shell"'></div>
</div>
</div>
<xp:panel>Below it</xp:panel>
</xp:view>
in the sample in the documentation it has this comment followed by the inclusion of a JavaScript file.
<!-- Need to load the theme files for Carousel and PageIndicator as well as the base theme file -->
<script type="text/javascript" src="dojox/mobile/deviceTheme.js"
data-dojo-config="mblThemeFiles: ['base','Carousel','PageIndicator']"></script>
Not having this step done may be my problem but I cannot see how to do that within the XPages environment.
The dojo carousel exists since 1.7 Notes 8.5.3 comes with 1.6 (i dont know the dojo version of Notes9), so you maby have to update your dojo or implement a newer dojo lib in your application.
I did a short experiment on it, i disabled the build in dojo adding xsp.client.script.libraries=none to my xsp.properties and importet the dojo 1.9 in my application under WEB-INF/dojo/... then add the dojo to my xPage as ClientSide script resource. As soon i finished this the programatic Example from the dojo homepage worked immediately with out bigger errors (forgot to change the image sources =) ..).
The problem when adding xsp.client.script.libraries=none to your xsp.properties is that you also disable the XSP. library and some other xPage features wich you have to rebuild using the newer dojo version.
I realy prefer using dojo over jquery but in this case If you dont want to update your dojo i recomend you to maby stay at the jquery Library for this or look for other solutions.