Makale Özeti

Bu makalemizde günlük hayatta birçok noktada işimize yarayabilecek ; mobil cihazlar üzerinde çalışacak olan bir Mobil Rss Reader uygulaması geliştireceğiz.

Makale

Son günlerde birçok blog, forum, haber ve benzeri amaçlar üzerine kurulmuş internet siteleri ya da  portalları üzerinde RSS yayını adı altında bir servis standart internet ziyaretçilerine hizmet vermektedir.   ikonu bulunan sitelerde kullanıcılar diledikleri taktirde bu RSS kaynaklarını RSS destekli uygulamalar üzerine kayıt ettirebilmekte ; site üzerinden herhangi bir noktada gerçekleştirilen bir güncelleme ile ilgili bu RSS kaynağından ; dolayısıyla RSS işleyen uygulamalar üzerinden haberdar edilmektedirler. Peki nedir bu kadar meşhur olan bu RSS ? O’ nu bu kadar kullanılması cazip kılan kavramlar nelerdir ? Bu noktada biraz bu soruların cevaplarını arayalım.

Öncelikle şunu belirtmek gerekirki RSS, belli bir zaman süreci içerisinde isim açılımı bakımından belli bir değişime uğramıştır. İlk standartatize versiyonundan itibaren RSS internet üzerinde ;

  • Rich Site Summary (RSS 0.91)
  • RDF Site Summary (RSS 0.9 and 1.0)
  • Really Simple Syndication (RSS 2.0.0)

şeklinde ifade edilebilecek farklı akronimler üzerinden tanımlanmaktadır.

RSS, temel amacı bakımından, “bu kaynağı sunan internet sitelerinin bu kaynak üzerinden sunulan içeriklerini daha rahat takip edebilmek için oluşturulmuş standartize bir XML dökümanı & XML Formatı” olarak ifade edilebilmektedir.

RSS kaynağı üzerinden içeriklerini dağıtan internet siteleri dünya üzerinde geliştirilmiş olan neredeyse tüm RSS okuyucuları için standartize edilmiş bazı temel kuralları uygulamış olmaları gerekmektedir.

Bu temel kuralların başında RSS kaynağı üzerinden yayını yapılan XML dökümanının bazı temel element isimlerine sahip olmaları gerekmektedir. Bu temel element isimleri üzerinden RSS kaynağınızı dünya üzerindeki neredeyse birçok RSS okuyucusu destek verebilir ; ziyaretçiler bu uygulamaları üzerinden siteniz üzerinden yayını yapılan RSS kaynaklarına erişebilirler.

Peki nedir bu temel kurallar diye sorarak makalemizin teorik kısmına bu noktada devam edelim. Bir önceki paragrafta doğru bir RSS dökümanı içerisinde mutlak surette olması gereken bazı elementlerden bahsetmiştik. Bu elementler dünya üzerinde birçok RSS kaynağı tarafından kabul edilmiş ; birçok uygulama tarafından da tanınmaktadır.  Bu temel element isimlerini kısaca açıklamak gerekirse ;

Bir RSS dökümanı içerisinde bulunması muhtemel XML Tag isimlerini ifade edebilmek açısından örnek bir RSS çıktısı görüntülemek daha doğru olacaktır. Ekran görüntüsü makalemizde de kullanacak olduğumuz Hürriyet Gazetesi RSS Kaynağı içerisindeki bir haberin RSS çıktısıdır.

Şekilden de anlaşılabileceği üzere, üzerinde çalışacak olduğumuz RSS kaynağının adresi, logosu ve açıklamasıyla ilgili XML Tag’ lerinin altında standartize ve tekrar ederek giden bir Tag betiği bulunmaktadır.

Her bir haber <item></item> tag’ leri ile ifade edilirken her <item></item> tag’ leri arasında bilginin başlığı, varsa açıklaması, kaynak adresi ve yayınlanma tarihi bulunmaktadır.

Bu noktada belirtilmiş olması gereken en önemli nokta ise bu sayılan tag’ lerin birçok RSS kaynağında standart bir şekilde bulunacağı ; spesifik durumlarda yeni tag’ lerinde eklenebileceği olduğudur.

