Erhan Ballıeker

Microsoft Xamarin Türkiye Meetup – Xamarin Forms Shell

Selamlar,

Dün Microsoft Türkiye’de gerçekleştirmiş olduğumuz etkinlikte katılımcılara yeni gelen Xamarin Forms Shell den bahsetmişim. Bu yazımda buna değinmek istedim.

Öncelikle şunu belirtmek isterim ki Xamarin.Forms Shell şuan production da kullanılmaya hazır değil diye düşünüyorum. Geliştirmeler halen devam ediyor, üzerinde daha birçok değişiklik olacaktır. Ama tanımaktan denemekten zarar gelmez. Değişiklikleride hepberaber takip ederiz.

Xamarin Forms Shell i eğer VisualStudio 2019 kurduysanız bir extension paketi kurarak File-> NewProject dediğinizde Template olarak görebilirsiniz.

Template i şuradan indirebilirsiniz.

Bu visual studio extension paketini kurduğunuz da Yeni bir xamarin forms projesi açtığınızda aşağıdaki gibi karşınıza Shell Template i gelecektir.

Capture.PNG

Bunu seçip devam ettiğiniz deki kısma geleceğiz. Ama önce hali hazırda Visual Studio 2019 kurmamış olanların Shell i nasıl deneyeceklerine gelelim.

Visual Studio 2017 de yine bir xamarin forms projesi açıp başlayın.

Sonrasında yapmanız gereken ilk şey platform spesifik projelere gidip Xamarin.Forms.Forms.Init.. den önce

  • global::Xamarin.Forms.Forms.SetFlags(“Shell_Experimental”, “Visual_Experimental”, “CollectionView_Experimental”, “FastRenderers_Experimental”);

kodunu eklemeniz. Bu kod sayesinde şuan experimental olarak geçen tüm diğer özellikleri de test etmeye başlayabilirsiniz. Örneğin CollectionView uzun zamandır beklenen bir Layout idi, FlexLayout ile kısmen sorunlarımız çözüyorduk ama bunu da denemekte fayda olacaktır şimdiden.

Bundan sonra projesine bir Xaml sayfası ekleyip onu Shell sınıfından türetmeniz yeterli olacaktır. Artık sizde bu Shell dosyası üzerinde oynayabilir, çıktıları gözlemleyebilirsiniz.

Gelelim Shell in özelliklerine;

Shell in başlıca amacı şu;

  • Tüm uygulama genelindeki navigasyonları tek bir çatı altında toplayıp, sanki bir storyboard hazırlar gibi hazırlayabilmeniz.

Shell ile beraber web e yakın bir routing mekanizması da geldi. Ama varolan tüm navigaston mekanizması yani Navigaion.Push..Pop.. vs hepsi halen geçerli tabi

Şuanda temel 4 farklı tag imiz var.

Bunlar şunlar;

  • ShellItem
  • ShellSection
  • ShellContent
  • MenuItem

Bınların uygulamaya etkileri  şöyle oluyor.

Temel menülerin dizilimi yukarıda kullanacağınız tag lara göre 3 e ayrılıyor.

  • Her bir ShellItem Sol menüde ki bir Link e karşılık geliyor.
  • Bunların içinde tanımlanmış Herbir Shell Section bottombar olarak karşımıza çıkıyor.
  • Bunun da içerisinde bir yada birden çok Shell Content tanımlarsak bunlar da topbar olarak karşımıza geliyor.

Yani aşağıdaki gibi bir xaml ın menü hiyerarşisi şu şekilde oluyor.

 
<Shell xmlns="http://xamarin.com/schemas/2014/forms" 	
	   xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	
	   xmlns:local="clr-namespace:TailwindTraders.Mobile.Features.Shell" 	
	   x:Class="TailwindTraders.Mobile.Features.Shell.TheShell" 	
	   Title="TailwindTraders"> 
