যারা মোবাইল অ্যাপ মাত্র ডেভেলপ করা শুরু করেছেন, তাদের ক্ষেত্রে একটা সমস্যা একেবারে শুরুর দিকে হয়। তা হচ্ছে, হ্যালো ওয়ার্ল্ড তো প্রিন্ট করলাম, এইবার কি করবো ?? মোবাইল অ্যাপ অনেক গতিশীল একটা প্লাটফর্ম। এইখানে নিজের ইচ্ছা মত, নিজের প্রয়োজনে লাগতে পারে বা কাউকে সাহায্য করতে পারে, এমন যে কোন আইডিয়া কে খুব সহজেই অ্যাপে পরিনত করে বাস্তব জীবনে প্রয়োগ করা যায়।
একটা মোবাইল অ্যাপ, শুরু থেকে শেষ পর্যন্ত কিভাবে ডিজাইন করা যায়, অন্তত কিভাবে এর মুল স্কেলিটন টা দাড় করানো যায় তাই আমি আজকে দেখাবো। আশা করি নবীনদের এতে অনেক সাহায্য হবে।
বিঃদ্রঃ আমি নিজেও খুব একজন অভিজ্ঞ অ্যাপ ডেভেলপার নই, বেস্ট প্র্যাক্টিস সহ ইত্যাদি অনেক কিছু আমার নিজেরও এখনো শেখা বাকি। সুতরাং অভিজ্ঞরা যদি এই ব্লগ এন্ট্রির গঠনমূলক সমালোচনা করেন, তবে কৃতজ্ঞ থাকবো।
আমরা আজকে একটি RSS Reader অ্যাপ বানাবো।
RSS – Rich Site Summary
XML বা JSON ফরম্যাটে এই RSS আমাদের কোন ওয়েবসাইটের নিত্যনতুন আপডেট প্রদান করে থাকে।
সাধারনত ব্লগ, নিউজ সাইট, ফেসবুক ইত্যাদি আমাদের RSS লিংক প্রদান করে থাকে।
ডেমো হিসেবে আমরা আজকে একটি ফেসবুক পেইজ, Collected Notes and Discussions এর RSS লিংক নিয়ে কাজ করবো।
আমরা আমাদের অ্যাপে MVVM (Model View ViewModel) সম্পুর্ন ভাবে অনুসরন করবো।
আমাদের অ্যাপে মুল যে কয়টা ক্লাস থাকবে, তারা হলোঃ
১. MainPage
২. DetailPage
৩. Model
৪. HtmlRemover ( helper class )
৫. ViewModel
MainPage ক্লাসের কাজ হবে মুল অ্যাপ টা ইনিশিয়েট করা, প্রতিটা নোটের Title আর Summary লিস্ট আকারে প্রদর্শন করা।
DetailPage এর কাজ হবে প্রতিটা নোটের মুল লেখা প্রদর্শন করা, অবশ্যই এককভাবে একটা পেইজে।
Model ক্লাস হবে RSS এর মাধ্যমে প্রাপ্ত ডাটার মিরর ক্লাস। অর্থাৎ RSS এর মাঝে যেই ফিল্ড/ প্রোপারটি/ ভ্যারিয়েবল গুলো থাকবে, ঠিক অনুরুপ ফিল্ড/ প্রোপারটি/ ভ্যারিয়েবল নিয়ে গঠিত একটা ক্লাস। এর ফলে প্রাপ্ত RSS ডাটা আমরা সরাসরি সেই Model ক্লাসের অবজেক্টের ভেতরে ঢুকিয়ে দিতে পারবো।
HtmlRemover ক্লাস হবে একটি স্ট্যাটিক, হেল্পার ক্লাস। এর কাজ হবে প্রাপ্ত RSS ডাটার মাঝে যদি কোনরকম HTML জনিত সমস্যা থাকে, তবে তা সমাধান করা।
ViewModel হচ্ছে আমাদের মুল কন্ট্রোলার ক্লাস। এইখানেই আমাদের অ্যাপের RSS ডাটা ওয়েব থেকে লোড হয়ে MainPage ও DetailPage এ গিয়ে প্রদর্শন করবে।
মুল কোডের ব্যাখ্যায় যাবার আগে আরো কিছু প্রাসঙ্গিক ব্যাখ্যা দেবার প্রয়োজন মনে করছি।
প্রথমত XML বা JSON কি জিনিস তা আমাদের জানতে হবে। এরা হচ্ছে Open Data Format. XML বা JSON এ কোন ডাটা সংরক্ষন করা হলে, সেই ডাটা যে কোন ধরনের সিস্টেম বুঝতে পারে।
আমি নিজে উদাহরন দেয়ার জন্যে প্রায়ই সময় একটা উদাহরন দেই। তাহলো, ধরুন আমাদের কে জাভা বেসড একটা সিস্টেম এর সাথে ডট নেট বেসড একটা সিস্টেমের সাথে ডাটা আদান প্রদান তথা কম্যুনিকেশন করতে হবে। এখন দুইটা সিস্টেম দুই ধরনের এনভায়রন্মেন্টে চলে। এদের মাঝে কম্যুনিকেশন স্থাপন করতে হলে আমাদের কে অবশ্যই এমন একটা মাধ্যম ব্যবহার করতে হবে যা কিনা জাভা এবং ডট নেট, দুইটা সিস্টেমই বুঝতে পারে। এই ধরনের প্রয়োজনীয়তা থেকেই XML, JSON এর মতো Open Data Format এর উৎপত্তি।
কোড দিয়ে ব্যাপারটা ব্যাখ্যা করা যাক।
ধরুন, সি# এ আমার একটা ক্লাস আছে, যা দেখতে অনেকটা এইরকম,
class Entry
{
public string title {get;set;}
public string summary {get;set}
public string content {get;set;}
}
Entry entry = new Entry(){ title = “hello”, summary = “summary” content = “main content goes here” };
এখন এই entry নামের অবজেক্ট টা কে যদি আমি XML এ পরিনত করি, তাহলে তা টেক্সট আকারে একটা টেক্সট ফাইলে সংরক্ষন করা যাবে এবং দেখতে হবে এইরকমঃ
<Entry>
<title>hello</title>
<summary>summary
<content>main content goes here</content>
</Entry>
আর JSON এ দেখাবে এইরকম,
{
“Entry”:{
“title”:”hello”,
“summary”:”summary”,
“content”:”main content goes here”
}
চাইলে এই XML, JSON কে আবার সি# এর অবজেক্টে রুপান্তর করা যায়। এবং শুধুমাত্র সি# নয়, জাভা, পিএইচপি, পাইথন, রুবি থেকে শুরু করে যে কোন অবজেক্ট অরিয়েন্টেড ল্যাংগুয়েজের অবজেক্টে রুপান্তর করা যায়, ওই ভাষার বিভিন্ন লাইব্রেরী/ ফাংশন ব্যবহার করে।
আর এইখানেই আসল মজাটা নিহিত। ফেসবুক তাদের RSS XML/JSON উৎপন্ন করছে হয়তো পিএইচপির মাধ্যমে, গুগল হয়তো তাদের API support দিচ্ছে XML/JSON এর মাধ্যমে যা উৎপন্ন হচ্ছে গুগলের সার্ভারে চলতে থাকা পাইথন ল্যাংগুয়েজের সাহায্যে, আর আমি এইদিকে সেই RSS XML/JSON রিসিভ করে কাজে লাগাচ্ছি সি# এর মাধ্যমে। এক কথায় সম্পূর্ণ দুটো আলাদা সিস্টেমের মাঝে ডাটা আদান প্রদান হচ্ছে।
তুলনামুলকভাবে XML এর চাইতে JSON নিয়ে ডাটা আদান প্রদান সহজতর। কারন XML এ শুরু এবং শেষ দুইটা ট্যাগের মাধ্যমে ডাটা চিহ্নিত করতে হয়, যা কিনা XML ফাইলের সাইজ বাড়িয়ে দেয় এবং প্রসেস করতে বেশি সময় লাগে।
কিন্তু JSON সরাসরি অবজেক্ট আকারে ডাটা প্রদর্শন করে, Key-Value Pair হিসেবে। যার কারনে মুল JSON ফাইলের সাইজ যেমন ছোট হয়, তেমনি JSON ডাটা প্রসেস করতেও XML এর চাইতে কম সিপিউ পাওয়ার ব্যয় হয়।
এখন আমরা যেহেতু কম্পিউটারের তুলনায় স্বল্প ক্ষমতা সম্পন্ন মোবাইল ডিভাইস নিয়ে কাজ করছি, তাই সিপিউ পাওয়ার + কম নেট খরচ, এই দুই হিসাব করলে XML এর চাইতে JSON ব্যবহার ই উত্তম।
JSON থেকে ডাটা সি# এর অবজেক্টে রুপান্তর করা অথবা এর বিপরীত কাজটা করার জন্য সি# এ একটা চমৎকার লাইব্রেরী আছে যার নাম NewtonSoft. http://json.net এ গেলে এই লাইব্রেরী সম্বন্ধে খুব সুন্দরভাবে, সহজে জানা যাবে।
এইবার আসি ডেস্কটপ বা মোবাইল অ্যাপ এর মাধ্যমে ওয়েব থেকে ডাটা কালেকশনের পদ্ধতি নিয়ে। হ্যা, বিভিন্ন ল্যাঙ্গুয়েজে নানারকম লাইব্রেরী পাওয়া যায় এই ব্যাপারে, যারা কিনা Http Request পাঠাতে পারে কোন নির্দিষ্ট ওয়েব লিঙ্কে, এবং সেই লিংক ওয়েব ব্রাউজারে লোড করলে, আমরা যে ডাটা(XML, JSON)/ওয়েবপেইজ পেতাম, তা ওই ল্যাঙ্গুয়েজের একটি অবজেক্টের ভেতরে স্ট্রিং আকারে সেইভ করে রাখে।
এইবার ওই স্ট্রিং এর ভেতরে থেকে চাইলে প্রয়োজনীয় ডাটা এক্সট্রাক্ট যেমন করে নিতে পারা যায় (XML, JSON), আবার চাইলে লোড হওয়া ওয়েব পেইজের নির্দিষ্ট HTML ট্যাগ এর ভিতরে থাকা প্যারাগ্রাফ, টেক্সট ইত্যাদি এক্সট্রাক্ট করে নিজের প্রয়োজন মত অ্যাপের ইউজার ইন্টারফেসে ব্যবহার করা যায়।
সি# এর ক্ষেত্রে Http Client নামের একটি ক্লাস আছে, যে কিনা আমাদেরকে ওয়েব থেকে এইভাবে ডাটা লোড করার সুযোগ দেয়।
এইবারে আরো গুরুত্তপুরন একটা কন্সেপ্টের সাথে পরিচিত হই। তা হচ্ছে Asynchronous Method. যখন আমরা ওয়েব থেকে ডাটা লোড হওয়ার জন্য আমাদের অ্যাপ থেকে রিকুয়েস্ট পাঠাবো, তখন যতক্ষন পর্যন্ত ডাটা লোড না হচ্ছে, ততক্ষন পর্যন্ত আমাদের অ্যাপ ওই জায়গায় আটকে থাকবে। আমাদের অ্যাপের ইউজার ইন্টারফেস লোড হবে না, হলেও আটকে থাকবে। আবার নেটওয়ার্কের পরিস্থিতির উপরে নির্ভর করে কতক্ষনে ডাটা লোড হবে তারও কোন নিশ্চিত সময় বলা যায় না। মানে সম্পূর্ণ অনিশ্চয়তায় পরিপূর্ণ একটা ব্যাপার যা কিনা শেষ পর্যন্ত খারাপ ইউজার এক্সেরিয়েন্সের দিকে নিয়ে যায়।
এই সমস্যা সমাধানের জন্য Asynchronous Method এর উৎপত্তি। এই মেথড কে যখন কল করা হয়, তখন সে নিজে নিজে অ্যাপের মুল কার্যক্রম ( থ্রেড ) এর পাশাপাশি আরেকটা সহযোগী কার্যক্রম ( সাব থ্রেড ) তৈরি করে। অ্যাপের মুল ইউজার ইন্টারফেস কোন রকম ঝামেলা ছাড়াই চলতে থাকে। আর সাব থ্রেডে চলতে থাকে লোডিং এর কাজ। যখন ডাটা ওয়েব থেকে এসে অ্যাপে লোড হয়, তখন আমাদের সাব থ্রেডের কাজ বন্ধ হয় এবং লোডকৃত ডাটা অ্যাপে ব্যবহার করার জন্য প্রস্তুত হয়।
Asynchronous Method ব্যবহার করলে যে সুবিধা টা পাওয়া যায়, আমি যদি অ্যাপ চলাকালীন সময়ে রিফ্রেশ নামের কোন বাটনে ক্লিক করে, তবে নতুন আপডেট এসে অ্যাপে হাজির হয়, এবং একই সময়ে আমি অ্যাপের পুরনো এন্ট্রি গুলো পড়তে পারি কোন রকম ঝামেলা ছাড়াই।
Asynchronous Method সম্বন্ধে আরো কিছু কথা বললে বুঝতে সুবিধা হবে। আমরা যারা ওয়েব নিয়ে কাজ করি, বা ওয়েব টেকনোলোজি সম্বন্ধে খোঁজখবর রাখি, তারা Ajax এর নাম শুনে থাকব। এই Ajax এর পুরো অর্থ হলো Asynchronous JavaScript. আমরা যখন ফেসবুক ব্রাউজ করি, তখন দেখা যায় ওয়েব পেইজ রিফ্রেশ না হয়েই নতুন নতুন নোটিফিকেশন আসছে, চ্যাট হচ্ছে, কমেন্ট করা যাচ্ছে। অথচ নরমাল সেন্সে বলে পুরো ওয়েব পেইজ লোড না হলে নতুন আপডেট পাবার কথা না। এইখানেই Ajax কাজ করে। ওয়েব পেইজের যে অংশটুকু লোড/ আপডেট হবার দরকার শুধু মাত্র সেই অংশটুকুই লোড/ আপডেট করে এই Ajax। এতে করে নতুন করে ওয়েব পেইজ লোডের ঝামেলা পোহাতে হয় না, অধিক ব্যান্ডউইথ খরচ হয় না, নতুন আপডেট পাবার সময় পুরনো লোড হওয়া ডাটা/ টেক্সট পড়তে কোন সমস্যা হয় না।
যাই হোক, অ্যাপ টা কিভাবে কাজ করে, কোন ক্লাস কোন ক্লাসের সাথে কিভাবে কানেক্টেড এইসব বর্ণনা করার আগে কিছু জিনিস জানতে হবে। যেমনঃ
১. কিভাবে নাগেট ম্যানেজারের মাধ্যমে নতুন প্যাকেজ/.dll/লাইব্রেরী ভিজুয়াল স্টুডিও প্রজেক্টে লোড করতে হয়
২. কিভাবে নেইমস্পেইস কাজ করে। প্রজেক্টের বিভিন্ন ফোল্ডার এর ভিতরে থাকা ক্লাসগুলোর নেইমস্পেস কিভাবে ডিফাইন করতে হয়।
৩. অবজেক্ট অরিয়েন্টেড প্রোগ্রামিং সম্বন্ধে মোটামুটি ধারনা থাকতে হবে
৪. এই প্রজেক্টের জন্য INotifyPropertyChanged, ObservableCollection এদের কাজ কি, কেন ব্যবহৃত হয় সে সম্বন্ধে ধারনা থাকতে হবে
৫. Partial Class কি, কিভাবে কাজ করে তা জানতে হবে
৬. উইন্ডোজ ফোনের ডিজাইন ল্যাঙ্গুয়েজ XAML ( Extensible Application Markup Language ), কিভাবে XAML এর সাথে মুল সি# কোডের অবজেক্ট বাইন্ড করতে হয়, XAML এর বিভিন্ন কন্ট্রোল(textBox, webBrowserControl) ইত্যাদি সম্বন্ধে পরিচয় এবং এদের বিভিন্ন প্রোপার্টি ইত্যাদি জানতে হবে।
৭. ইভেন্ট কিভাবে কাজ করে
মোটামুটি এই ব্যাপারগুলো সম্বন্ধে ধারনা থাকলে অনেক সহজেই এই অ্যাপ কিভাবে কাজ করে তা বোঝা যাবে।
এইবার আসুন ব্যাখ্যা করি অ্যাপের অভ্যন্তরীণ আর্কিটেকচার।
সবার প্রথমেই Nuget Manager এর মাধ্যমে Json.net, MVVMlight ও Http Client এই তিনটি প্যাকেজ সল্যুশনে অ্যাড করে নিতে হবে। কোন সমস্যা হলে ম্যানুয়ালি ওয়েব থেকে ডাউনলোড করে তারপরে প্রজেক্টের Reference এ অ্যাড করা যাবে।
প্রথমেই RSS link. আমরা ফেসবুকের এই http://goo.gl/pdGyPd লিংক থেকে Get Notes Via Rss ট্যাবে ক্লিক করি। XML এর একটা RSS আমাদের ওয়েব ব্রাউজারে লোড হবে। সতর্কতার সাথে লোড হওয়া পেইজের URL এর দিকে তাকাই, দেখতে পাবো সবার শেষে লেখা আছে, ….&format=rss20, এইখানে rss20 এর জায়গায় json লিখে এন্টার প্রেস করি। তাহলে এইবার দেখবো JSON এর একটি পেইজ লোড হয়েছে।
এইবার পুরো পেইজ যদি ভালোভাবে লক্ষ্য করে দেখি, তবে দেখা যাবে পুরো পেইজটা একটা অবজেক্ট। তার ভিতরে title, link, self, updated, icon, author, entries নামে বেশ কিছু ফিল্ড আছে। আবার author এর ভেতরেও দুটো ফিল্ড, name আর uri.
entries নামের ফিল্ডের ভেতরে আবার প্রায় ১০ টা অবজেক্ট, অর্থাৎ entries ফিল্ড টা একটা অ্যারে এর মতো কাজ করছে। এই ১০ টা অবজেক্টের প্রত্যেকের ভেতরে আবার title, id, alternate, catagories ইত্যাদি সহ প্রায় ১৫ টার মত ফিল্ড রয়েছে।
আমাদের অ্যাপে শুধুমাত্র এই entries নামের অ্যারে থেকে title, summary আর content(_html) এই তিনটা ফিল্ড দরকার।
এখন এই পুরো পেইজটা সিলেক্ট করে কপি করি এবং http://json2csharp.com এ যাই। কপি করা JSON এইখানে পেস্ট করে দেই এবং এই JSON কে ধারন করতে পারে, এমন একটা সি# এর ক্লাস জেনারেট করি।
জেনারেট হওয়া ক্লাস টা আমাদের অ্যাপের মডেল হিসেবে ব্যবহৃত হবে।
এইবার MainPage.xaml এ গিয়ে একটি longlistselector ডিক্লেয়ার করি, এর ডাটাটেমপ্লেটে title আর summary এর জন্য দুটো ফিল্ড ডিক্লেয়ার করি।
ViewModel এ আমাদের Model এ থাকা Entry ক্লাসের একটি Observable Collection Object ডিক্লেয়ার করি। একই সাথে Entry ক্লাস এ INotifyPropertyChanged Interface ইমপ্লিমেন্ট করি। এই ক্লাসের title, summary আর content প্রোপার্টি গুলোতে INotifyPropertyChanged এর শর্ত গুলো ব্যবহার করি।
ViewModel এ Load() এবং DownloadPageAsync() নামের মেথড দুইটি ডিক্লেয়ার করি। ViewModel এর Constructor যখন কল করা হবে, তখন Load() মেথড কে কল করা হবে যা শেষ পর্যন্ত DownloadPageAsync() মেথড কে কল করবে, এবং যখন ডাটা ওয়েব থেকে এসে হাজির হবে, তখন ViewModel এর Load() ও DownloadPageAsync() নামের Asynchronous Method দুইটির কাজ শেষ হবে।
এইবার MainPage.xaml.cs এ MainViewModel এর একটি অবজেক্ট MyVM ডিক্লেয়ার করি। এই ক্লাসের constructor এ পুরো অ্যাপের DataContext হিসেবে সেট করে দেই MyVM কে। একই সাথে আমাদের পূর্বে ডিক্লেয়ার করা longlistselector এর ItemsSource হিসেবে assign করে দেই আমাদের MyVM.entry কে।
longlistselector এর একটি silectedItemChanged ইভেন্ট ডিক্লেয়ার করি, এবং তাতে রেফার করে দেই longlistselector এর কোন আইটেমে ক্লিক করলে যেন DetailsPage.xaml এ চলে যায় এবং সাথে সাথে সিলেক্টেড আইটেমের content প্রোপার্টি যেন ওই পেইজে লোড হয়। এইখানে NavigationService.Navigate() নামের একটি মেথড ব্যবহার করা হয়েছে, এবং content প্রোপার্টির ভিতরে HTML সম্পর্কিত কোন সমস্যা থাকলে তা সমাধান করা হয়েছে Htmlrmover.StripSpaceCharArray() নামের একটি স্ট্যাটিক মেথডের মাধ্যমে।
DetailsPage.xaml এ পাস করা content প্রোপার্টি কে প্রদর্শন করা হয়েছে একটি ওয়েব ব্রাউজার কন্ট্রোলের মাধ্যমে কারন content প্রোপার্টি বিভিন্ন লাইন ব্রেক, ইন্ডেন্টিং ইত্যাদি নিয়ন্ত্রন করা হচ্ছে HTML ট্যাগ এর মাধ্যমে। DetailsPage.xaml.cs এ OnNvaigatedTo() মেথডের মাধ্যমে পাস হয়ে আসা content কে ওয়েব ব্রাউজার কন্ট্রোলে প্রদর্শন করা হচ্ছে।
এই ছিলো মোটামুটি ভাবে অ্যাপটা কিভাবে কাজ করে তার বর্ণনা। আশা করি আগ্রহীরা নিজেরাও RSS ফিড দিয়ে অনেক চমৎকার সব অ্যাপ বানাবেন।
সোর্স কোডের লিংক http://cnd.codeplex.com . সোর্স কোড টা ভালো করে পড়বেন এই ব্লগে দেয়া বর্ণনার সাথে সাথে। ভালো থাকবেন 🙂