Kriptofolio অ্যাপ সিরিজ - পার্ট 3
একটি নতুন অ্যাপ তৈরি করা শুরু করার সময় সবচেয়ে গুরুত্বপূর্ণ বিষয় হল আর্কিটেকচার। আপনি করতে পারেন সবচেয়ে বড় ভুল কোন স্থাপত্য শৈলী সঙ্গে যেতে হয়.
সাম্প্রতিক বছরগুলিতে অ্যান্ড্রয়েড সম্প্রদায়ের জন্য আর্কিটেকচার পছন্দের বিষয়টি বেশ বিতর্কিত হয়েছে। এমনকি গুগল জড়িত হওয়ার সিদ্ধান্ত নিয়েছে। 2017 সালে তারা অ্যান্ড্রয়েড আর্কিটেকচার কম্পোনেন্ট প্রকাশ করে প্রমিত স্থাপত্যের নিজস্ব পদ্ধতির প্রস্তাব করেছিল। এটি ডেভেলপারদের জীবনকে সহজ করার উদ্দেশ্যে করা হয়েছিল৷
৷এই পোস্টে, আমি প্রথমে আলোচনা করতে যাচ্ছি কেন আমাদের অ্যাপসকে আর্কিটেক্ট করতে হবে। আমরা কি বিকল্প আছে কভার করব. তারপর আমরা শিখতে যাচ্ছি কিভাবে এটা করতে হবে। চাকাটি পুনরায় উদ্ভাবনের পরিবর্তে, আমরা অ্যান্ড্রয়েড টিমের প্রদত্ত নির্দেশিকা ব্যবহার করব৷
৷এটি সম্পর্কে আমার নিজের জ্ঞানের অভাবের কারণে এই পোস্টটি লেখা আমার পক্ষে সবচেয়ে কঠিন ছিল। বড় ছবি দেখতে প্রথমে আমাকে স্থাপত্যের বিষয়টা ভালোভাবে অধ্যয়ন করতে হয়েছিল। এখন আমি আপনার সাথে আমার ফলাফল শেয়ার করতে প্রস্তুত।
সিরিজ বিষয়বস্তু
- পরিচয়:2018-2019 সালে একটি আধুনিক অ্যান্ড্রয়েড অ্যাপ তৈরি করার একটি রোডম্যাপ
- পর্ব 1:সলিড নীতিগুলির একটি ভূমিকা
- অংশ 2:কিভাবে আপনার Android অ্যাপ তৈরি করা শুরু করবেন:Mockups, UI, এবং XML লেআউট তৈরি করা
- ৩য় পর্ব:সেই আর্কিটেকচার সম্বন্ধে সমস্ত কিছু:বিভিন্ন আর্কিটেকচার প্যাটার্ন অন্বেষণ করা এবং কীভাবে সেগুলি আপনার অ্যাপে ব্যবহার করবেন (আপনি এখানে আছেন)
- পার্ট 4:ড্যাগার 2 এর সাথে আপনার অ্যাপে ডিপেনডেন্সি ইনজেকশন কীভাবে প্রয়োগ করবেন
- অংশ 5:Retrofit, OkHttp, Gson, Glide এবং Coroutines ব্যবহার করে RESTful ওয়েব পরিষেবাগুলি পরিচালনা করুন
আপনি অ্যাপ আর্কিটেকচার সম্পর্কে কেন যত্নবান হবেন?
সাধারণত আপনি যখন অ্যান্ড্রয়েডের সাথে কাজ শুরু করেন তখন আপনি বেশিরভাগ মূল ব্যবসায়িক যুক্তি ক্রিয়াকলাপ বা টুকরোগুলিতে লিখতে পারেন। এটি আমার সহ সমস্ত নতুন অ্যান্ড্রয়েড বিকাশকারীদের সাথে ঘটে৷ সমস্ত ছোট টিউটোরিয়াল এবং সমস্ত নমুনা এটি করার পরামর্শ দেয়। এবং আসলে, ব্যাখ্যার জন্য তৈরি করা ছোট অ্যাপগুলির জন্য, এটি যথেষ্ট ভাল কাজ করে৷
৷যাইহোক, এটি একটি বাস্তব অ্যাপে করার চেষ্টা করুন যা ক্রমাগত ব্যবহারকারীদের চাহিদা অনুযায়ী পরিবর্তিত হচ্ছে এবং নতুন বৈশিষ্ট্যগুলির সাথে এটিকে প্রসারিত করছে। শীঘ্রই আপনি দেখতে পাবেন যে আপনার কোডিং অভিজ্ঞতা আরও বেশি বেদনাদায়ক হচ্ছে। সমস্ত কিছু তথাকথিত "ঈশ্বর শ্রেণী" দ্বারা পরিচালিত হয় যেমন কার্যকলাপ বা টুকরা। এগুলোর কোডের এত লাইন আছে যে আপনি সহজেই হারিয়ে যাবেন।
মূলত আপনার সমস্ত কোড স্প্যাগেটির মতো দেখতে শুরু করে যেখানে সবকিছু মিশ্রিত হয়। সমস্ত অংশ একে অপরের উপর নির্ভর করে। তারপর যখন ব্যবসার দ্বারা নতুন পরিবর্তনের প্রয়োজন হয়, তখন পুরো প্রকল্পটি পুনর্নির্মাণ করা ছাড়া আপনার কাছে আর কোন বিকল্প নেই। এছাড়াও এটি সেই বিন্দু যেখানে আর্কিটেকচার প্রশ্নগুলি উপস্থিত হতে শুরু করে।
আপনার কোড গঠন করার আরও ভালো উপায় আছে কি?
অবশ্যই আছে! উচ্চ মানের কোডের চাবিকাঠি হল সলিড নীতিগুলি অনুসরণ করা৷ আমি আমার আগের পোস্টে এই বিষয়ে কথা বলেছি (কোন কারণ ছাড়াই)। উদ্বেগগুলিকে আলাদা করার জন্য আপনার কিছু আর্কিটেকচার প্যাটার্নও প্রয়োগ করা উচিত। আসলে, উদ্বেগের বিচ্ছেদ আপনার চূড়ান্ত লক্ষ্য হওয়া উচিত। এটি সবচেয়ে গুরুত্বপূর্ণ পয়েন্ট যা কোডের গুণমান নির্দেশ করে। অ্যাপ আর্কিটেকচারের জন্য বেশ কয়েকটি নিদর্শন রয়েছে। সবচেয়ে সুপরিচিত ক্লাসিক তিন স্তরের আর্কিটেকচার যেমন:
- MVC:মডেল-ভিউ-কন্ট্রোলার
- MVP:মডেল-ভিউ-উপস্থাপক
- MVVM:মডেল-ভিউ-ভিউ মডেল
এই সমস্ত নিদর্শনগুলি প্রধান অনুরূপ ধারণার প্রতিনিধিত্ব করে — আপনার প্রকল্পের কোডটিকে এমনভাবে গঠন করতে যাতে এটি বিভিন্ন জেনেরিক স্তর দ্বারা পৃথক করা হয়। প্রতিটি স্তরের নিজস্ব দায়িত্ব আছে। এই কারণেই আপনার প্রোজেক্ট মডুলার হয়ে যায়:আলাদা করা কোড অংশগুলি আরও পরীক্ষাযোগ্য, এবং আপনার অ্যাপটি ক্রমাগত পরিবর্তনের জন্য যথেষ্ট নমনীয়৷
আমরা যদি প্রতিটি প্যাটার্ন সম্পর্কে পৃথকভাবে কথা বলি, তাহলে বিষয়টি খুব বিস্তৃত হয়ে যায়। আমি আপনাকে প্রত্যেকের সাথে পরিচয় করিয়ে দিতে যাচ্ছি যাতে আপনি মূল পার্থক্য বুঝতে পারেন।
মডেল-ভিউ-কন্ট্রোলার (MVC) প্যাটার্ন
এই প্যাটার্নটি পুরানো সময়ে ফিরে নেওয়া Android অ্যাপ আর্কিটেকচারের প্রথম পুনরাবৃত্তি। এটি প্রস্তাব করে যে আপনি আপনার কোডকে 3টি ভিন্ন স্তরে আলাদা করুন:
মডেল - ডেটা স্তর। নেটওয়ার্ক এবং ডাটাবেস স্তরগুলির সাথে ব্যবসার যুক্তি এবং যোগাযোগ পরিচালনার জন্য দায়ী৷
দেখুন — ইউজার ইন্টারফেস (UI) স্তর। এটি মডেল থেকে ডেটার একটি সহজ ভিজ্যুয়ালাইজেশন।
কন্ট্রোলার — লজিক লেয়ার, ব্যবহারকারীর আচরণ সম্পর্কে অবহিত হয় এবং প্রয়োজন অনুসারে মডেল আপডেট করে।
এটি হল MVC স্কিমা। এতে আমরা দেখতে পাচ্ছি যে কন্ট্রোলার এবং ভিউ উভয়ই মডেলের উপর নির্ভর করে। কন্ট্রোলার ডেটা আপডেট করে। ভিউ ডেটা পায়। যাইহোক, মডেলটি আলাদা করা হয়েছে এবং UI থেকে স্বাধীনভাবে পরীক্ষা করা যেতে পারে।
MVC প্যাটার্ন কিভাবে প্রয়োগ করতে হয় তার কয়েকটি পন্থা রয়েছে। এটা বেশ বিভ্রান্তিকর।
একটি হল যখন কার্যকলাপ এবং খন্ডগুলি নিয়ন্ত্রকের মত কাজ করে। তারা ডেটা প্রক্রিয়াকরণ এবং ভিউ আপডেট করার দায়িত্বে রয়েছে। এই স্থাপত্য পদ্ধতির সমস্যা হল যে কার্যকলাপ এবং খন্ডগুলি বেশ বড় এবং পরীক্ষা করা খুব কঠিন হতে পারে৷
আরেকটি পদ্ধতি যা আরও যৌক্তিক (এবং সঠিক) বলে মনে হয় তা হল যেখানে ক্রিয়াকলাপ এবং টুকরোগুলি MVC জগতের দৃশ্য হওয়া উচিত। কন্ট্রোলারগুলি আলাদা ক্লাস হওয়া উচিত যা কোনও অ্যান্ড্রয়েড ক্লাস প্রসারিত বা ব্যবহার করে না। মডেলের জন্য একই।
যাইহোক আপনি যদি MVC সম্পর্কে আরও অনুসন্ধান করেন, আপনি জানতে পারবেন যে যখন একটি Android প্রকল্পে প্রয়োগ করা হয়, এমনকি সঠিক উপায়ে কোড স্তরগুলি একে অপরের উপর নির্ভর করে। সেজন্য আমি আপনাকে আপনার পরবর্তী অ্যান্ড্রয়েড অ্যাপের জন্য এটি আর ব্যবহার করার সুপারিশ করব না।
মডেল-ভিউ-প্রেজেন্টার (MVP) প্যাটার্ন
প্রথম পদ্ধতির পরে, যা কাজ করেনি, অ্যান্ড্রয়েড বিকাশকারীরা এগিয়ে চলে এবং সবচেয়ে জনপ্রিয় স্থাপত্য নিদর্শনগুলির মধ্যে একটি - এমভিপি ব্যবহার করার চেষ্টা করেছিল। এই প্যাটার্নটি স্থাপত্য পছন্দের দ্বিতীয় পুনরাবৃত্তির প্রতিনিধিত্ব করে। এই প্যাটার্নটি ব্যাপকভাবে ব্যবহৃত হয়েছে এবং এখনও এটি একটি প্রস্তাবিত। যে কেউ অ্যান্ড্রয়েড ডেভেলপমেন্ট শুরু করে, তার জন্য এটা শেখা সহজ। আসুন এর 3টি আলাদা স্তরের ভূমিকা দেখে নেওয়া যাক:
মডেল — ডেটা স্তর, যা MVC প্যাটার্নের মতোই। নেটওয়ার্ক এবং ডাটাবেস স্তরগুলির সাথে ব্যবসার যুক্তি এবং যোগাযোগ পরিচালনার জন্য দায়ী৷
দেখুন — ইউজার ইন্টারফেস (UI) স্তর। ডেটা প্রদর্শন করে এবং উপস্থাপককে ব্যবহারকারীর ক্রিয়া সম্পর্কে অবহিত করে৷
৷উপস্থাপক — মডেল থেকে ডেটা পুনরুদ্ধার করে, UI যুক্তি প্রয়োগ করে এবং দৃশ্যের অবস্থা পরিচালনা করে, কী প্রদর্শন করতে হবে তা সিদ্ধান্ত নেয় এবং ভিউ থেকে ব্যবহারকারীর ইনপুট বিজ্ঞপ্তিগুলিতে প্রতিক্রিয়া জানায়। এটি মূলত MVC-এর থেকে কন্ট্রোলার ব্যতীত যে এটি দৃশ্যের সাথে আবদ্ধ নয়, শুধুমাত্র একটি ইন্টারফেস৷
MVP স্কিমা দেখায় যে ভিউ এবং উপস্থাপক ঘনিষ্ঠভাবে সম্পর্কিত। তাদের একে অপরের রেফারেন্স থাকা দরকার। তাদের সম্পর্ক একটি Contract
এ সংজ্ঞায়িত করা হয়েছে ইন্টারফেস ক্লাস।
এই প্যাটার্নটির একটি উল্লেখযোগ্য কিন্তু নিয়ন্ত্রণযোগ্য অসুবিধা রয়েছে। আপনি যদি যথেষ্ট সতর্ক না হন এবং একক দায়িত্ব নীতি অনুযায়ী আপনার কোড না ভাঙেন তাহলে উপস্থাপক একটি বিশাল সর্বজ্ঞানী শ্রেণীতে প্রসারিত হতে থাকে। যাইহোক, সাধারণভাবে বলতে গেলে, MVP প্যাটার্ন উদ্বেগের একটি খুব ভাল বিচ্ছেদ প্রস্তাব করে। এটি আপনার প্রকল্পের জন্য আপনার প্রধান পছন্দ হতে পারে৷
মডেল-ভিউ-ভিউ মডেল (MVVM) প্যাটার্ন
MVVM প্যাটার্ন হল পদ্ধতির তৃতীয় পুনরাবৃত্তি। এটি অ্যান্ড্রয়েড আর্কিটেকচার কম্পোনেন্টস রিলিজের সাথে Android টিমের দ্বারা সুপারিশকৃত আর্কিটেকচার প্যাটার্নে পরিণত হয়েছে। এই কারণেই আমরা এই প্যাটার্নটি শেখার দিকে সবচেয়ে বেশি মনোযোগ দেব। এছাড়াও আমি এটি "মাই ক্রিপ্টো কয়েন" অ্যাপের জন্য ব্যবহার করব। আগের মতই, এর আলাদা কোড লেয়ারগুলো দেখে নেওয়া যাক:
মডেল - ডেটা উৎসকে বিমূর্ত করে। ভিউমডেল ডেটা পেতে এবং সংরক্ষণ করতে মডেলের সাথে কাজ করে।
ভিউ — যা ভিউমডেলকে ব্যবহারকারীদের কর্ম সম্পর্কে অবহিত করে।
ভিউমডেল — ভিউ-এর সাথে প্রাসঙ্গিক ডেটার স্ট্রীম প্রকাশ করে।
MVP প্যাটার্নের তুলনায় পার্থক্য হল যে, MVVM-এ, ViewModel উপস্থাপকের সাথে ভিউ-এর কোনো রেফারেন্স রাখে না। MVVM-এ, ViewModel ইভেন্টের একটি স্ট্রীম উন্মোচন করে যার সাথে বিভিন্ন ভিউ আবদ্ধ হতে পারে। অন্যদিকে, MVP ক্ষেত্রে, উপস্থাপক সরাসরি কি প্রদর্শন করতে হবে তা ভিউকে বলে। আসুন MVVM স্কিমা দেখে নেওয়া যাক:
এমভিভিএম-এ ভিউটির ভিউমডেলের একটি রেফারেন্স রয়েছে। ViewModel এর ভিউ সম্পর্কে কোন তথ্য নেই। ভিউ এবং ভিউমডেলের মধ্যে বহু-থেকে-এক সম্পর্ক রয়েছে৷
৷MVC বনাম MVP বনাম MVVM-এর তুলনা
এখানে একটি সারণী রয়েছে যা আমি যে সমস্ত প্যাটার্নের কথা বলেছি তার সমষ্টি করে:
আপনি লক্ষ্য করেছেন যে, একটি মডুলার এবং পরীক্ষাযোগ্য আধুনিক অ্যাপ তৈরি করার সময় MVP এবং MVVM এর তুলনায় MVC এতটা ভালো নয়। কিন্তু প্রতিটি প্যাটার্নের নিজস্ব সুবিধা এবং অসুবিধা আছে। এটি একটি ভাল পছন্দ যদি এটি ঠিক আপনার প্রয়োজনের সাথে খাপ খায়। আমি পরামর্শ দিচ্ছি যে আপনি তদন্ত করুন এবং এই সমস্ত নিদর্শনগুলি সম্পর্কে আরও জানুন কারণ এটি মূল্যবান৷
৷ইতিমধ্যে, আমি 2018 সালে ট্রেন্ডিং প্যাটার্নের সাথে আমার প্রজেক্ট চালিয়ে যাব, যেটিকে Google — MVVM দ্বারাও ঠেলে দিয়েছে৷
Android আর্কিটেকচার উপাদান
আপনি যদি অ্যান্ড্রয়েড অ্যাপ্লিকেশান লাইফসাইকেলের সাথে পরিচিত হন তবে আপনি জানেন যে এমন একটি অ্যাপ তৈরি করা কী মাথাব্যথা হতে পারে যা সমস্ত ডেটা প্রবাহ সমস্যা এবং স্থায়ীত্ব এবং স্থিতিশীলতার সমস্যাগুলি এড়িয়ে যায় যা সাধারণত কনফিগারেশন পরিবর্তনের সময় উপস্থিত হয়৷
2017 সালে, Android টিম সিদ্ধান্ত নিয়েছে যে আমরা যথেষ্ট সংগ্রাম করব। তারা দায়িত্ব গ্রহণ করে এবং অ্যান্ড্রয়েড আর্কিটেকচার কম্পোনেন্ট ফ্রেমওয়ার্ক প্রবর্তন করে। এটি অবশেষে আপনার কোডকে জটিল না করে বা এতে হ্যাক প্রয়োগ না করেই আপনাকে এই সমস্ত সমস্যার সমাধান করতে দেয়৷
Android Architecture Components হল লাইব্রেরির একটি সংগ্রহ যা আপনাকে শক্তিশালী, পরীক্ষাযোগ্য এবং রক্ষণাবেক্ষণযোগ্য অ্যাপ ডিজাইন করতে সাহায্য করে। বর্তমান মুহুর্তে যখন আমি এই ব্লগ পোস্টটি লিখছি, এটি এই উপাদানগুলি নিয়ে গঠিত:
- ডেটা বাইন্ডিং — ঘোষণামূলকভাবে পর্যবেক্ষণযোগ্য ডেটাকে UI উপাদানের সাথে আবদ্ধ করে
- লাইফসাইকেল — আপনার কার্যকলাপ এবং খণ্ডিত জীবনচক্র পরিচালনা করুন
- লাইভডেটা — ডাটাবেস পরিবর্তনের সময় ভিউকে অবহিত করুন
- নেভিগেশন — অ্যাপ-মধ্যস্থ নেভিগেশনের জন্য প্রয়োজনীয় সবকিছু পরিচালনা করুন
- পেজিং — ধীরে ধীরে আপনার ডেটা উৎস থেকে চাহিদা অনুযায়ী তথ্য লোড করুন
- রুম — সাবলীল SQLite ডাটাবেস অ্যাক্সেস
- ভিউমডেল — জীবনচক্র-সচেতন উপায়ে UI-সম্পর্কিত ডেটা পরিচালনা করুন
- ওয়ার্ক ম্যানেজার — আপনার অ্যান্ড্রয়েড ব্যাকগ্রাউন্ডের কাজগুলি পরিচালনা করুন
অ্যান্ড্রয়েড আর্কিটেকচার উপাদানগুলির সাহায্যে আমরা এই চিত্রটি অনুসরণ করে My Crypto Coins অ্যাপে MVVM আর্কিটেকচার প্যাটার্ন বাস্তবায়ন করতে যাচ্ছি:
এটি Google দ্বারা একটি প্রস্তাবিত আর্কিটেকচার। এটি দেখায় কিভাবে সমস্ত মডিউল একে অপরের সাথে যোগাযোগ করা উচিত। পরবর্তীতে আমরা শুধুমাত্র নির্দিষ্ট Android আর্কিটেকচার উপাদানগুলি কভার করব যা আমরা আমাদের প্রকল্পে ব্যবহার করব৷
আপনার উৎস ফাইলগুলি সংগঠিত করা
বিকাশ শুরু করার আগে আমাদের বিবেচনা করা উচিত যে আমাদের প্রকল্পের উত্স ফাইলগুলি কীভাবে সংগঠিত করা উচিত। আমরা এই প্রশ্নটিকে উত্তর ছাড়া ছেড়ে দিতে পারি না, কারণ পরবর্তীতে আমাদের বোঝা এবং সংশোধন করা কঠিন একটি অগোছালো কাঠামো থাকবে৷
এটা করতে বিভিন্ন উপায় আছে। একটি উপাদান বিভাগ দ্বারা সংগঠিত হয়. উদাহরণস্বরূপ, সমস্ত ক্রিয়াকলাপ তাদের নিজস্ব ফোল্ডারে যায়, সমস্ত অ্যাডাপ্টার তাদের ফোল্ডারে যায় ইত্যাদি৷
আরেকটি উপায় অ্যাপ বৈশিষ্ট্য দ্বারা সবকিছু সংগঠিত হবে. উদাহরণস্বরূপ, সমস্ত ক্রিপ্টো মুদ্রা তালিকা বৈশিষ্ট্যে ক্রিপ্টো অনুসন্ধান এবং যোগ করুন তার নিজস্ব addsearchlist
এ যায় ফোল্ডার মূল ধারণাটি হল যে সবকিছু এলোমেলোভাবে স্থাপন করার পরিবর্তে আপনাকে কিছু নির্দিষ্ট উপায়ে এটি করতে হবে। আমি এই উভয়ের কিছু ধরণের মিশ্রণ ব্যবহার করি।
প্রোজেক্টের ফোল্ডার স্ট্রাকচার ছাড়াও, আপনাকে প্রোজেক্ট ফাইলের নামকরণের জন্য কিছু নিয়ম প্রয়োগ করার কথা বিবেচনা করা উচিত। উদাহরণস্বরূপ, অ্যান্ড্রয়েড ক্লাসের নামকরণ করার সময় আপনাকে নামের মধ্যে ক্লাসের উদ্দেশ্য পরিষ্কারভাবে সংজ্ঞায়িত করা উচিত।
ভিউ মডেল
আমাদের অ্যাপ আর্কিটেকচার ডেভেলপমেন্ট শুরু করার জন্য, প্রথমে আমরা ViewModel তৈরি করতে যাচ্ছি। ভিউ মডেলগুলি এমন বস্তু যা UI উপাদানগুলির জন্য ডেটা সরবরাহ করে এবং কনফিগারেশন পরিবর্তনগুলিকে বাঁচিয়ে রাখে৷
আপনি একটি ক্রিয়াকলাপ বা একটি খণ্ডের সমগ্র জীবনচক্র জুড়ে ডেটা ধরে রাখতে একটি ViewModel ব্যবহার করতে পারেন। ক্রিয়াকলাপ এবং খণ্ডগুলি স্বল্পস্থায়ী বস্তু। কোনও ব্যবহারকারী কোনও অ্যাপের সাথে ইন্টারঅ্যাক্ট করার সময় সেগুলি প্রায়শই তৈরি এবং ধ্বংস হয়ে যায়। একটি ভিউমডেল নেটওয়ার্ক যোগাযোগের সাথে সাথে ডেটা ম্যানিপুলেশন এবং অধ্যবসায় সম্পর্কিত কাজগুলি পরিচালনা করার জন্য আরও উপযুক্ত৷
উদাহরণ হিসেবে এখন MainListFragment
-এর জন্য একটি ViewModel তৈরি করা যাক এটি থেকে UI ডেটা আলাদা করতে।
class MainViewModel : ViewModel() {
...
}
তারপর কোডের একক লাইনের সাথে ViewModel প্রাপ্ত করুন।
class MainListFragment : Fragment() {
...
private lateinit var viewModel: MainViewModel
...
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
setupList()
// Obtain ViewModel from ViewModelProviders, using this fragment as LifecycleOwner.
viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
...
}
...
}
মূলত এটাই, অভিনন্দন! ? চলুন এগিয়ে যাই।
লাইভডেটা
LiveData হল একটি পর্যবেক্ষণযোগ্য ডেটা ধারক শ্রেণী। এটি পর্যবেক্ষক প্যাটার্ন অনুসরণ করে। LiveData হল জীবনচক্র-সচেতন। এর মানে হল যে এটি শুধুমাত্র অ্যাপ কম্পোনেন্ট (অ্যাক্টিভিটি, ফ্র্যাগমেন্ট, ইত্যাদি) পর্যবেক্ষকদের আপডেট করে যারা একটি সক্রিয় জীবনচক্র অবস্থায় আছে।
LiveData ক্লাস ডেটার সর্বশেষ মান প্রদান করে। ডেটা পরিবর্তন হলে এটি আপডেট করা মান প্রদান করে। LiveData ভিউমডেলের সাথে সবচেয়ে উপযুক্ত৷
৷আমরা ViewModel এর সাথে একসাথে LiveData ব্যবহার করব এভাবে:
...
class MainViewModel : ViewModel() {
private val liveData = MutableLiveData<ArrayList<Cryptocurrency>>()
val data: LiveData<ArrayList<Cryptocurrency>>
get() = liveData
init {
val tempData = ArrayList<Cryptocurrency>()
val btc:Cryptocurrency = Cryptocurrency("Bitcoin", 1, 0.56822348, "BTC", 8328.77, 4732.60, 0.19, -10.60, 0.44, 20.82)
val eth:Cryptocurrency = Cryptocurrency("Etherium", 2, 6.0, "ETH", 702.99, 4217.94, 0.13, -7.38, 0.79, 33.32)
tempData.add(btc)
tempData.add(eth)
liveData.value = tempData
}
}
ViewModel-এ ডেটা পর্যবেক্ষণ করুন, LiveData হিসাবে উন্মুক্ত:
...
class MainListFragment : Fragment() {
private lateinit var recyclerView: RecyclerView
private lateinit var recyclerAdapter: MainRecyclerViewAdapter
private lateinit var viewModel: MainViewModel
...
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
setupList()
// Obtain ViewModel from ViewModelProviders, using this fragment as LifecycleOwner.
viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
// Observe data on the ViewModel, exposed as a LiveData
viewModel.data.observe(this, Observer { data ->
// Set the data exposed by the LiveData
if (data != null) {
recyclerAdapter.setData(data)
}
})
}
...
}
এখানে ইতিহাসের এই মুহুর্তে সংগ্রহস্থলটি ব্রাউজ করুন।
ডেটা বাইন্ডিং
XML লেআউটের সাথে সংযোগ করার জন্য প্রয়োজনীয় বয়লারপ্লেট কোড সরানোর জন্য ডেটা বাইন্ডিং লাইব্রেরি তৈরি করা হয়েছিল৷
আপনার কোটলিন প্রকল্পগুলিতে ডেটা বাইন্ডিং ব্যবহার করতে, আপনাকে ক্যাপ্ট কম্পাইলার প্লাগইন সহ টীকা প্রসেসরগুলির জন্য সমর্থন চালু করতে হবে। এছাড়াও অ্যান্ড্রয়েড কনফিগারেশন গ্রেডল ফাইলে ডেটা বাইন্ডিং ব্লক যোগ করুন:
...
apply plugin: 'kotlin-kapt'
android {
...
dataBinding {
enabled = true
}
}
...
ডেটা বাইন্ডিং জেনারেটেড ক্লাস ব্যবহার করতে, আমাদের সমস্ত ভিউ কোড <layo
এ রাখতে হবে ut> ট্যাগ। ডেটা বাইন্ডিংয়ের সবচেয়ে শক্তিশালী ধারণা হল যে আমরা কিছু ডেটা ক্লাসকে একটি xml লেআউট এবং আইটেম বৈশিষ্ট্যগুলিকে সরাসরি ক্ষেত্রগুলিতে আবদ্ধ করতে পারি।
<layout xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools">
<data>
<variable
name="cryptocurrency"
type="com.baruckis.mycryptocoins.data.Cryptocurrency" />
</data>
...
<android.support.v7.widget.AppCompatTextView
android:id="@+id/item_name"
style="@style/MainListItemPrimeText"
android:layout_marginEnd="@dimen/main_cardview_list_item_text_between_margin"
android:layout_marginStart="@dimen/main_cardview_list_item_inner_margin"
android:text="@{cryptocurrency.name}"
android:textAlignment="viewStart"
app:layout_constraintBottom_toTopOf="@+id/item_amount_symbol"
app:layout_constraintEnd_toStartOf="@+id/guideline1_percent"
app:layout_constraintStart_toEndOf="@+id/item_image_icon"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="spread"
tools:text="@string/sample_text_item_name" />
...
</layout>
ডেটা বিডিং সহ রিসাইক্লারভিউ অ্যাডাপ্টার দেখতে এইরকম হবে:
class MainRecyclerViewAdapter() : RecyclerView.Adapter<MainRecyclerViewAdapter.BindingViewHolder>() {
private lateinit var dataList: ArrayList<Cryptocurrency>
fun setData(newDataList: ArrayList<Cryptocurrency>) {
dataList = newDataList
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BindingViewHolder {
val inflater = LayoutInflater.from(parent.context)
val binding = FragmentMainListItemBinding.inflate(inflater, parent, false)
return BindingViewHolder(binding)
}
override fun onBindViewHolder(holder: BindingViewHolder, position: Int) = holder.bind(dataList[position])
override fun getItemCount(): Int = dataList.size
...
inner class BindingViewHolder(var binding: FragmentMainListItemBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(cryptocurrency: Cryptocurrency) {
binding.cryptocurrency = cryptocurrency
binding.itemRanking.text = String.format("${cryptocurrency.rank}")
...
binding.executePendingBindings()
}
}
}
শেষ পর্যন্ত আর findViewById
লেখা নেই ? এখানে ইতিহাসের এই মুহুর্তে সংগ্রহস্থলটি ব্রাউজ করুন।
রুম
আমাদের অ্যাপকে ব্যবহারকারীর ধারণ করা বিভিন্ন ক্রিপ্টোকারেন্সির ক্রমাগত ডেটা সংরক্ষণ করতে হবে। এটি স্থানীয় ডেটাবেসের মধ্যে সংরক্ষণ করা উচিত যা ব্যক্তিগতভাবে Android ডিভাইসের ভিতরে রাখা হয়।
একটি প্রাইভেট ডাটাবেসে স্ট্রাকচার্ড ডেটা সংরক্ষণের জন্য আমরা একটি SQLite ডাটাবেস ব্যবহার করব। এটি প্রায়শই সেরা পছন্দ।
আমাদের অ্যাপের জন্য SQLite ডাটাবেস তৈরি করতে আমরা রুম ব্যবহার করব। রুম হল একটি অধ্যবসায় লাইব্রেরি যা Android টিম দ্বারা তৈরি করা হয়েছে যা SQLite-এর উপরে একটি মোড়ক। এটি একটি বিমূর্ততা স্তর যা SQLite এর সাথে ইন্টারঅ্যাক্ট করার জন্য আপনার প্রয়োজনীয় বয়লারপ্লেট কোডের অনেকাংশ সরিয়ে দেয়। এটি আপনার এসকিউএল কোয়েরির কম্পাইল-টাইম চেকিং যোগ করে।
এটিকে ভাবার সর্বোত্তম উপায় হল একটি ORM (অবজেক্ট রিলেশনাল ম্যাপার) টুল যা স্বয়ংক্রিয়ভাবে আপনার অবজেক্ট ইনস্ট্যান্স এবং আপনার ডাটাবেসের সারিগুলির মধ্যে ম্যাপ করার জন্য আঠালো কোড তৈরি করার জন্য ডিজাইন করা হয়েছে৷
রুমে মূলত ৩টি প্রধান উপাদান রয়েছে:
- সত্তা — এই উপাদানটি এমন একটি শ্রেণিকে প্রতিনিধিত্ব করে যা একটি ডাটাবেস সারি ধারণ করে। প্রতিটি সত্তার জন্য, আইটেমগুলিকে ধরে রাখার জন্য একটি ডাটাবেস টেবিল তৈরি করা হয়।
- DAO (ডেটা অ্যাক্সেস অবজেক্ট) - প্রধান উপাদান যা ডাটাবেস অ্যাক্সেস করার পদ্ধতিগুলি সংজ্ঞায়িত করার জন্য দায়ী৷
- ডাটাবেস — একটি উপাদান যা একটি ধারক শ্রেণি যা সত্তার তালিকা, DAO-এর তালিকা এবং ডাটাবেস সংস্করণ নির্ধারণ করতে টীকা ব্যবহার করে এবং অন্তর্নিহিত সংযোগের জন্য প্রধান অ্যাক্সেস পয়েন্ট হিসাবে কাজ করে।
আমাদের My Crypto Coins অ্যাপে রুম সেটআপ করার জন্য এই সহজ ধাপগুলি অনুসরণ করুন:
- একটি সত্তা তৈরি করুন৷ ৷
@Entity
data class Cryptocurrency(val name: String,
val rank: Short,
val amount: Double,
@PrimaryKey
val symbol: String,
val price: Double,
val amountFiat: Double,
val pricePercentChange1h: Double,
val pricePercentChange7d: Double,
val pricePercentChange24h: Double,
val amountFiatChange24h: Double)
ডাটাবেসে রুমকে এর গঠন সম্পর্কে জানাতে কিছু অতিরিক্ত তথ্য যোগ করুন।
2. DAO তৈরি করুন৷
৷@Dao
interface MyCryptocurrencyDao {
@Query("SELECT * FROM Cryptocurrency")
fun getMyCryptocurrencyLiveDataList(): LiveData<List<Cryptocurrency>>
@Insert
fun insertDataToMyCryptocurrencyList(data: List<Cryptocurrency>)
}
শুরুর জন্য, আমরা একটি DAO তৈরি করতে যাচ্ছি যা শুধুমাত্র আমাদের সত্তার সাথে তৈরি করা টেবিল থেকে রেকর্ড পুনরুদ্ধার করতে এবং কিছু নমুনা ডেটা সন্নিবেশ করার অনুমতি দেয়৷
3. ডেটাবেস তৈরি এবং সেটআপ করুন৷
৷এটা বলা গুরুত্বপূর্ণ যে ডেটাবেস ইনস্ট্যান্স আদর্শভাবে প্রতি সেশনে শুধুমাত্র একবার তৈরি করা উচিত। এটি অর্জনের একটি উপায় হল একটি সিঙ্গেলটন প্যাটার্ন ব্যবহার করা।
@Database(entities = [Cryptocurrency::class], version = 1, exportSchema = false)
abstract class AppDatabase : RoomDatabase() {
abstract fun myCryptocurrencyDao(): MyCryptocurrencyDao
// The AppDatabase a singleton to prevent having multiple instances of the database opened at the same time.
companion object {
// Marks the JVM backing field of the annotated property as volatile, meaning that writes to this field are immediately made visible to other threads.
@Volatile
private var instance: AppDatabase? = null
// For Singleton instantiation.
fun getInstance(context: Context): AppDatabase {
return instance ?: synchronized(this) {
instance ?: buildDatabase(context).also { instance = it }
}
}
// Creates and pre-populates the database.
private fun buildDatabase(context: Context): AppDatabase {
return Room.databaseBuilder(context, AppDatabase::class.java, DATABASE_NAME)
// Prepopulate the database after onCreate was called.
.addCallback(object : Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
// Insert the data on the IO Thread.
ioThread {
getInstance(context).myCryptocurrencyDao().insertDataToMyCryptocurrencyList(PREPOPULATE_DATA)
}
}
})
.build()
}
// Sample data.
val btc: Cryptocurrency = Cryptocurrency("Bitcoin", 1, 0.56822348, "BTC", 8328.77, 4732.60, 0.19, -10.60, 0.44, 20.82)
val eth: Cryptocurrency = Cryptocurrency("Etherium", 2, 6.0, "ETH", 702.99, 4217.94, 0.13, -7.38, 0.79, 33.32)
val PREPOPULATE_DATA = listOf(btc, eth)
}
}
private val IO_EXECUTOR = Executors.newSingleThreadExecutor()
// Utility method to run blocks on a dedicated background thread, used for io/database work.
fun ioThread(f : () -> Unit) {
IO_EXECUTOR.execute(f)
}
আপনি যেমন প্রাথমিক রানে দেখতে পাচ্ছেন, শুধুমাত্র পরীক্ষার উদ্দেশ্যে কিছু নমুনা ডেটা দিয়ে ডাটাবেস তৈরি করা হবে৷
4. অতিরিক্ত ধাপ। সংগ্রহস্থল তৈরি করুন।
রিপোজিটরি আর্কিটেকচার কম্পোনেন্ট লাইব্রেরির অংশ নয়। এটি কোড বিভাজন এবং স্থাপত্যের জন্য একটি প্রস্তাবিত সেরা অনুশীলন৷
যদি আপনাকে একাধিক ডেটা উত্স পরিচালনা করতে হয় তবে এটি সমস্ত অ্যাপ ডেটার জন্য সত্যের একক উত্স হিসাবে দাঁড়িয়েছে৷
class MyCryptocurrencyRepository private constructor(
private val myCryptocurrencyDao: MyCryptocurrencyDao
) {
fun getMyCryptocurrencyLiveDataList(): LiveData<List<Cryptocurrency>> {
return myCryptocurrencyDao.getMyCryptocurrencyLiveDataList()
}
companion object {
// Marks the JVM backing field of the annotated property as volatile, meaning that writes to this field are immediately made visible to other threads.
@Volatile
private var instance: MyCryptocurrencyRepository? = null
// For Singleton instantiation.
fun getInstance(myCryptocurrencyDao: MyCryptocurrencyDao) =
instance ?: synchronized(this) {
instance
?: MyCryptocurrencyRepository(myCryptocurrencyDao).also { instance = it }
}
}
}
আমরা আমাদের ViewModel-এ এই সংগ্রহস্থলটি ব্যবহার করতে যাচ্ছি।
class MainViewModel(myCryptocurrencyRepository: MyCryptocurrencyRepository) : ViewModel() {
val liveData = myCryptocurrencyRepository.getMyCryptocurrencyLiveDataList()
}
আমাদের ফ্র্যাগমেন্ট কোডও বিকশিত হয়৷
class MainListFragment : Fragment() {
...
private lateinit var viewModel: MainViewModel
...
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
setupList()
subscribeUi()
}
...
private fun subscribeUi() {
val factory = InjectorUtils.provideMainViewModelFactory(requireContext())
// Obtain ViewModel from ViewModelProviders, using this fragment as LifecycleOwner.
viewModel = ViewModelProviders.of(this, factory).get(MainViewModel::class.java)
// Update the list when the data changes by observing data on the ViewModel, exposed as a LiveData.
viewModel.liveData.observe(this, Observer<List<Cryptocurrency>> { data ->
if (data != null && data.isNotEmpty()) {
emptyListView.visibility = View.GONE
recyclerView.visibility = View.VISIBLE
recyclerAdapter.setData(data)
} else {
recyclerView.visibility = View.GONE
emptyListView.visibility = View.VISIBLE
}
})
}
}
কারণ আমাদের ViewModel ক্লাসে এখন একটি কনস্ট্রাক্টর রয়েছে যা আর খালি নেই, আমাদের একটি প্রদানকারী কারখানার প্যাটার্ন বাস্তবায়ন করতে হবে। এটি ViewModelProviders.of()
-এ পাঠানো হবে দ্বিতীয় প্যারামিটার হিসাবে পদ্ধতি।
object InjectorUtils {
fun provideMainViewModelFactory(
context: Context
): MainViewModelFactory {
val repository = getMyCryptocurrencyRepository(context)
return MainViewModelFactory(repository)
}
private fun getMyCryptocurrencyRepository(context: Context): MyCryptocurrencyRepository {
return MyCryptocurrencyRepository.getInstance(
AppDatabase.getInstance(context).myCryptocurrencyDao())
}
}
class MainViewModelFactory(private val repository: MyCryptocurrencyRepository) : ViewModelProvider.NewInstanceFactory() {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return MainViewModel(repository) as T
}
}
এখানে ইতিহাসের এই মুহুর্তে সংগ্রহস্থলটি ব্রাউজ করুন।
চূড়ান্ত চিন্তা
ডিজাইন আর্কিটেকচার, যা আমরা এই অংশে আলোচনা করেছি, সেগুলিকে অবহিত নির্দেশিকা হিসাবে ব্যবহার করা উচিত কিন্তু একটি কঠিন নিয়ম নয়। আমি প্রতিটি বিষয়ে খুব বেশি বিস্তারিতভাবে যেতে চাইনি। অ্যান্ড্রয়েড আর্কিটেকচার উপাদানগুলির সাথে আমরা কোডিং প্রক্রিয়াটি দেখেছিলাম। মনে রাখবেন যে প্রতিটি উপাদানে পৃথকভাবে আরও অনেক কিছু শেখার আছে এবং আমি আপনাকে এটি করার পরামর্শ দিচ্ছি।
আসুন আমরা ইতিমধ্যে তৈরি করা সমস্ত কিছুর সংক্ষিপ্তসার করি:
- My Crypto Coins অ্যাপে, প্রতিটি আলাদা স্ক্রিনের নিজস্ব ViewModel আছে। এটি যেকোন কনফিগারেশন পরিবর্তন থেকে বাঁচবে এবং ব্যবহারকারীকে যেকোনো ডেটার ক্ষতি থেকে রক্ষা করবে।
- অ্যাপের ইউজার ইন্টারফেস একটি প্রতিক্রিয়াশীল প্রকার। এর মানে ব্যাক-এন্ডে ডেটা পরিবর্তন হলে এটি অবিলম্বে আপডেট হবে। এটি LiveData-এর সাহায্যে করা হয়৷ ৷
- ডাটা বাইন্ডিং ব্যবহার করে সরাসরি আমাদের কোডের ভেরিয়েবলের সাথে আবদ্ধ হওয়ার কারণে আমাদের প্রোজেক্টে কম কোড আছে।
- অবশেষে, আমাদের অ্যাপ একটি SQLite ডাটাবেস হিসাবে ডিভাইসের ভিতরে স্থানীয়ভাবে ব্যবহারকারীর ডেটা সঞ্চয় করে। ডাটাবেসটি রুম উপাদানের সাথে সুবিধাজনকভাবে তৈরি করা হয়েছিল। অ্যাপের কোড বৈশিষ্ট্য দ্বারা গঠিত এবং সমস্ত প্রজেক্ট আর্কিটেকচার হল MVVM — Android টিমের প্রস্তাবিত প্যাটার্ন৷
ভাণ্ডার
এখন, আপনি যেমন "ক্রিপ্টোফোলিও" (আগে "মাই ক্রিপ্টো কয়েন") অ্যাপটি দেখছেন তা সত্যিই আকার নিতে শুরু করেছে। এই অংশ 3-এর জন্য সর্বশেষ সংগ্রহস্থলের প্রতিশ্রুতি দিয়ে, আপনি এটিকে সঠিকভাবে গণনা করা মোট হোল্ডিং পোর্টফোলিও মান সহ ব্যবহারকারীর জন্য প্রাক-পপুলেটেড ডেটাবেস ডেটা দেখাচ্ছে।
GitHub-এ উৎস দেখুন
অ্যাচিউ! পড়ার জন্য ধন্যবাদ! আমি মূলত এই পোস্টটি আমার ব্যক্তিগত ব্লগ www.baruckis.com-এর জন্য 22 আগস্ট, 2018-এ প্রকাশ করেছি।