ডেটা বাইন্ডিং হল একটি কৌশল যা আপনি ব্যবহার করেন যখন আপনি তথ্যের টুকরোها (আপনার ডেটা) কিছু ভিজ্যুয়াল ইউজার ইনপুট এলিমেন্টের সাথে আটকে দিতে চান। এই প্রক্রিয়ায়, যখনই ইনপুট আপডেট হয়, তার পেছনের ডেটাও আপডেট হয়ে যায়।
এটি কোনো নতুন ধারণা নয়, এবং এই ধারণাটি তাদের ডিজাইনে অন্তর্ভুক্ত করা অনেক ফ্রেমওয়ার্ক রয়েছে (যেমন AngularJS/React/Vue)।
এই নিবন্ধে আমাদের ফোকাস ফ্রন্ট-এন্ড ফ্রেমওয়ার্কের ওপর নয়, বরং মোবাইল ডেভেলপমেন্টের ওপর। Google Android-এ Data Binding Library চালু করেছে, যা Android Jetpack-এর অংশ।
যদি আপনি Jetpack লাইব্রেরি স্যুট সাথে পরিচিত না হন, তবে এর কারণ হতে পারে Google ঘোষণা করেছে যে এটি সাপোর্ট লাইব্রেরিগুলোর ডেভেলপমেন্ট বন্ধ করবে। বরং এটি AndroidX লাইব্রেরিগুলো (যা সাপোর্ট লাইব্রেরির নতুন সংস্করণ) সাপোর্ট করার দিকে যাবে।
আমি জানি ডেটা বাইন্ডিং অ্যাডাপ্টার ব্যবহার করে কীভাবে ব্যবহার করবেন সে নিয়ে অনেক নিবন্ধ রয়েছে, কিন্তু এই টুকরো সেটি ফোকাস করবে না। বরং, আমি ডেটা বাইন্ডিং-এর একটি নগ্ন, ন্যূনতম পদ্ধতি দেখাব যা আপনার লেখা কোডের পরিমাণ কমিয়ে আপনার সময় বাঁচাতে পারে।
কেন ডেটা বাইন্ডিং ব্যবহার করবেন?
আপনি এখনো নিশ্চিত হয়নি, তবে আসুন কয়েক মিনিট ব্যয় করে ডেটা বাইন্ডিং-এর সুবিধা একটি উদাহরণ দিয়ে ব্যাখ্যা করি। মনে করুন আপনার একটি মেনু আছে তিনটি কাস্টম বাটনের সাথে, যেখানে প্রতিটি বাটন নিজস্ব একটি লেআউট।
এটি জেনারেট করার একটি পদ্ধতি হল চারটি আলাদা XML লেআউট ব্যবহার করা: একটি মেইন লেআউটের জন্য এবং তিনটি বাটনের জন্য প্রত্যেকের জন্য একটি।
আপনাকে এটি করতে হবে কারণ প্রতিটি বাটন ব্যবহারকারীকে আপনার অ্যাপ্লিকেশনের আলাদা অংশে নিয়ে যাবে এবং তাই আলাদা টেক্সট এবং আলাদা ছবির প্রয়োজন হবে।
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="https://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_gravity="center_horizontal" android:layout_height="wrap_content" android:layout_width="wrap_content"> <ImageView android:id="@+id/imageView" android:layout_height="100dp" android:layout_width="100dp" android:src="@drawable/image_name" android:adjustViewBounds="true" android:scaleType="centerInside" /> <TextView android:id="@+id/textView" android:gravity="center_horizontal" android:layout_height="wrap_content" android:layout_width="match_parent" android:text="Image Text" android:textSize="16sp" /> </LinearLayout>
এতে যaceous, কোড ডুপ্লিকেশন বেশি নয় কারণ আমরা শুধু তিনটি লেআউট হ্যান্ডল করছি। কিন্তু চিন্তা করলে, সেটি সম্পূর্ণ সময়ের বর্জনা। যদি আপনি একটি আরও জটিল লেআউট 가진 অ্যাপ্লিকেশনের কথা চিন্তা করেন, যা পণ্য এবং তাদের ছবি প্রদর্শন করতে পারে, তবে এটি অনেক বিরক্তিকর কোড রেপ্লিকেশনে দাঁড়াতে পারে।
ডেটা বাইন্ডিং-এর সাথে, আমরা মাত্র একটি XML লেআউট তৈরি করব যা আমাদের সব বাটন ব্যবহার করবে।
আমরা কোথা থেকে শুরু করব?
আমাদের প্রজেক্টে ডেটা বাইন্ডিং সক্ষম করতে হবে। সেটির জন্য, আমাদের অ্যাপ্লিকেশনের build.gradle ফাইলে dataBinding এলিমেন্ট যোগ করতে হবে:
android { compileSdkVersion 29 buildToolsVersion "29.0.2" defaultConfig { applicationId "com.tomerpacific.example" minSdkVersion 15 targetSdkVersion 29 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" dataBinding { //<------- enabled = true } } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } }
প্রজেক্ট সিঙ্ক্রোনাইজ করার পর, আমরা আমাদের ডেটা ক্লাস তৈরি করব, jota আমরা লেআউটের সাথে বাইন্ড করব।
package com.tomerpacific.example import android.graphics.drawable.Drawable data class ButtonData(val buttonText: String, val buttonImageSrc : Drawable)
লক্ষ্য করুন যে আমাদের ButtonData ক্লাসে দুটি ফিল্ড রয়েছে:
buttonText— এটি হল টেক্স্ট যা আমাদের ছবির নিচে দেখাবে।buttonImageSrc— এটি বাটনের ছবির জন্য দায়ী।
আমরা আরও ডেটা চাইলে, আমরা শুধু আমাদের ডেটা ক্লাসে আরও ফিল্ড যোগ করব।
আসল বাইন্ডিং
পরবর্তীতে, আমাদের লেআউটে একটি ভেরিয়েবল প্রপার্টি ডিক্লেয়ার করতে হবে যাতে তা ব্যবহার করা যায়। এই ভেরিয়েবলটি আমাদের তৈরি করা ডেটা ক্লাসের সাথে বাউন্ড হবে। এটি করার জন্য দুটি কাজ করতে হবে:
- আমাদের রুট লেআউট এলিমেন্টকে একটি layout ট্যাগে মোড়ানো।
- একটি data ট্যাগ যোগ করা যাতে আমাদের ভেরিয়েবল (
buttonData) এর ঘোষণা থাকে।
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="https://schemas.android.com/apk/res/android"> // <---- 1 <data> <variable name="buttonData" type="com.tomerpacific.example.ButtonData"/> // <---- 2 </data> <androidx.constraintlayout.widget.ConstraintLayout xmlns:app="https://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Example" android:textSize="30dp" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:orientation="vertical" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@+id/linearLayout3" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/textView2"> <ImageButton android:layout_width="100dp" android:layout_height="100dp" android:adjustViewBounds="true" android:scaleType="centerInside" android:src="@drawable/android"> </ImageButton> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:text="Image Text" android:textSize="16sp" /> </LinearLayout> <LinearLayout android:id="@+id/linearLayout3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:orientation="vertical" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/textView2" app:layout_constraintVertical_bias="0.504"> <ImageButton android:layout_width="100dp" android:layout_height="100dp" android:adjustViewBounds="true" android:scaleType="centerInside" android:src="@drawable/android_p_logo"> </ImageButton> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:text="Image Text" android:textSize="16sp" /> </LinearLayout> <LinearLayout android:id="@+id/linearLayout2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:orientation="vertical" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.200" app:layout_constraintStart_toEndOf="@+id/linearLayout3" app:layout_constraintTop_toBottomOf="@+id/textView2" app:layout_constraintVertical_bias="0.504"> <ImageButton android:layout_width="100dp" android:layout_height="100dp" android:adjustViewBounds="true" android:scaleType="centerInside" android:src="@drawable/android_studio_icon"> </ImageButton> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:text="Image Text" android:textSize="16sp" /> </LinearLayout> </androidx.constraintlayout.widget.ConstraintLayout> </layout>
লক্ষ্য করুন যে আমরা আমাদের আগের মেইন লেআউট থেকে স্কিমা সরাতে পারি কারণ তা রুট layout ট্যাগে স্থানান্তরিত হয়েছে। এছাড়া, আমরা যে ভেরিয়েবলটি যোগ করেছি তা সরাসরি আমাদের ডেটা ক্লাসের সাথে যুক্ত।
আমাদের MainActivity ফাইলে, বাইন্ডিং হ্যান্ডেল করার জন্য কোড যোগ করতে হবে:
package com.tomerpacific.example import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import androidx.databinding.DataBindingUtil import com.tomerpacific.example.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val binding: ActivityMainBinding = DataBindingUtil.setContentView( this, R.layout.activity_main) binding.buttonData = ButtonData("First", resources.getDrawable(R.drawable.android)) } }
প্রতিবার আপনি একটি লেআউটের ভিতরে একটি ভেরিয়েবল তৈরি করলে, সেই লেআউটের জন্য একটি বাইন্ডিং ক্লাস স্বয়ংক্রিয়ভাবে জেনারেট হয়। আমাদের কেসে, আমাদের লেআউটের নাম activity_main, তাই বাইন্ডিং ক্লাসের নাম হবে ActivityMainBinding।
কনভেনশনটি সবসময় লেআউটের নামের সাথে Binding যোগ করা।
যেহেতু আমরা লেআউটে buttonData আমাদের ভেরিয়েবল হিসেবে ডিক্লেয়ার করেছি, তাই সেটি বাইন্ডিং অবজেক্টে যুক্ত হয়ে যায় এবং আমরা আমাদের ButtonData ক্লাসের একটি নতুন ইনস্ট্যান্স এসাইন করতে পারি।
এটি সব করার পর, আমরা আমরা লেআউটে আমরা যা ডেটা বাইন্ড করেছি সেটি ব্যবহার করতে পারি।
<LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:orientation="vertical" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@+id/linearLayout3" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/textView2"> <ImageButton android:layout_width="100dp" android:layout_height="100dp" android:adjustViewBounds="true" android:scaleType="centerInside" android:src="@{buttonData.buttonImageSrc}"> // <---- </ImageButton> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:text="@{buttonData.buttonText}" // <---- android:textSize="16sp" />
এবং ফলাফল হল:
এক সেকেন্ড রুকুন…
আমাদের তিনটি বাটন আছে এবং আমাদের ডেটা ক্লাস শুধু একটি বাটনের জন্য ব্যবহার করা যেতে পারে, তাহলে আমরা এটি কীভাবে পার করব?
package com.tomerpacific.example data class ButtonsData(val buttonsData : List<ButtonData>) { fun get(index: Int) : ButtonData { return buttonsData.get(index) } }
আমাদের get মেথড ওভাররাইড করতে হয়েছিল কারণ লেআউটে ব্যবহার করার সময় সেটি চেনা যায়।
তারপর, আমাদের activity_main.xml-এ রেফারেন্সগুলো পরিবর্তন করতে হবে:
<data> <variable name="buttonsData" type="com.tomerpacific.example.ButtonsData"/> </data>
এবং আমাদের নতুন ডেটা ক্লাসের সাথে একটি নতুন বাইন্ডিং তৈরি করতে হবে:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val binding: ActivityMainBinding = DataBindingUtil.setContentView( this, R.layout.activity_main) val firstButton : ButtonData = ButtonData("First", resources.getDrawable(R.drawable.android)) val secondButton : ButtonData = ButtonData("Second", resources.getDrawable(R.drawable.android_p_logo)) val thirdButton : ButtonData = ButtonData("Third", resources.getDrawable(R.drawable.android_studio_icon)) val buttonsData : ButtonsData = ButtonsData(listOf(firstButton, secondButton, thirdButton)) binding.buttonsData = buttonsData }
আমরা ButtonData ক্লাসের তিনটি ইনস্ট্যান্স তৈরি করি। তারপর আমরা একটি ButtonsData অবজেক্ট ইনস্ট্যান্টিয়েট করি এবং সেটি আমাদের বাইন্ডিং অবজেক্টের সাথে অ্যাটাচ করি।
শেষে, আমরা আমাদের ডেটা ক্লাসকে আমাদের লেআউটে সঠিকভাবে ব্যবহার করতে পারি:
<LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:orientation="vertical" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@+id/linearLayout3" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/textView2"> <ImageButton android:layout_width="100dp" android:layout_height="100dp" android:adjustViewBounds="true" android:scaleType="centerInside" android:src="@{buttonsData.get(0).buttonImageSrc}"> // <------- </ImageButton> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:text="@{buttonsData.get(0).buttonText}" // <-------- android:textSize="16sp" /> </LinearLayout>
এই নিবন্ধটি আমার নিচের অ্যাপ্লিকেশন ডেভেলপ করার অভিজ্ঞতার কারণে লেখা হয়েছে:
(আপনি কখনো জানেন না, এটি উপকারী হতে পারে)
Laundry Symbols - Apps on Google Play
কখনো কখনো লন্ড্রি চিহ্নগুলো কী বোঝায় তা বুঝতে কষ্ট হয়? তাহলে আপনি পার্টিকিউলারলি সৌভাগ্যবান! এই অ্যাপে সেই অদ্ভুত চিহ্নগুলো সব ব্যাখ্যা রয়েছে সহজ ইন্টারফেস এবং ছবির সাথে
tomerpacificApps on Google Play
আপনি সম্পূর্ণ সোর্স কোড এখানে দেখতে পারেন:
TomerPacific/LaundrySymbols
Kotlin-এ লেখা একটি অ্যাপ্লিকেশন যা বিভিন্ন লন্ড্রি চিহ্ন এবং ব্যাখ্যা প্রদর্শন করে :cyclone: - TomerPacific/LaundrySymbols
TomerPacificGitHub