Evet, RSS ile ilgili temel seviyede bilgi sahibi olduktan sonra yavaş yavaş makalemizin asıl konusuna doğru geçiş yapalım. Amacımız dünya üzerindeki standart bir RSS okuyucusunun yaptığı gibi yukarıda örneği ifade edilen bir RSS kaynağını standartların dışında çok farklı bir ortamdan ; “Mobil Cihazlar” üzerinden okuyup kullanıcıya gün içerisinde yolda ya da bulunduğu herhangi bir lokasyonda haberleri takip etmesini sağlayacak bir Mobil RSS Okuyucusu geliştireceğiz.

Bu makale süresince .Net Compact Framework 2.0 üzerinde birçok farklı kavram üzerinde bilgi sahibi olup böyle bir uygulama içerisinde uygulayarak tecrübe sahibi olacağız.

Hiç vakit kaybetmeden uygulama senaryomuz üzerinde bilgi sahibi olalım.

Amacımız Mobil Cihaz kullanıcılarının diledikleri her noktada Hürriyet Gazetesinin RSS Kaynağı üzerinden farklı kategoriler üzerinden sunulan haber başlıklarına ulaşabilmeleri için bir RSS Okuyucusu oluşturmak olacaktır. Bu noktada uygulama tasarımı bakımından birtakım problemlere karşın bazı önlemler almamız gerekmektedir.

Üzerinde çalışacak olduğumuz kavram internet erişiminin o anki performansı ile doğru orantılı olarak çalışacağından uygulamayu kullanacak olan kullanıcılar RSS Servisine istekte bulunduğunda sonuç gelene kadar beklememesi gerekmektedir. Bu noktada işin içerisine Asenkron Mimari girmektedir. Uygulamamız içerisinde uzak noktaya yapacak olduğumuz çağrıların tümü “Asenkron Mimari” üzerinden geliştirilecektir. Böylece tek bir makale üzerinden Xml, Threading ve RSS kavramlarını öğrenmiş olacağız.

Hiç vakit kaybetmeden makalemizin konusunu oluşturan uygulamamızı geliştirmeye başlayabiliriz. Bu noktada uygulamamız Windows Mobile 5.0 işletim sistemi ile çalışan Pocket PC cihazları için geliştirilecektir. Bunun için sistemimize Mobile 5.0 SDK’ nın yüklü olduğunu varsayarak bir C# Smart Device Mobile 5.0 Projesi açıyoruz.

Bir sonraki adımda ise yavaş yavaş uygulama ekranımızı tasarlamaya başlayabiliriz. Bu noktada uygulama içerisinde gerçekleştirmek istediğimiz senaryoda kullanıcı Hürriyet Gazetesinin RSS Kaynaklarıyla ile ilgili kategorileri bir ComboBox içerisinden seçip ; bir sonraki adımda ComboBox’ ın altında bulunan ListView kontrolü içerisinde kolon bazlı bir yapı üzerinden seçilen kategorideki haberleri görüntüleyecektir. İşin programatik kısmına geçmeden önce bu noktada Hürriyet Gazetesinin RSS Kaynağı ile ilgili adreslerden bahsetmek daha doğru olacaktır.

Hürriyet Gazetesi RSS Kaynağı olarak farklı adresler üzerinden farklı kategorilerde kaynaklar sunmaktadır.

http://dosyalar.hurriyet.com.tr/rss/ adresinde ifade edildiği üzere Hürriyet Gazetesi RSS Servisi şekildeki adresler ve katerogiler üzerinden kullanıcılara RSS Kaynağı sunmaktadır.

Amacımız bu noktada kullanıcıya ComboBox içerisinden şekilde sol tarafta sıralanmış olan kategorileri seçtirtmek ; bir sonraki adımda ise sağ tarafta bulunan adresler üzerinden RSS kaynağını almak olacaktır. Bu noktada şekildeki form tasarımı üzerinden uygulamamıza devam ediyoruz :

Şekildende anlaşılabileceği üzere form üzerine Bir ComboBox, View Özelliği “Details” olarak belirtilmiş bir ListView ve En alta seçili haber ile ilgili detay bilgiyi gösterecek “ReadOnly” bir metin kutusu ekledik. Bu noktada standart olarak eklenen MainMenu kontrolü içerisine iki adet MenuItem eklemiş bulunmaktayız.

