دیتا بایندینگ در اندروید به چه شکل انجام می شود

جمعه 8 فروردین 1399

دیتا بایندینگ یک تکنیک بسیار مهم در برنامه نویسی اندروید است، ما در این مطلب قصد داریم کمی بیشتر درباره دیتا بایندینگ در اندروید صحبت کنیم.

 دیتا بایندینگ در اندروید به چه شکل انجام می شود

دیتا بایندینگ نوعی تکنیک است که در آن شما می توانید بخشی از اطلاعات خود را به برخی از عناصر بصری متصل کنید. در این پروسه هر بار که ورودی به روزرسانی می شود داده های عملیات اتصال داده به ویو نیز به روزرسانی می شود. این موضوع در دنیای برنامه نویسی یک موضوع جدید است و برای آن نیز کتابخانه ها و فریم ورک های بسیار زیادی وجود دارند که این کار را برای شما انجام خواهند داد. توجه ما در این مقاله به فریم ورک های فرانت اند نیست بلکه ما می خواهیم این کار را بر روی گوشی های موبایل انجام دهیم. گوگل کتابخانه مربوط به دیتا بایندینگ را در اندروید معرفی کرده است که در واقع بخشی از Android Jetpack می باشد.

مقدمه ای درباره دیتا بایندینگ در اندروید

اگر شما با کتابخانه Jetpack در اندروید آشنایی ندارید شاید دلیل این موضوع آن باشد که گوگل اعلام کرده است از این پس پشتیبانی از این کتابخانه را کاهش خواهد داد و به جای آن به سمت توسعه و پشتیبانی از کتابخانه های AndroidX حرکت خواهد کرد.( که این کتابخانه ها ورژن های جدیدی از کتابخانه های پشتیبانی اندروید به حساب می آیند).

امروزه مقاله های بسیار زیادی وجود دارند که به صورت کامل توضیح می دهند چگونه می توانید عملیات دیتا بایندینگ را با استفاده از یک آداپتور انجام دهید، اما در بسیاری از این مقالات به نکات مهمی دقت نمی شود. در عوض من در این مطلب قصد دارم یک روش جدید را به شما معرفی کنم که با کمترین کد می توانید عملیات دیتا بایندینگ در اندروید را انجام دهید که این کار در زمان شما برای برنامه نویسی صرفه جویی خواهد کرد.

 دیتا بایندینگ

چرا باید از دیتا بایندینگ در برنامه نویسی اندروید استفاده کنیم؟

اگر تا به حال خودتان متوجه نشده اید من در یک مثال قصد دارم توضیح دهم که استفاده از دیتا بایندینگ می تواند چه مزیت هایی را برای شما داشته باشد. اجازه دهید فرض کنیم که شما یک منو دارید که در آن سه دکمه شخصی سازی شده وجود دارند که هر دکمه دارای یک layout درون خود می باشد.

 دیتا بایندینگ

یک راه برای تولید تمامی این موارد استفاده از 4 XML layout مختلف می باشد که یکی برای لایه اصلی و 3 مورد دیگر برای هر یک از دکمه ها می باشد.

شما به انجام این کار نیازمند هستید چرا که هر دکمه کاربر شما را وارد بخش مختلفی از اپلیکیشن می کند و بنابراین نیازمند متن و تصویر جدیدی می باشد.

در ادامه یک لایه برای دکمه را ایجاد کرده ایم:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://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>

توجه داشته باشید که در این جا زیاد کار تکراری انجام نمی دهیم چرا که ما تنها 3 طرح مختلف داریم ولی اگر به درستی درباره آن فکر کنید متوجه می شوید که یک کار کاملا خسته کننده را انجام می دهید که کاملا اتلاف وقت است. اگر برنامه ای را در نظر بگیرید که طرح های پیچیده تری را داشته باشد که ممکن است محصولات و تصاویر مختلفی را به کاربران خود ارائه دهد نوشتن کدهای مربوط به آن می تواند بسیار خسته کننده باشد.

