{"id":43680,"date":"2019-03-28T12:01:13","date_gmt":"2019-03-28T19:01:13","guid":{"rendered":"https:\/\/blog.xamarin.com\/?p=39293"},"modified":"2019-08-30T08:34:35","modified_gmt":"2019-08-30T15:34:35","slug":"glidex-fast-images-android","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/xamarin\/glidex-fast-images-android\/","title":{"rendered":"GlideX For Fast Images on Android"},"content":{"rendered":"<p>\t\t\t\tGetting good image performance on Android has traditionally been a difficult task. Google has some <a href=\"https:\/\/developer.android.com\/topic\/performance\/graphics\/manage-memory.html\">documentation<\/a> on the subject, which unfortunately mentions some complex topics:<\/p>\n<ul>\n<li>Cache and recycle bitmaps in memory<\/li>\n<li>Java classes named <em>LruCache<\/em> and <em>MutableSet&lt;SoftReference&lt;Bitmap&gt;&gt;<\/em>?<\/li>\n<li>Specific cases for older Android versions<\/li>\n<\/ul>\n<p>This is not the type of problem developers want to be focusing on&#8211;they just want to build their app!<\/p>\n<p>To explain the problem further, let&#8217;s imagine a Xamarin.Forms page with\u00a0<em>lots\u00a0<\/em>of images (<em>MainPage.xaml.cs<\/em>):<\/p>\n<pre class=\"lang:c# decode:true\">public partial class MainPage : ContentPage\r\n{\r\n    public MainPage()\r\n    {\r\n        InitializeComponent();\r\n\r\n        var uri = new Uri(\"https:\/\/pbs.twimg.com\/media\/DZ_B8cEU8AASnUI.jpg\");\r\n        for (var i = 0; i &lt; 100; i++)\r\n        {\r\n            MainGrid.RowDefinitions.Add(new RowDefinition { Height = 100 });\r\n\r\n            for (var j = 0; j &lt; 4; j++)\r\n            {\r\n                var image = new Image\r\n                {\r\n                    Source = ImageSource.FromUri(uri)\r\n                };\r\n                Grid.SetRow(image, i);\r\n                Grid.SetColumn(image, j);\r\n                MainGrid.Children.Add(image);\r\n            }\r\n        }\r\n    }\r\n}<\/pre>\n<p>With the following <em>MainPage.xaml<\/em>:<\/p>\n<pre class=\"lang:xhtml decode:true \">&lt;?xml version=\"1.0\" encoding=\"utf-8\" ?&gt;\r\n&lt;ContentPage xmlns=\"http:\/\/xamarin.com\/schemas\/2014\/forms\"\r\n             xmlns:x=\"http:\/\/schemas.microsoft.com\/winfx\/2009\/xaml\"\r\n             x:Class=\"HelloGlide.MainPage\"&gt;\r\n    &lt;ScrollView Padding=\"0\"&gt;\r\n        &lt;Grid x:Name=\"MainGrid\" ColumnSpacing=\"0\" RowSpacing=\"0\"&gt;\r\n            &lt;Grid.ColumnDefinitions&gt;\r\n                &lt;ColumnDefinition \/&gt;\r\n                &lt;ColumnDefinition \/&gt;\r\n                &lt;ColumnDefinition \/&gt;\r\n                &lt;ColumnDefinition \/&gt;\r\n            &lt;\/Grid.ColumnDefinitions&gt;\r\n        &lt;\/Grid&gt;\r\n    &lt;\/ScrollView&gt;\r\n&lt;\/ContentPage&gt;<\/pre>\n<p><em>Note, you would not really want to implement a screen like this in a Xamarin.Forms application. <a href=\"https:\/\/docs.microsoft.com\/en-us\/xamarin\/xamarin-forms\/user-interface\/listview\/\">ListView<\/a> or <a href=\"https:\/\/docs.microsoft.com\/en-us\/xamarin\/xamarin-forms\/user-interface\/collectionview\">CollectionView<\/a> are much better options!<\/em><\/p>\n<p>This example code presents 400 images of a strange man in a\u00a0<em>ScrollView <\/em>(non-virtualized):<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/devblogs.microsoft.com\/xamarin\/wp-content\/uploads\/sites\/44\/2019\/03\/glidex-before.gif\" alt=\"\" width=\"254\" height=\"428\" class=\"aligncenter size-full wp-image-40800\" \/><\/p>\n<p>Especially in an emulator, the performance while scrolling this <em>ScrollView<\/em> is not the best. The Xamarin.Forms team has done a great job improving the performance of a page like this in recent releases&#8211;but is there a way to do better?<\/p>\n<h2>Glide: an image library for Android focused on smooth scrolling<\/h2>\n<p><a href=\"https:\/\/developer.android.com\/topic\/performance\/graphics\/manage-memory.html\">Google&#8217;s response<\/a> to this complexity problem is to use a Java library named Glide:<\/p>\n<pre class=\"lang:diff decode:true\">Note: For most cases, we recommend that you use the Glide library to\r\nfetch, decode, and display bitmaps in your app. Glide abstracts out\r\nmost of the complexity in handling these and other tasks related to\r\nworking with bitmaps and other images on Android. For information\r\nabout using and downloading Glide, visit the Glide repository on\r\nGitHub: https:\/\/github.com\/bumptech\/glide<\/pre>\n<p>Glide has a nice, fluent API for loading bitmaps in Java:<\/p>\n<pre class=\"lang:java decode:true \">GlideApp\r\n    .with(myFragment)\r\n    .load(url)\r\n    .centerCrop()\r\n    .placeholder(R.drawable.loading_spinner)\r\n    .into(myImageView);<\/pre>\n<p>Glide handles a lot of details for you:<\/p>\n<ul>\n<li>Downloads images from URLs<\/li>\n<li>Handles device rotation<\/li>\n<li>Handles in-memory and on-disk caching<\/li>\n<li>Can crop, place a loading indicator, etc.<\/li>\n<\/ul>\n<p>So if Glide is written in Java, how do we use it in Xamarin.Forms?<\/p>\n<p>To unlock the power of Glide, I created &#8220;GlideX&#8221;: a simple library to swap-in Glide&#8217;s image loading implementation in-place of what Xamarin.Forms ships in the box. This began as an experiment, but perhaps one day could be the default for Xamarin.Forms?<\/p>\n<h2>How do I use GlideX in my Xamarin.Forms app?<\/h2>\n<p>This part is pretty easy:<\/p>\n<ul>\n<li>Add the <a href=\"https:\/\/www.nuget.org\/packages\/glidex.forms\/\">glidex.forms<\/a> NuGet package to the Android project in your solution.<\/li>\n<li>Add one line of code to initialize GlideX.<\/li>\n<\/ul>\n<p>In your\u00a0<em>MainActivity.cs<\/em>:<\/p>\n<pre class=\"lang:c# decode:true \">public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity\r\n{\r\n    protected override void OnCreate(Bundle savedInstanceState)\r\n    {\r\n        TabLayoutResource = Resource.Layout.Tabbar;\r\n        ToolbarResource = Resource.Layout.Toolbar;\r\n\r\n        base.OnCreate(savedInstanceState);\r\n        Xamarin.Forms.Forms.Init(this, savedInstanceState);\r\n        \/\/ Add this line, that's it!\r\n        Android.Glide.Forms.Init();\r\n        LoadApplication(new App());\r\n    }\r\n}<\/pre>\n<p>And behold! smooth scrolling!<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/devblogs.microsoft.com\/xamarin\/wp-content\/uploads\/sites\/44\/2019\/03\/glidex-after.gif\" alt=\"\" width=\"254\" height=\"428\" class=\"aligncenter size-full wp-image-40799\" \/><\/p>\n<p>For a complete example, see my <a href=\"https:\/\/github.com\/jonathanpeppers\/HelloGlide\">HelloGlide sample on Github<\/a>.<\/p>\n<h2>Future plans<\/h2>\n<p>Try out GlideX today, and let us know how it works in your apps!<\/p>\n<ul>\n<li>File any issues you find using <a href=\"https:\/\/github.com\/jonathanpeppers\/glidex\/issues\">GlideX on Github.<\/a><\/li>\n<li>Track our progress on using <a href=\"https:\/\/github.com\/xamarin\/\/issues\/3577\">Glide in Xamarin.Forms here<\/a>.<\/li>\n<\/ul>\n<p>For a complete demo, check our episode about GlideX on the Xamarin Show:<\/p>\n<p><iframe src=\"https:\/\/channel9.msdn.com\/Shows\/XamarinShow\/Super-Fast-Image-Loading-for-Android-Apps-with-GlideX\/player\" width=\"560\" height=\"315\" allowFullScreen frameBorder=\"0\"><\/iframe><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Unlock the power of Glide with \u201cGlideX\u201d: a simple library to swap-in Glide\u2019s image loading implementation in-place of what Xamarin.Forms ships in the box.<\/p>\n","protected":false},"author":1345,"featured_media":43720,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[313,2],"tags":[5,648,16],"class_list":["post-43680","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-android","category-developers","tag-android","tag-performance","tag-xamarin-forms"],"acf":[],"blog_post_summary":"<p>Unlock the power of Glide with \u201cGlideX\u201d: a simple library to swap-in Glide\u2019s image loading implementation in-place of what Xamarin.Forms ships in the box.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/43680","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/users\/1345"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/comments?post=43680"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/43680\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/media\/43720"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/media?parent=43680"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/categories?post=43680"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/tags?post=43680"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}