Ayrıca şunuda belirtmemiz gerekmektedirki Details görünümünde çalıştırılacak olan ListView kontrolümüzün içerisine RSS Kaynağı üzerinden getirilen bilgilerin Başlık Ve Tarih bilgilerini ekran üzerinde gösterebilmemiz için iki adet kolon eklemiş bulunmaktayız.

Ve sıra geldi kodların geliştirilmesine. Bu noktada dikkatli olmamiz ; tasarimsal olarak herhangi bir hataya maruz kalmamamız gerekmektedir.

Senaryoya baktığımızda ilk noktadaki amacımız kullanıcıya ComboBox içerisinden RSS Kaynağı üzerinden sunulan Haber Kategorilerini seçtirtmek olacaktır. Bu noktada gerçekleştirmemiz gereken ilk eylem ComboBox’ ın içerisine bu kategorileri eklemek olacaktır. Fakat ComboBox’ ın Items collection’ı içerisinde bulunan Add metoduna baktığımızda metodun tek bir kere tanımlandığı ve bu tanımlanan versiyonunda uygulama geliştiriciden “object” tipinde bir parametre beklediğini görmekteyiz.

Tasarımsal olarak bu noktadaki amacımız, kullanıcının “AnaSayfa”, “Gündem” şeklinde anlaşılır kategori isimlerini görmesini isterken, arka tarafta seçili kategorinin RSS Adresine istekte bulunmak olacaktır. Olaya bu açıdan baktığımızda içerisinde iki adet bilgiyi depolayabilen ; Adres Ve İsim bilgisini depolayabilen bir sınıf tipine ihtiyaç duymaktayız.

Bu problemin çözülebilmesi için .Net Compact Framework üzerinde Key – Value mantığıyla çalışan birçok tip bulunmasına rağmen kendi özelleştirilmiş tipimizi oluşturmak tasarımsal oalrak daha doğru olacaktır.

Şekildeki sınıfı oluşturarak uygulamamıza devam ediyoruz :

Şekildende anlaşılabileceği üzere standart olarak bir RSS Adresini ifade edebilecek özelliklere sahip bir sınıf oluşturmuş bulunmaktayız. Sınıfın içerisinde bir RSS’ in görsel ismi ve adresini barındırabilecek iki adet özellik ve parametreli bir yapıcı metot (Constructer) bulunmaktadır.

Ayrıca “object isteyen görsel görsel objelerinde kullanabilmesi amacı ile” ToString() metodunu override edere metottan sınıfın içerisindeki Isim_ değişkeninin değerinin dönmesini sağlamış bulunmaktayız.

Bir sonraki adımda Form’ umuzun Load olayı gerçekleştiğinde ComboBox içerisine Hürriyet Gazetesi RSS Kaynağı üzerinden sunulan adresleri geliştirdiğimiz sınıfın constructer’ ı üzerinden oluşturarak ekliyoruz.

ComboBox içerisine eklenen objelerin otomatik olarak ToString() metodunu çalıştıracak ve ekran üzerinde eklenen RSS Kaynağının ismini görüntüleyecektir.  Fakat bizimde bildiğimiz üzere o noktada bir string olmadığı bir RssKaynagi objesi bulunmaktadır. Gerektiğinde objeyi bulunduğu yerden çekeren tip dönüşümüne sokarak seçili Kategorinin adresini alacağız.

Uygulamayı herhangi bir kod daha yazmadan bu haliyle Emülatörümüz üzerinde çalıştırdığımızda :

Listeden Pocket PC Emulator ‘ u seçiyoruz ve uygulamamızı Deploy ediyoruz.

Ve uygulama ekranı içerisinde kategoriler başarıyla listelenmiştir. Bu noktada kullanıcılar ComboBox içerisinde Kategori adlarını görmelerine rağmen bu liste elemanları arka taraflarında adres bilgilerinide barındırmaktadırlar.

Hızlı bir şekilde kaldığımız yerden devam edelim.