با استفاده از دیتا بایندینگ ما تنها یک لایه XML را ایجاد خواهیم کرد که می تواند برای تمامی دکمه های ما مورد استفاده قرار گیرد.

پروسه دیتا بایندینگ را از کجا شروع کنیم؟

در ابتدا ما باید به پروژه خود اجازه دهیم که دیتا بایندینگ را فعال کند. برای انجام این کار ما نیاز داریم که عنصر دیتا بایندینگ را به فایل build.gradle در پروژه خود اضافه کنیم:

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'

       }

    }

}

بعد از آن که پروژه خود را دوباره راه اندازی کردیم می توانیم کلاس مربوط به داده های خود را ایجاد کنیم که از آن برای دیتا بایندینگ لایه خود استفاده خواهیم کرد.

package com.tomerpacific.example


import android.graphics.drawable.Drawable


data class ButtonData(val buttonText: String, val buttonImageSrc : Drawable)

حتما به این نکته توجه داشته باشید که کلاس ButtonData ما دارای دو فیلد می باشد:

buttonText که در زیر تصویر ما نمایش داده می شود.

button Image Src که مسئولیت تصویر دکمه ما را بر عهده دارد.

اگر ما نیازمند داده های بیشتری باشیم تنها کافی است که فیلدهای بیشتری را به کلاس خود اضافه کنیم.

 دیتا بایندینگ

Data binding واقعی در اندروید( بخش اول)

در مرحله بعدی ما نیاز داریم که یک متغیر ویژگی را به لایه خود اضافه کنیم تا در ادامه از آن استفاده کنیم. این متغیر به کلاس داده ما متصل می شود که ما آن را ایجاد کردیم. برای انجام این کار دو کار است که ما باید آنها را انجام دهیم:

-          عنصر لایه روت خود را در تگ لیوت قرار دهیم.

-          یک تگ داده را اضافه کنیم که شامل تعریف متغیر ما می باشد(buttonData).

<?xml version="1.0" encoding="utf-8"?>

<layout xmlns:android="http://schemas.android.com/apk/res/android">  // <---- 1

                                                                             

    <data>

       <variable name="buttonData" type="com.tomerpacific.example.ButtonData"/> // <---- 2

    </data>

    

    <androidx.constraintlayout.widget.ConstraintLayout xmlns:app="http://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>

توجه داشته باشید که حال می توانیم شما را از لایه اصلی قبلی خود حذف کنیم چرا که آن را به تگ لایه روت خود منتقل کرده ایم. علاوه بر این متغیری که ما آن را اضافه کرده ایم به صورت مستقیم به کلاس داده ما متصل شده است.

 دیتا بایندینگ

Data binding واقعی در اندروید( بخش دوم)

در فایل MainActivity ما نیازمند کدهایی هستیم که این بایندینگ را برای ما مدیریت کنند:

package com.tomerpacific.example


import android.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 را فراخوانی می کند و بنابراین کلاس بایندینگ با نام Activity Main 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 را زمانی که قصد داریم از آن در لایه خود استفاده کنیم override کنیم.

بعد از آن ما نیاز داریم که references را در 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 می سازیم. در مرحله بعدی شی Button Data را مقداردهی می کنیم و به شی بایندینگ خود متصل می کنیم. در انتها ما می توانیم از کلاس دیتا خود در کل لایه استفاده کنیم.

<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>

 دیتا بایندینگ

این مطلب براساس تجربه من در زمینه برنامه نویسی اندروید نوشته شده است که امیدوارم مطالعه آن برای شما مفید بوده باشد و اطلاعات مورد نیاز را در اختیار شما قرار داده باشد. در پایان تشکر می کنیم از شما که این مطلب را تا انتها مطالعه کرده و ما را همراهی کردید.

برنامه نویسان

نویسنده 3355 مقاله در برنامه نویسان

کاربرانی که از نویسنده این مقاله تشکر کرده اند

در صورتی که در رابطه با این مقاله سوالی دارید، در تاپیک های انجمن مطرح کنید