<ShellItem Title="Home“ Route=“Home”> 
	<ShellSection Route=“Section1“>  
		<ShellContent Route=“index”> 
			<local:HomePage1 /> 
		</ShellContent>
		<ShellContent Route=“index”> 
			<local:HomePage2 /> 
		</ShellContent>
	 </ShellSection> 
	 	<ShellSection Route=“Section2“>  
		<ShellContent Route=“index”> 
			<local:HomePage3 /> 
		</ShellContent>
	 </ShellSection> 
</ShellItem> 
</Shell>

Sol tarafta tek bir menü linki. Buna tıkladığımızda, bu sayfada altta iki tab ı olan bir bottom tab. çünkü iki adet ShellSection konulmuş. İlk taba tıkladığımızda da yukarıda 2 tane tab ı olan topbar göreceğiz çünkü bunun içerisine de iki tane shell content konulmuş.

Bunun yanı sıra Flyout dediğimiz tag in Header ve Footer ile istediğimiz gibi oynayıp sol menünün görünümünü düzenleyebiliyoruz.

Routing mekanizması şu şekilde değişiyor.

RouteScheme: Url scheme such as “http” or “app”

RouteHost: The Domain portion of the URI

Route: The base segment of your application’s URI

▪Exp: “app://microsoft.com/myapp/home/section/index”