Uygulama içerisindeki amacımız uzak noktadan gelen RSS bilgilerini mobil cihazın memory’ si üzerinde depolamak ve bu depolanan verileri uygun noktalara eklemek olacaktır. Bu amaçla RSS kaynağı üzerinden gelen XML verilerini mobil cihazın belleği üzerinde depolayabilmek amacı ile System.Xml namespace’ i altında bulunan XmlDocument sınıfından yararlanacağız.

XmlDocument sınıfı, yapısı gereği instance’ ı oluşturulduktan sonra hafıza üzerinde DOM yapısına uygun oluşturulan XML verileri üzerinde dolaşabilmektedir. Ayrıca içerisindeki –ki makalemizde bu metot üzerinden yapıyı çalıştıracağız- GetElementsByTagName metodu üzerinden uygulama geliştirici metoda parametre değeri olarak gönderilen element ismine sahip tüm XmlNode objelerini XmlNodeList tipinde geri dönüş değeri olarak alabilmektedirler.

Bu amacı gerçekleştirmek adına globalde bir XmlDocument referansı ; uygulama ekranı yüklendiğinde ise bu referansın instance’ ını oluşturuyoruz.

Ayrıca metot üzerinden gelecek olan XmlNode dizisini taşıyabilmesi için bir XmlNodeList referansını yine global’ de tanımlıyoruz.

Bir sonraki adımda Form yüklendiğinde XmlDocument objesini oluşturuyoruz :

Bir sonraki adımda her kategori seçiminde çalışacak olan Thread objesinin başlatılacağı zaman gidip çalıştıracağı ; seçili kategorinin adres bilgisini kullanarak uzak noktadan RSS bilgilerini çekecek olan HaberleriYukle() isimli bir metot ve bu metodun çalıştırılmasında tetikleyici rolü oynayacak olan ComboBox’ ın seçili kategori değeri değiştiğinde çalışacak olan kod bloklarını geliştiriyoruz. Şekildeki kod bloğu üzerinden uygulamamıza devam ediyoruz :

Öncelikle globalde Thread sınıfının bir referansını tanımlıyoruz.

Ve bir sonraki adımda ayrıntılı açıklanacak olan şekildeki kod bloklarını geliştiriyoruz :

Kod bloklarını ayrıntılı olarak incelediğimizde ilk olarak ComboBox’ ın seçili indeks değeri değiştiğinde global olarak tanımlı olan AktifRssAdresi isimli değişkene seçili olan ComboBox objesini RssKaynagi tipine dönüştürdükten sonra Adres değerini alıp eşitliyoruz. Bunu gerçekleştirmemizin sebebi bir sonraki adımda farklı bir thread içerisinden farklı bir thread içerisindeki bir objenin özelliğine erişmeye çalışırken yaşayacak olduğumuz CrossThreadOperationException’ dır. Bunu yaşamamak adına kontrolün değerini diğer thread’ e geçmeden önce her iki thread’ inde erişebileceği güvenli bir string değişken üzerine taşıyoruz.

Daha sonraki satırda global Thread referansını oluşturup içerisine bizden istediği ThreadStart isimli delege instance’ ını gönderiyoruz. Bu delege sadece parametre almayan ve void geri dönüş değerine sahip metotları adresleyebilmektedir. Zaten HaberleriYukle metodumuzun tanımlanma amacıda aslında  bu olmaktadır. Thread’ i tanımladıktan sonra sonra ise Thread sınıfının Start metodu üzerinden Thread’ i başlatıyoruz.

Bir sonraki adımda HaberleriYukle isimli metodumuz oluşturulmuştur. Bu metot içerisinde Form yüklendiğinde objesi oluşturulmuş olan XmlDocument sınıfının Load metodu içerisinden uzaktan gelen RSS bilgilerini mobil cihazımızın memory’ si üzerinde oluşturulmasını sağlıyoruz. Ve sıra geldi en önemli noktaya.

Şekilden de anlaşılabileceği üzer rssDOC isimli XmlDocument objesinin GetElementsByTagName isimli metoduna parametre değeri olarak “item” bilgisini vererek metodumuzu çalıştırıyoruz. Metot sonucunda kullanıcıya kaynak üzerinden gelen tüm <item> elementlerini içerisindeki diğer child element’ ler ile birlikte XmlNodeList olarak döndürmektedirler.

