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.
ikonubulunan sitelerde kullanıcılar diledikleri taktirde bu RSS kaynaklarını RSSdestekli uygulamalar üzerine kayıt ettirebilmekte ; site üzerinden herhangi birnoktada gerçekleştirilen bir güncelleme ile ilgili bu RSS kaynağından ;dolayısıyla RSS işleyen uygulamalar üzerinden haberdar edilmektedirler. Pekinedir bu kadar meşhur olan bu RSS ? O’ nu bu kadar kullanılması cazip kılankavramlar nelerdir ? Bu noktada biraz bu soruların cevaplarını arayalım.
Öncelikle şunu belirtmek gerekirki RSS, belli bir zamansüreci içerisinde isim açılımı bakımından belli bir değişime uğramıştır. İlkstandartatize 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 edilebilecekfarklı akronimler üzerinden tanımlanmaktadır.
RSS, temel amacı bakımından, “bukaynağı sunan internet sitelerinin bu kaynak üzerinden sunulan içeriklerinidaha rahat takip edebilmek için oluşturulmuş standartize bir XML dökümanı &XML Formatı” olarak ifade edilebilmektedir.
RSS kaynağı üzerindeniçeriklerini dağıtan internet siteleri dünya üzerinde geliştirilmiş olanneredeyse tüm RSS okuyucuları için standartize edilmiş bazı temel kurallarıuygulamış olmaları gerekmektedir.
Bu temel kuralların başında RSSkaynağı üzerinden yayını yapılan XML dökümanının bazı temel element isimlerinesahip olmaları gerekmektedir. Bu temel element isimleri üzerinden RSSkaynağınızı dünya üzerindeki neredeyse birçok RSS okuyucusu destek verebilir ;ziyaretçiler bu uygulamaları üzerinden siteniz üzerinden yayını yapılan RSSkaynaklarına erişebilirler.
Peki nedir bu temel kurallar diyesorarak makalemizin teorik kısmına bu noktada devam edelim. Bir öncekiparagrafta 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. Butemel element isimlerini kısaca açıklamak gerekirse ;
Bir RSS dökümanı içerisindebulunması 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 dekullanacak 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 veaçıklamasıyla ilgili XML Tag’ lerinin altında standartize ve tekrar ederekgiden bir Tag betiği bulunmaktadır.
Her bir habertag’ leri ile ifade edilirken hertag’ leri arasında bilginin başlığı, varsaaçı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ğındastandart bir şekilde bulunacağı ; spesifik durumlarda yeni tag’ lerindeeklenebileceği olduğudur.
Evet, RSS ile ilgili temelseviyede bilgi sahibi olduktan sonra yavaş yavaş makalemizin asıl konusunadoğru geçiş yapalım. Amacımız dünya üzerindeki standart bir RSS okuyucusununyaptığı gibi yukarıda örneği ifade edilen bir RSS kaynağını standartlarındışında çok farklı bir ortamdan ; “Mobil Cihazlar” üzerinden okuyup kullanıcıyagün içerisinde yolda ya da bulunduğu herhangi bir lokasyonda haberleri takipetmesini sağlayacak bir Mobil RSS Okuyucusu geliştireceğiz.
Bu makale süresince .Net CompactFramework 2.0 üzerinde birçok farklı kavram üzerinde bilgi sahibi olup böylebir uygulama içerisinde uygulayarak tecrübe sahibi olacağız.
Hiç vakit kaybetmeden uygulamasenaryomuz üzerinde bilgi sahibi olalım.
Amacımız Mobil Cihaz kullanıcılarınındiledikleri her noktada Hürriyet Gazetesinin RSS Kaynağı üzerinden farklıkategoriler üzerinden sunulan haber başlıklarına ulaşabilmeleri için bir RSSOkuyucusu oluşturmak olacaktır. Bu noktada uygulama tasarımı bakımındanbirtakım problemlere karşın bazı önlemler almamız gerekmektedir.
Üzerinde çalışacak olduğumuzkavram internet erişiminin o anki performansı ile doğru orantılı olarakçalışacağından uygulamayu kullanacak olan kullanıcılar RSS Servisine istektebulunduğunda sonuç gelene kadar beklememesi gerekmektedir. Bu noktada işiniçerisine Asenkron Mimari girmektedir. Uygulamamız içerisinde uzak noktayayapacak olduğumuz çağrıların tümü “Asenkron Mimari” üzerindengeliştirilecektir. Böylece tek bir makale üzerinden Xml, Threading ve RSSkavramlarını öğrenmiş olacağız.
Hiç vakit kaybetmeden makalemizinkonusunu oluşturan uygulamamızı geliştirmeye başlayabiliriz. Bu noktadauygulamamı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 uygulamaiçerisinde gerçekleştirmek istediğimiz senaryoda kullanıcı Hürriyet GazetesininRSS Kaynaklarıyla ile ilgili kategorileri bir ComboBox içerisinden seçip ; birsonraki adımda ComboBox’ ın altında bulunan ListView kontrolü içerisinde kolonbazlı bir yapı üzerinden seçilen kategorideki haberleri görüntüleyecektir. İşinprogramatik 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 adreslerve katerogiler üzerinden kullanıcılara RSS Kaynağı sunmaktadır.
Amacımız bu noktada kullanıcıyaComboBox içerisinden şekilde sol tarafta sıralanmış olan kategorileriseçtirtmek ; bir sonraki adımda ise sağ tarafta bulunan adresler üzerinden RSSkaynağını almak olacaktır. Bu noktada şekildeki form tasarımı üzerindenuygulamamıza devam ediyoruz :
Şekildende anlaşılabileceği üzereform üzerine Bir ComboBox, View Özelliği “Details” olarak belirtilmiş birListView 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 belirtmemizgerekmektedirki Details görünümünde çalıştırılacak olan ListView kontrolümüzüniçerisine RSS Kaynağı üzerinden getirilen bilgilerin Başlık Ve Tarihbilgilerini ekran üzerinde gösterebilmemiz için iki adet kolon eklemişbulunmaktayız.
Ve sıra geldi kodlarıngeliştirilmesine. Bu noktada dikkatli olmamiz ; tasarimsal olarak herhangi birhataya maruz kalmamamız gerekmektedir.
Senaryoya baktığımızda ilknoktadaki amacımız kullanıcıya ComboBox içerisinden RSS Kaynağı üzerindensunulan Haber Kategorilerini seçtirtmek olacaktır. Bu noktada gerçekleştirmemizgereken ilk eylem ComboBox’ ın içerisine bu kategorileri eklemek olacaktır.Fakat ComboBox’ ın Items collection’ı içerisinde bulunan Add metodunabaktığımızda metodun tek bir kere tanımlandığı ve bu tanımlanan versiyonunda uygulamageliştiriciden “object” tipinde bir parametre beklediğini görmekteyiz.
Tasarımsal olarak bu noktadakiamacımız, kullanıcının “AnaSayfa”, “Gündem” şeklinde anlaşılır kategoriisimlerini görmesini isterken, arka tarafta seçili kategorinin RSS Adresineistekte bulunmak olacaktır. Olaya bu açıdan baktığımızda içerisinde iki adetbilgiyi depolayabilen ; Adres Ve İsim bilgisini depolayabilen bir sınıf tipineihtiyaç duymaktayız.
Bu problemin çözülebilmesi için.Net Compact Framework üzerinde Key – Value mantığıyla çalışan birçok tipbulunmasına rağmen kendi özelleştirilmiş tipimizi oluşturmak tasarımsal oalrakdaha doğru olacaktır.
Şekildeki sınıfı oluşturarakuygulamamıza devam ediyoruz :
Şekildende anlaşılabileceği üzerestandart olarak bir RSS Adresini ifade edebilecek özelliklere sahip bir sınıfoluşturmuş bulunmaktayız. Sınıfın içerisinde bir RSS’ in görsel ismi veadresini barındırabilecek iki adet özellik ve parametreli bir yapıcı metot(Constructer) bulunmaktadır.
Ayrıca “object isteyen görsel görselobjelerinde kullanabilmesi amacı ile” ToString() metodunu override ederemetottan sınıfın içerisindeki Isim_ değişkeninin değerinin dönmesini sağlamışbulunmaktayız.
Bir sonraki adımda Form’ umuzunLoad olayı gerçekleştiğinde ComboBox içerisine Hürriyet Gazetesi RSS Kaynağıüzerinden sunulan adresleri geliştirdiğimiz sınıfın constructer’ ı üzerindenoluşturarak ekliyoruz.
ComboBox içerisine eklenenobjelerin otomatik olarak ToString() metodunu çalıştıracak ve ekran üzerindeeklenen 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çiliKategorinin adresini alacağız.
Uygulamayı herhangi bir kod dahayazmadan bu haliyle Emülatörümüz üzerinde çalıştırdığımızda :
Listeden Pocket PC Emulator ‘ useçiyoruz ve uygulamamızı Deploy ediyoruz.
Ve uygulama ekranı içerisindekategoriler başarıyla listelenmiştir. Bu noktada kullanıcılar ComboBoxiçerisinde Kategori adlarını görmelerine rağmen bu liste elemanları arkataraflarında adres bilgilerinide barındırmaktadırlar.
Hızlı bir şekilde kaldığımızyerden devam edelim.
Uygulama içerisindeki amacımızuzak noktadan gelen RSS bilgilerini mobil cihazın memory’ si üzerinde depolamakve bu depolanan verileri uygun noktalara eklemek olacaktır. Bu amaçla RSSkaynağı üzerinden gelen XML verilerini mobil cihazın belleği üzerindedepolayabilmek amacı ile System.Xml namespace’ i altında bulunan XmlDocumentsınıfından yararlanacağız.
XmlDocument sınıfı, yapısı gereğiinstance’ ı oluşturulduktan sonra hafıza üzerinde DOM yapısına uygunoluşturulan XML verileri üzerinde dolaşabilmektedir. Ayrıca içerisindeki –ki makalemizdebu metot üzerinden yapıyı çalıştıracağız- GetElementsByTagName metodu üzerindenuygulama geliştirici metoda parametre değeri olarak gönderilen element isminesahip tüm XmlNode objelerini XmlNodeList tipinde geri dönüş değeri olarakalabilmektedirler.
Bu amacı gerçekleştirmek adınaglobalde bir XmlDocument referansı ; uygulama ekranı yüklendiğinde ise bureferansın instance’ ını oluşturuyoruz.
Ayrıca metot üzerinden gelecekolan XmlNode dizisini taşıyabilmesi için bir XmlNodeList referansını yineglobal’ de tanımlıyoruz.
Bir sonraki adımda Formyüklendiğinde XmlDocument objesini oluşturuyoruz :
Bir sonraki adımda her kategoriseçiminde çalışacak olan Thread objesinin başlatılacağı zaman gidipçalıştıracağı ; seçili kategorinin adres bilgisini kullanarak uzak noktadan RSSbilgilerini çekecek olan HaberleriYukle() isimli bir metot ve bu metodunçalıştırılmasında tetikleyici rolü oynayacak olan ComboBox’ ın seçili kategorideğeri değiştiğinde çalışacak olan kod bloklarını geliştiriyoruz. Şekildeki kodbloğu üzerinden uygulamamıza devam ediyoruz :
Öncelikle globalde Threadsı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ı olarakincelediğimizde ilk olarak ComboBox’ ın seçili indeks değeri değiştiğinde globalolarak tanımlı olan AktifRssAdresi isimli değişkene seçili olan ComboBoxobjesini RssKaynagi tipine dönüştürdükten sonra Adres değerini alıpeşitliyoruz. Bunu gerçekleştirmemizin sebebi bir sonraki adımda farklı birthread içerisinden farklı bir thread içerisindeki bir objenin özelliğineeriş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 ikithread’ inde erişebileceği güvenli bir string değişken üzerine taşıyoruz.
Daha sonraki satırda global Threadreferansını oluşturup içerisine bizden istediği ThreadStart isimli delegeinstance’ ını gönderiyoruz. Bu delege sadece parametre almayan ve void geridönüş değerine sahip metotları adresleyebilmektedir. Zaten HaberleriYuklemetodumuzun tanımlanma amacıda aslında bu olmaktadır. Thread’ i tanımladıktansonra sonra ise Thread sınıfının Start metodu üzerinden Thread’ i başlatıyoruz.
Bir sonraki adımda HaberleriYukleisimli metodumuz oluşturulmuştur. Bu metot içerisinde Form yüklendiğinde objesioluşturulmuş olan XmlDocument sınıfının Load metodu içerisinden uzaktan gelenRSS 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 üzerrssDOC isimli XmlDocument objesinin GetElementsByTagName isimli metodunaparametre değeri olarak “item” bilgisini vererek metodumuzu çalıştırıyoruz.Metot sonucunda kullanıcıya kaynak üzerinden gelen tüm elementlerini içerisindeki diğer child element’ ler ile birlikte XmlNodeListolarak döndürmektedirler.
Daha sonra bu XmlNodeListreferansı üzerinden içerisindeki her bir XmlNode objesi için yeni birListViewItem objesi oluşturulmakta ; içerisine ikinci bir SubItem eklenmekte vebu SubItem’ ların Text’ lerine sırasıyla başlık ve yayınlanma tarihi bilgilerieklenmektedir. Ayrıca ListViewItem üzerine tıklatıldığında tıklanan haberindetayını alabilmek bakımından ListViewItem objesinin Tag özelliğine XmlNodeobjesinin kendisi verilmektedir –ki gerektiği noktalarda haberin tümelementlerini 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öndermemizbu noktada yeterli olacaktır. Fakat bu işlemleri farklı thread üzerindegerçekleştirdiğimizi göz önünde bulundurur isek Main Thread üzerindeoluşturulmuş olan listView1 kontrolüne Worker Thread üzerinden “ThreadGüvenliği” bakımından erişememekteyiz. Bu amaca uygun olarak işlemi listView1kontrolünün ilk oluşturulmuş olduğu Thread üzerinde gerçekleştirebilmek için listView1kontrolünün Invoke metodunu kullanmamız gerekmektedir. Bu metodun sonucundaişlem listView1 kontrolünün ilk olarak oluşturulduğu thread üzerindegerçekleştirilecektir.
Invoke metodunun yapısınabaktığımızda ise hangi metodun Invoke edileceği ile ilgili Invoke edilecek olanmetodun adresini üzerinde barındıran bir delege objesi bizden istemektedir.Amacımız listView1 kontrolünün Add metodunu kullanmak ise Add metoduna uygunparametre 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öndermemizgerekmektedir. Bu amaca uygun olarak globalde Add metodunun parametrekombinasyonu ve geri dönüş değerine uygun bir delege tanımlıyoruz ve hemenaltına bu delegenin global referansınız tanımlıyoruz. Global değişkenlerin sondurumu şekildeki gibidir :
Bu delegenin objesini formyüklendiğinde oluşturuyoruz ve adres olarak listView1 kontrolünün Add metodunuveriyoruz.
Son olarak ise listView1.Invokemetodu üzerinden ilk parametresine delegemizin kopyasını, ikinci parametresineise li isimli ListViewItem objesini göndererek ekleme işlemini Main Threadüzerinde gerçekleştiriyoruz.
Bir sonraki ve son adımda iselistView1 kontrolü üzerinde seçili haber bilgisi değiştiğinde Tag özelliğiüzerinden XmlNode objesini çektik ve “description” element’ inin değeriniTextBox içerisinde görüntüledik. Diper kısımları standart MessageBox.Show kodsatırları olarak ifade edilebilir.
MessageBox ile ilgili kısımlar :
Ve sıra geldi makalemizin enheyecanlı 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 internetayarlarının yapılı olduğunu varsayıyoruz.
Sonuç Mükemmel ! Farklıkategorileri seçtikte haberleri kaynak üzerinden Mobil Cihazımızayüklenecektir. Ayrıca haberlerin üzerinde gezindiğimiz sürece Metin Kutusununiçerisinde haber detayı gösterilmektedir.
Bu makalemizde Asenkron Bir MobilRSS Okuyucusu geliştirdik. Başka bir makalede daha görüşmek üzere.