▪(App.Current.MainPage as Shell).GoToAsync(“app:///newapp/greeting?msg=Hello”);

İstersek sayfalar arasında data taşımak için querystring bile kullanabiliyoruz 🙂

[QueryProperty("Message", "msg"]
    public partial class GreetingPage : ContentPage
    {
        public GreetingPage()
        {
            InitializeComponent();
        }
 
        string _message;
        public string Message
        {
            get { return _message; }
            set
            {
                _message = value;
            }
        }
    }

Dediğim gibi şuan için yeni başlayan projelerinizde asla başlamamanızla birlikte deneysel olarak alışmanızda fayda olduğunu düşündüğümden çok fazla detaylarına girmeden Shell den bahsetmek istedim.

Daha fazla detaylara şuradan ulaşabilirsiniz.

Bir sonraki yazımda görüşmek üzere.

Asp.Net Core 2.1 İle Gelen HttpClientFactory ve HttpClient İle Kıyaslama.

Selamlar,

Üzerinden 3 ay kadar geçmiş olsa da, Eylül 2018 de Microsoft Türkiye tarafından düzenlenen etlinlikte bahsettiğim ve uzunca zamandır, hakkında konuşmak istediğim HttpClientFactory ve HttpClient hakkında yazmaya henüz başlayabiliyorum.

Öncelikle HttpClient dan, yanlış kullanımlarından ve doğru kullanım olsa dahi handikapları nelerdi bunlardan bahsedip, sonrasında HttpClientFactory hakkında yazacağım.

Özellikle uygulamalar arasındaki haberleşme konuları, ve bu alanda kullanılabilecek yeni teknolojiler ilgi alanımda olduğu için, (Resilient network services hakkında yazılarımı buradan başlayarak okumanızı öneririm) bu konuda yazmak istediğim çok şey var.

Önce kısa bir özet geçelim. Eğer bir .net developer iseniz ve dış dünya ile haberleşecek mekanizmalar yazmanız gerekiyor ise (http üzerinden), sırası ile .netframework tarafından bize sunulan API lar şu şekilde idi;

  • HttpWebRequest
  • WebClient
  • HttpClient

Özellikle son senelerde uygulamamlarımızda bir haberleşme olacak ise dış dünya ile(http protokolü ile), kolay kullanımı ve birçok isteri yerine getirebilmesinden, async desteğinden vs çokça sebepten ilk seçenek hemen hemen herkes için HttpClient oluyor.

Aşağıda yanlışları ile birlikte kolay kullanımıına bir örnek görüyoruz. Bir for döngüsü içerisinde, tıpkı microsoft un best-practice lerinde söylediği gibi using bloğu içerisinde bir endpoint e request atıyoruz. Burada diyebilirsiniz ki, – Client ı neden for un içerisinde yazdık dışında yazalım –  doğru diyorsunuz derim. Ama gelmek istediğim nokta başka.


for (int i = 0; i < 13; i++)
{
     using (var httpClient = new HttpClient())
      {
            var result = await httpClient.GetAsync("https://randomuser.me/api?results=5");
            Console.WriteLine($"{result.StatusCode} - {result.IsSuccessStatusCode}");
      }
}

Microsoft der ki;

“Eğer bir api IDisposable dan miras alıyor ise, onu using bloğu içerisinde kullanın”

Aşağıdaki resimde görmüş olduğunuz gibi, HttpClient, HttpMessageInvoker dan o da, IDisposable dan türüyen bir sınıf. Bu durumda bu HttpClient objesini using bloğu içerisinde kullanmakta bir sıkıntı yok gibi düşünebiliriz.

Capture

Lakin ki durum öyle değildir 🙂

Netstat.exe komutunu çalıştırarak pc mizden dış dünyaya açılan Socket lerin durumuna bir bakalım.

Bu arada socket dediğimiz de anlayacağımız şudur. İki bilgisayarın birbiri ile haberleşmesi sırasında birbirlerine verdikleri adres. Sadece IP adresi yeterli değildir bunun yanında bir de port numarası önemlidir.

Ör: browser dan google.com u açtınız. Client tarafındaki socket adresi:ClientIP+60432(dynamic port number)

Aradaki bağlantı ise : ClientIP+dynamicPort —- GoogleIP+80(standart port) şeklinde olucaktır. Session bittikten sonra aynı port yeniden kullanılabilir.

Peki dönelim netstat.exe nin sonuçlarına. Aşağıda ki resimde görebileceğiniz gibi. Ben Console uygulamamı durdurmuş olsam bile yine de HttpClient objelerinin dışarıya açmış olduğu socket lerin TIME_WAIT state inde bekliyor olduklarını görüyorum.

Capture.PNG

Yani aslında client tarafı connection ı kapamış ama eksik kalan paketler olabilmesi vs adına halen socket ler açık.Windows için global olarak bu bekleme süresi 240 sn.

Bu değeri değiştirmemiz mümkün;

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\TcpTimedWaitDelay

ile yeni istediğimiz değeri set edebiliriz.Peki bu şekilde bir kullanım sonunda uygulamanın herhangi bir t anında alabileceğimiz muhtemelen hata nedir?

System.Net.Sockets.SocketException

Peki önce bu genel HttpClient kullanım hatasının çözümüne gelelim. Çözüm aslında basit. Singleton bir HttpClient kullanmak.

private static HttpClient client = new HttpClient();

for (int i = 0; i < 13; i++)
{
	var result = await client.GetAsync("https://randomuser.me/api?results=5");
       Console.WriteLine($"{result.StatusCode} - {result.IsSuccessStatusCode}");
}

Peki client ı singleton yaparak farklı farklı httpclient objeleri oluşturmaktan ve dolayısı ile aslında kapanmış olan connectionların açtığı boşuna bekleyen açık socket israfından kurtulmuş oluyoruz. Fakat bu da beraberinde farklı sorunlar getiriyor.

Bu durumda longlived HttpClient lar yüzünden DNS değişikliği veya Azure tarafında otomatize edilmiş Staging-Production ortamları arasındaki geçişlerde halen eski adreslere gitme vs vs gibi farklı sorunlar karşımıza çıkıyor.

Bunlara da çözüm olarak; DefaultRequestHeaders. ConnectionClose true diyerek http keep-alive-header = false göndermek ve ya ServicePointManager api sini kullanarak kuracağımız bağlantı üzerinde daha low level ayarlar yapmak da mümkün. Fakat herkes tarafında net olarak evet çözüm budur denen bir durum yok.

Client.DefaultRequestHeaders.ConnectionClose = true;

var sp = ServicePointManager.FindServicePoint(new Uri(” https://randomuser.me/api?results=5 “)); 

sp.ConnectionLeaseTimeout = 60*1000;

aşağıdaki github issue sunda konuşulan sıkıntıları fikir sahibi olmanız açısında okumanızı öneririm

https://github.com/dotnet/corefx/issues/11224

Peki gelelim HttpClientFactory e. Bu Asp.net core 2.1 ile gelen api bize neler sunuyor bir bakalım.

HttpClientFactory

Bu api aslında şuan .net dünyasında bir haberleşme durumunda kullanmanız gereken en taze iyi api diyebilirim. Yani henüz başlamadı iseniz kullanmaya, bundan sonraki tüm Asp.Net Core projelerinizde kullanmaya başlamanızı şiddetle tavsiye ederim.

4 temel özelliğinden bahsedebiliriz;

  1. Tüm haberleşmenin merkezi bir şekilde tanımlanma ve konfigüre edilmesi imkanını sunuyor bize
  2. Refit, polly gibi .net foundation dünyasında önemli yeri olan kütüphanelerin extensionları yazıldı bile. Poly-based middleware extensionlar ve delegating handler lar ile request ve responselar üzerinde istediğimiz oynamaları yapabiliyoruz. Bir çeşit interceptor gibi düşünebilirsiniz.
  3. Yukarıd da bahsettiğim HttpClient görünümlü sıkıntıların asıl sebebi aslında HttpClientHandler.  HttpClienFactory de bu HttpClientHandler ın lifetime ını pooling mekanizması sayesinde daha doğru yönettiği için yukarıdaki sıkıntılardan da kurtulmuş oluyoruz.
  4. Kendi Factorysi tarafından oluşturulmuş tüm request ve responların loglanması otomatik olarak sağlanıyor.

 

Peki HttpClientFactory bu sorunlara nasıl çözüm getiriyor?

Şöyleki;

  • HttpClientHandler instance ları pool a alınır ve lifetime ları yönetilir. Default 2 dakika süre ile bu pool da yeni oluşturulmuş olan HttpClient instancelarının kullanımına hazır halde beklerler.HttpClient instance ları yaşadığı sürece, HttpClientHandler da yaşar.
  • 2 dakika sonra expired olarak işaretlenirler. Dolayısı ile, CreateClient ile yeni bir HttpClient instance I oluşturulduğunda, onun kullanabileceği durumda olmaz. Hemen dispose olmaz, çünkü başka dispose olmamış HttpClient ların önceden kullanımına alınmış olabilir.
  • HttpClientFactory, arkada bir background service kullanır ve expire olarak işaretlenmiş ClientHandler I takip eder. Artık referans edilmediklerinde de dispose eder ve connectionları kapar.
  • Pooling feature sayesinde, Socket exhaustion riskini azaltır. Refreshleme mekanizması da DNS update I gibi problemlere (long lived httpclienthandler lar yok artık =) ) çözüm getirir.

HttpClientFactory nin 4 farklı kullanım şekli mevcut.

  • Basic Usage
  • Named Clients
  • Typed Clients
  • Generated Clients

 

Teoril olarak HttpClient ve HttpClientFactory hakkında biraz bahsettikten sonra bundan sonraki yazılarımda bu farklı kullanım şekillerini göreceğiz.

Bir sonraki yazımda görüşmek üzere.

Xamarin Forms 3.0, 3.1, 3.2, 3.3 Yeni Gelen Özellikler

Selamlar

Geçen haftalarda Microsoft Türkiyede yapmış olduğumuz etkinliğin ikinci oturumunda anlatıığım ve göstermiş olduğum Xamarin.Forms a 3.0 – 3.3 arası yeni gelen ve hayatı çok daha kolaylaştıran özelliklerden bahsetmek istiyorum.

Xamarin.Forms 3.0 Özellikleri

Bu major versiyonla ile beraber hayatımıza yepyeni bir layout ve küçük ölçekte de olsa yeni güzellikler geldi. En temel yenilikleri aşağıdaki gibi inceleyebiliriz.

  • Visual State Manager
  • FlexLayout
  • StyleSheets
  • Right-To-Left Localization

Detaylı örneklere bakmadan önce diğer versiyonlarda hayatımıza neler girmiş bunlara bakalım. Ve hepsinin kullanıldığı bir uygulama ile örneklendirelim.

Xamarin.Forms 3.1 Özellikleri

Hayatımıza 3.1 versiyonu ile küçük gibi gözükse de birçok custom renderer dan bizi kurtaracak özellikler girdi Bunlar şöyle;

  • Android Bottom Tabs
  • Hide ScrollView scroll Bars
  • Bindable Span
  • Autoresizable Editor
  • Add SelectionMode Property To ListView

bunların dışında diğer detyalara buradan ulaşabilirsiniz.

Xamarin.Forms 3.2 Özellikleri

Burada en göe çarpan 2 özellik var bence. Birincisi Page Title View ını artık istediğimiz gibi edign edebiliyor olmamız. Diğeri SwipeGestureRecognizer.

  • SwipeGestureRecognizer
  • Rounded Corners on BoxView
  • Padding on Buttons
  • Page TitleView

yine çoğu zaman custom rendererlar ile yazmak durumunda kaldığımız birçok şeyden kurtulmuş durumdayız.

Son olarak da 3.3 ile hayatımıza neler girdi buna bakalım.

Xamarin.Forms 3.3 Özellikleri

Bu versiyonda, birçok etkinlikte duyduğum, xamarine başlarken garip bir şekilde insanların uzaklaşmasına sebep olan Label ve özelliklerine abanmışlar gibi. Aşağıda yeni özellikleri listeliyorum.

  • Max Lines on Label
  • Label with Wrap/LineNumber and Truncation
  • Label underline/strikethrough support
  • Use WKWebView on iOS

Bu özelliklerin çoğunu kullandığımı bir demo örneği ve kodları üzerinden gidelim istiyorum. Meetupda göstermiş olduğum ve insanların oldukça hoşuna gitmiş olan çok yaratıcı örneğimin adı Confinsta(bir instagram çakması arayüz) idi. Instagramın arayüzünün birçok ekranını xamarin.Forms ve yeni gelen özellikleri ile nasıl oluşturduğumu göstermek için bu örneği hazırlamıştım.

ÖRneği hazırlamak yaklaşık olarak 1 iş günümü aldı.

Arayüz ler şu şekilde.

5 temel sayfa üzerinde uğraştım. Kodların neler olduğunu bakacağız zaten ama özetlemem gerekirse, bu sayfalar ve yeni gelen xamarin forms özelliklerinden, yardımcı olacak pluginler den kullandıklarım şunlar;

  1. Ana Sayfa: Burada şimdiye kadar kullandıklarınızdan farklı özel bir şey yok. Sadece yardımcı birkaç plugin var. Bunlar;
    1. ImageCircle
    2. MediaManager
    3. CarouselView
    4. Page TitleView
  2. Explore Sayfası: Burada zaman kazandıran en güzel yeni özelliğimiz FlexLayout
    1. Rg.Plugins.Popup
    2. FlexLayout
    3. SwipeGestureRecognizer
  3. Like Sayfası: Burada tab geçişlerinin yukarıda ve swipe lı olabilmesi için syncfusion ın TabView ını kullandım.
    1. Syncfusion.XForms.TabView
    2. ImageCircle
    3. FlexLayout
    4. Bindable Span
  4. Follow Sayfası: Basit bir listview. Sycnffusion TabView ının ikinci tabı oluyor  zaten bu sayfa.
    1. Bindable Span
  5. Profile: Bu sayfanın da tasarımında çok sağdan açılan hamburger menu dışında bir özellik olmadığından sadece o kısmı ekledim.
    1. SlideOverKit

exp1exp2exp3follow1follow2likemain1main2pro1pro2

 

Tüm resimlerin yanında yukarı birde uygulamanın akışını görebilmeniz için kısa bir video koydum. Unutmayın yalnızca 1 iş günü ayrılmış bu ekran prototipleri bence gayet güzel gözüküyor. Xamarin.Forms ile yapabileceklerinizin gücünü anlamamız için yeterli bence.

Bir sonraki yazımda her bir sayfanın kod taraflarında detaylarına girip, hem xamarin in yeni özelliklerini göreceğiz hem de varolan özelliklerinden nasıl faydalanmışız bunlara bakacağız.

Görüşmek üzere.