Daha sonra bu XmlNodeList referansı üzerinden içerisindeki her bir XmlNode objesi için yeni bir ListViewItem objesi oluşturulmakta ; içerisine ikinci bir SubItem eklenmekte ve bu SubItem’ ların Text’ lerine sırasıyla başlık ve yayınlanma tarihi bilgileri eklenmektedir. Ayrıca ListViewItem üzerine tıklatıldığında tıklanan haberin detayını alabilmek bakımından ListViewItem objesinin Tag özelliğine XmlNode objesinin kendisi verilmektedir –ki gerektiği noktalarda haberin tüm elementlerini bu özellik üzerinden gelen XmlNode objesi üzerinden alabilelim.

Son olarak enteresan bir yapı üzerinden kod bloğunu tamamlıyoruz. Normal şartlarda listView1.Items.Add metodu üzerinden yeni oluşturulmuş olan ListViewItem objesini Add metoduna göndermemiz bu noktada yeterli olacaktır. Fakat bu işlemleri farklı thread üzerinde gerçekleştirdiğimizi göz önünde bulundurur isek Main Thread üzerinde oluşturulmuş olan listView1 kontrolüne Worker Thread üzerinden “Thread Güvenliği” bakımından erişememekteyiz. Bu amaca uygun olarak işlemi listView1 kontrolünün ilk oluşturulmuş olduğu Thread üzerinde gerçekleştirebilmek için listView1 kontrolünün Invoke metodunu kullanmamız gerekmektedir. Bu metodun sonucunda işlem listView1 kontrolünün ilk olarak oluşturulduğu thread üzerinde gerçekleştirilecektir.

Invoke metodunun yapısına baktığımızda ise hangi metodun Invoke edileceği ile ilgili Invoke edilecek olan metodun adresini üzerinde barındıran bir delege objesi bizden istemektedir. Amacımız listView1 kontrolünün Add metodunu kullanmak ise Add metoduna uygun parametre ve geri dönüş değerine sahip bir delege tanımlamamız ve instance’ ını oluşturup bunu parametre değeri olarak Invoke metoduna göndermemiz gerekmektedir. Bu amaca uygun olarak globalde Add metodunun parametre kombinasyonu ve geri dönüş değerine uygun bir delege tanımlıyoruz ve hemen altına bu delegenin global referansınız tanımlıyoruz. Global değişkenlerin son durumu şekildeki gibidir :

Bu delegenin objesini form yüklendiğinde oluşturuyoruz ve adres olarak listView1 kontrolünün Add metodunu veriyoruz.

Son olarak ise listView1.Invoke metodu üzerinden ilk parametresine delegemizin kopyasını, ikinci parametresine ise li isimli ListViewItem objesini göndererek ekleme işlemini Main Thread üzerinde gerçekleştiriyoruz.

Bir sonraki ve son adımda ise listView1 kontrolü üzerinde seçili haber bilgisi değiştiğinde Tag özelliği üzerinden XmlNode objesini çektik ve “description” element’ inin değerini TextBox içerisinde görüntüledik. Diper kısımları standart MessageBox.Show kod satırları olarak ifade edilebilir.

MessageBox ile ilgili kısımlar :

Ve sıra geldi makalemizin en heyecanlı kısmına. Uygulamamızı hiç vakit kaybetmeden mobil cihaz emülatörü üzerinde çalıştırıyoruz. Bu noktada Mobil Cihaz Emülatörümüzün internet ayarlarının yapılı olduğunu varsayıyoruz.

Sonuç Mükemmel ! Farklı kategorileri seçtikte haberleri kaynak üzerinden Mobil Cihazımıza yüklenecektir. Ayrıca haberlerin üzerinde gezindiğimiz sürece Metin Kutusunun içerisinde haber detayı gösterilmektedir.

Bu makalemizde Asenkron Bir Mobil RSS Okuyucusu geliştirdik. Başka bir makalede daha görüşmek üzere.

 

 


Ekin ÖZÇİÇEKÇİLER
Microsoft Certified Trainer
ekin.ozcicekciler@bilgeadam.com
MCP, MCAD.NET, MCSD.NET, MCSD.NET, MCTS, MCPD Ent.