يركّز هذا الموضوع على بعض الجوانب الأكثر فائدة في لغة Kotlin. عند التطوير لأجهزة Android.
التعامل مع الأجزاء
تستخدم الأقسام التالية أمثلة باللغة Fragment
لتسليط الضوء على بعض من أمثلة
أفضل الميزات.
الاكتساب
يمكنك الإعلان عن فئة في لغة Kotlin باستخدام الكلمة الرئيسية class
. في ما يلي
على سبيل المثال، LoginFragment
هي فئة فرعية من Fragment
. يمكنك الإشارة إلى
التوريث باستخدام عامل التشغيل :
بين الفئة الفرعية والفئة الرئيسية التابعة لها:
class LoginFragment : Fragment()
في بيان الفئة هذا، تكون الدالة LoginFragment
مسؤولة عن استدعاء الدالة
دالة إنشاء لفئتها الفائقة، Fragment
.
ضمن LoginFragment
، يمكنك إلغاء عدد من معاودة الاتصال بمراحل النشاط إلى
الاستجابة لتغييرات الحالة في "Fragment
" لإلغاء دالة، استخدم دالة الاستدعاء
كلمة رئيسية واحدة (override
)، كما هو موضّح في المثال التالي:
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.login_fragment, container, false)
}
للإشارة إلى دالة في الفئة الرئيسية، استخدِم الكلمة الرئيسية super
على النحو الموضّح
في المثال التالي:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
}
القدرة على الإلغاء والإعداد
في الأمثلة السابقة، كان لبعض المعلمات في الطرق التي تم إلغاؤها
الأنواع اللاحقة بعلامة استفهام ?
. يشير هذا إلى أن الوسيطات
يمكن أن تكون قيمة تمرير هذه المعلمات فارغة. تأكد من
التعامل مع القيم الفارغة بطريقة آمنة.
في Kotlin، يجب تهيئة خصائص الكائن عند تعريف الكائن.
وهذا يعني أنه عند الحصول على مثيل لفئةٍ ما، يمكنك على الفور
يشير إلى أي من خصائصه التي يمكن الوصول إليها. الكائنات View
في Fragment
،
ومع ذلك، لن تكون جاهزة لتكبير حجمها حتى يتم الاتصال بـ Fragment#onCreateView
، لذلك
ستحتاج إلى طريقة لتأجيل إعداد السمة View
.
تتيح لك lateinit
تأجيل إعداد الموقع. عند استخدام lateinit
،
عليك إعداد موقعك في أقرب وقت ممكن.
يوضّح المثال التالي استخدام lateinit
لتعيين عناصر View
في
onViewCreated
:
class LoginFragment : Fragment() {
private lateinit var usernameEditText: EditText
private lateinit var passwordEditText: EditText
private lateinit var loginButton: Button
private lateinit var statusTextView: TextView
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
usernameEditText = view.findViewById(R.id.username_edit_text)
passwordEditText = view.findViewById(R.id.password_edit_text)
loginButton = view.findViewById(R.id.login_button)
statusTextView = view.findViewById(R.id.status_text_view)
}
...
}
إحالة ناجحة إلى SAM
يمكنك الاستماع إلى أحداث النقر في Android من خلال تنفيذ
واجهة OnClickListener
. يحتوي Button
عنصرًا على setOnClickListener()
.
التي تتطلب تنفيذ OnClickListener
.
تتضمن الدالة OnClickListener
طريقة تجريدية واحدة، وهي onClick()
، والتي يجب عليك
وتنفيذها. لأنّ السمة setOnClickListener()
تتخذ دائمًا OnClickListener
كـ
وسيطة، ولأن OnClickListener
تحتوي دائمًا على نفس ملخص الرسم البياني
يمكن تمثيل هذا التنفيذ باستخدام دالة مجهولة في
لغة Kotlin. تُعرف هذه العملية باسم
تحويل الطريقة التجريدية الواحدة،
أو الإحالة الناجحة إلى SAM
تحويل SAM يمكن أن يجعل الرمز الخاص بك أكثر وضوحًا. المثال التالي
كيفية استخدام الإحالات الناجحة من خلال استراتيجية التسويق (SAM) لتنفيذ OnClickListener
Button
:
loginButton.setOnClickListener {
val authSuccessful: Boolean = viewModel.authenticate(
usernameEditText.text.toString(),
passwordEditText.text.toString()
)
if (authSuccessful) {
// Navigate to next screen
} else {
statusTextView.text = requireContext().getString(R.string.auth_failed)
}
}
يتم تمرير الرمز داخل الدالة المجهولة إلى setOnClickListener()
ويتم تنفيذه عندما ينقر المستخدم على loginButton
.
الكائنات المصاحبة
العناصر المصاحبة
توفير آلية لتحديد المتغيرات أو الدوال المرتبطة
من الناحية النظرية إلى نوع ولكنها غير مرتبطة بكائن معين. مرافق
من هذه العناصر استخدام الكلمة الرئيسية static
في Java للمتغيّرات والطرق.
في المثال التالي، تكون TAG
قيمة ثابتة String
. لا تحتاج إلى عنوان URL فريد
مثيل String
لكل مثيل LoginFragment
، لذلك يجب عليك
تعريفها في كائن مصاحب:
class LoginFragment : Fragment() {
...
companion object {
private const val TAG = "LoginFragment"
}
}
يمكنك تحديد TAG
في المستوى الأعلى من الملف، ولكن
ملف قد يحتوي أيضًا على عدد كبير من المتغيرات والدوال والفئات
والتي تم تحديدها أيضًا على المستوى الأعلى. العناصر المصاحبة للمساعدة في الربط
والمتغيرات والدوال وتعريف الفئة دون الإشارة إلى أي
مثيل معين من تلك الفئة.
تفويض المواقع
عند إعداد الخصائص، يمكنك تكرار بعض أساليب Android الأكثر شيوعًا
مثل الوصول إلى ViewModel
داخل Fragment
. لتجنُّب المبالغة
يمكنك استخدام بنية تفويض الموقع في Kotlin.
private val viewModel: LoginViewModel by viewModels()
يوفِّر تفويض المواقع طريقة تنفيذ شائعة يمكنك إعادة استخدامها.
في جميع أنحاء التطبيق. توفّر لك منصة Android KTX بعض تفويضات العقارات.
على سبيل المثال، يسترد viewModels
قيمة ViewModel
التي تم تحديد نطاقها على
Fragment
الحالي.
يستخدم تفويض المواقع الانعكاس، مما يضيف بعض النفقات العامة للأداء. المقايضة هي بناء جملة موجز يوفر وقت التطوير.
القابلية للإلغاء
توفر لغة Kotlin قواعد صارمة حول قابلية القيم الفارغة للحفاظ على أمان النوع طوال
تطبيقك. في Kotlin، لا يمكن أن تحتوي مراجع الكائنات على قيم فارغة عن طريق
الافتراضي. لتعيين قيمة فارغة لمتغير، يجب الإعلان عن القيمة nullable
نوع المتغير من خلال إضافة ?
إلى نهاية نوع القاعدة.
التعبير التالي غير قانوني في لغة Kotlin، على سبيل المثال. name
من النوع
String
وغير قابلة للإلغاء:
val name: String = null
للسماح بقيمة خالية، يجب استخدام نوع String
قابل للقيم String?
، باعتباره
كما هو موضح في المثال التالي:
val name: String? = null
إمكانية التشغيل التفاعلي
إن قواعد Kotlin الصارمة تجعل التعليمة البرمجية أكثر أمانًا وإيجازًا. تقل هذه القواعد
احتمالات وجود NullPointerException
يمكن أن يؤدي إلى
والأعطال. علاوة على ذلك، فإنها تقلل عدد الشيكات الفارغة التي تحتاج إلى إجرائها في
الرمز.
في كثير من الأحيان، يجب أيضًا استدعاء رمز غير لغة البرمجة Kotlin عند كتابة تطبيق Android، كما تتم كتابة معظم واجهات برمجة تطبيقات Android بلغة برمجة Java.
وتُعد إمكانية القيم من المجالات الرئيسية التي تختلف فيها لغة Java وKotlin في السلوك. لغة Java أقل صارمة بشأن بناء جملة القيم الفارغة.
على سبيل المثال، تتضمّن الفئة Account
بعض السمات، من بينها السمة String
.
يسمى name
. لا تمتلك Java قواعد Kotlin حول قابلية القيم الفارغة،
بدلاً من ذلك، نعتمد على التعليقات التوضيحية الاختيارية المتعلقة بقابلية القيم الفارغة
ما إذا كان بإمكانك تعيين قيمة فارغة.
نظرًا لأن إطار عمل Android مكتوب بشكل أساسي بلغة Java، قد تواجه هذا السيناريو عند طلب الدخول إلى واجهات برمجة التطبيقات بدون التعليقات التوضيحية التي تؤدي إلى قبول القيم الفارغة.
أنواع المنصات
إذا كنت تستخدم لغة Kotlin للإشارة إلى عضو name
بدون تعليقات توضيحية تم تحديده في
فئة Account
في Java، لا يعرف برنامج التحويل البرمجي ما إذا كانت String
مرتبطة
String
أو String?
في Kotlin. يتم تمثيل هذا الغموض من خلال
نوع المنصة، String!
.
ليس لـ String!
أي معنى خاص في برنامج التجميع بلغة Kotlin. يمكن أن يمثّل String!
إما String
أو String?
، ويتيح لك برنامج التحويل البرمجي تعيين قيمة
أيًا من النوعين. تجدر الإشارة إلى أنّك تخاطر برمي NullPointerException
إذا
تمثيل النوع على أنّه String
وتعيين قيمة فارغة.
لمعالجة هذه المشكلة، يجب استخدام التعليقات التوضيحية التي تؤدي إلى قبول القيم الفارغة عندما تكتب التعليمات البرمجية في Java. تساعد هذه التعليقات التوضيحية مطوّري كل من Java وKotlin.
على سبيل المثال، إليك الفئة Account
كما هو محدّد في Java:
public class Account implements Parcelable {
public final String name;
public final String type;
private final @Nullable String accessId;
...
}
تمت إضافة تعليقات توضيحية إلى أحد متغيرات العضو، accessId
، باستخدام @Nullable
،
مما يشير إلى أنه يمكن أن يحتوي على قيمة فارغة. سيتعامل Kotlin بعد ذلك مع accessId
.
بصفتك String?
.
للإشارة إلى أنّه لا يمكن أن يكون أحد المتغيّرات فارغًا مطلقًا، استخدِم التعليق التوضيحي @NonNull
:
public class Account implements Parcelable {
public final @NonNull String name;
...
}
في هذا السيناريو، تُعتبر السمة name
String
غير قابلة للقيم الفارغة في لغة Kotlin.
تم تضمين التعليقات التوضيحية للقيم الفارغة في جميع واجهات برمجة تطبيقات Android الجديدة والعديد من واجهات برمجة تطبيقات Android. أضافت العديد من مكتبات Java تعليقات توضيحية ل قبول القيم الفارغة تدعم مطوري لغتَي Kotlin وJava.
التعامل مع إمكانية قبول القيم الفارغة
إذا لم تكن متأكدًا من نوع جافا، فيجب أن تعتبره قابلاً للقيم الفارغة.
على سبيل المثال، لا تتم إضافة تعليقات توضيحية للعضو name
في الفئة Account
، وبالتالي يمكنك
من المفترض أن تكون قيمة String
قابلة للقيم الفارغة.
إذا كنت تريد قطع السمة name
بحيث لا تشتمل قيمتها على بادئة أو
مسافة بيضاء لاحقة، يمكنك استخدام دالة trim
في Kotlin. يمكنك قطع
String?
بعدة طرق مختلفة تتمثل إحدى هذه الطرق في استخدام القيمة not-null
كما هو موضَّح في المثال التالي: !!
val account = Account("name", "type")
val accountName = account.name!!.trim()
يتعامل عامل التشغيل !!
مع كل شيء في جانبه الأيسر على أنه غير فارغ، ولذلك في
في هذه الحالة، فأنت تتعامل مع name
على أنها String
غير فارغة. إذا كانت نتيجة
التعبير على يساره فارغ، ثم يعرض تطبيقك NullPointerException
.
عامل التشغيل هذا سريع وسهل، ولكن يجب استخدامه باعتدال، لأنه يمكن
أعِد إدخال مثيلات NullPointerException
في الرمز الخاص بك.
هناك خيار أكثر أمانًا هو استخدام عامل تشغيل المكالمة الآمن، ?.
، كما هو موضّح في القسم
المثال التالي:
val account = Account("name", "type")
val accountName = account.name?.trim()
باستخدام عامل تشغيل الاتصال الآمن، إذا لم يكن name
قيمة خالية، تكون نتيجة
name?.trim()
هي قيمة اسم بدون مسافة بيضاء بادئة أو لاحقة. في حال حذف
name
قيمة خالية، فإن نتيجة name?.trim()
هي null
. هذا يعني أنّ
لا يمكن لتطبيقك إطلاق علامة NullPointerException
عند تنفيذ هذه العبارة.
على الرغم من أنّ عامل تشغيل المكالمات الآمنة ينقذك من NullPointerException
محتمَل،
فإنها تمرر قيمة فارغة إلى العبارة التالية. يمكنك بدلاً من ذلك التعامل مع القيم الفارغة
على الفور باستخدام عامل تشغيل Elvis (?:
)، كما هو موضّح في ما يلي
مثال:
val account = Account("name", "type")
val accountName = account.name?.trim() ?: "Default name"
إذا كانت نتيجة التعبير على الجانب الأيسر من عامل تشغيل Elvis هي
فارغ، يتم تعيين القيمة الموجودة على الجانب الأيمن إلى accountName
. هذا النمط
مفيد لتوفير قيمة افتراضية كانت بخلاف ذلك تكون فارغة.
يمكنك أيضًا استخدام عامل التشغيل Elvis للعودة من دالة مبكرًا، كما هو موضح في المثال التالي:
fun validateAccount(account: Account?) {
val accountName = account?.name?.trim() ?: "Default name"
// account cannot be null beyond this point
account ?: return
...
}
التغييرات في واجهة برمجة تطبيقات Android
أصبحت واجهات برمجة تطبيقات Android متوافقة بشكل متزايد مع لغة Kotlin. العديد من ميزات Android
تحتوي أكثر واجهات برمجة التطبيقات شيوعًا، بما في ذلك AppCompatActivity
وFragment
، على
التعليقات التوضيحية لقابلية القيم الفارغة، وبعض الطلبات مثل Fragment#getContext
لديها
المزيد من البدائل المتوافقة مع Kotlin.
على سبيل المثال، يكون الوصول إلى Context
لـ Fragment
غالبًا غير فارغ،
نظرًا لأن معظم الاتصالات التي تجريها في Fragment
تحدث أثناء استخدام Fragment
مُلحق بـ Activity
(فئة فرعية من Context
). ومع ذلك،
لا تعرض Fragment#getContext
دائمًا قيمة غير فارغة، حيث تتوفر
حيث لا يتم ربط Fragment
بـ Activity
. ومن ثم، يكون
نوع Fragment#getContext
قابل للقيم الفارغة.
بما أنّ قيمة Context
المعروضة من Fragment#getContext
قابلة للقيم الفارغة (
عليه التعليق كـ @Nullable)، فيجب التعامل معه كـ Context?
في رمز Kotlin.
يعني ذلك تطبيق أحد عوامل التشغيل المذكورة سابقًا لمعالجة
قبول القيم الفارغة قبل الوصول إلى خصائصها ودوالها. بالنسبة لبعض هذه الأشياء
يحتوي Android على واجهات برمجة تطبيقات بديلة توفر هذه الراحة.
على سبيل المثال، تعرض الدالة Fragment#requireContext
قيمة Context
غير خالية وطرح
IllegalStateException
إذا تم طلبها عندما تكون قيمة Context
فارغة. بهذه الطريقة،
يمكنك التعامل مع Context
الناتج على أنّه غير خالٍ بدون الحاجة إلى
الاتصال الآمن أو الحلول البديلة.
إعداد الموقع
لا يتم إعداد الخصائص في Kotlin تلقائيًا. يجب إعدادها عند تهيئة فئة التضمين.
يمكنك إعداد المواقع بعدّة طرق مختلفة. المثال التالي
توضح كيفية إعداد متغيّر index
من خلال تحديد قيمة له في
تصريح الفئة:
class LoginFragment : Fragment() {
val index: Int = 12
}
يمكن أيضًا تحديد هذا الإعداد في كتلة أداة الإعداد:
class LoginFragment : Fragment() {
val index: Int
init {
index = 12
}
}
في الأمثلة أعلاه، يتم إعداد index
عندما تكون LoginFragment
البيانات التي تم إنشاؤها.
ومع ذلك، قد تكون لديك بعض السمات التي لا يمكن إعدادها أثناء الكائن.
البناء. على سبيل المثال، ننصحك بالرجوع إلى View
من داخل
Fragment
، ما يعني أنّه يجب تضخيم تنسيق التنسيق أولاً. التضخم
لا تحدث عند إنشاء Fragment
. بدلاً من ذلك، يتم تضخيم صوت الجهاز عند إجراء الاتصال.
Fragment#onCreateView
تتمثل إحدى طرق معالجة هذا السيناريو في إعلان طريقة العرض على أنها قابلة للقيم الفارغة عليكم إعداده في أقرب وقت ممكن، كما هو موضح في المثال التالي:
class LoginFragment : Fragment() {
private var statusTextView: TextView? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
statusTextView = view.findViewById(R.id.status_text_view)
statusTextView?.setText(R.string.auth_failed)
}
}
على الرغم من أنّ هذه العملية تعمل على النحو المتوقّع، عليك الآن إدارة إمكانية قبول القيم الفارغة في View
.
متى احتجت إليها. الحل الأفضل هو استخدام lateinit
للنطاق الزمني View
كما هو موضح في المثال التالي:
class LoginFragment : Fragment() {
private lateinit var statusTextView: TextView
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
statusTextView = view.findViewById(R.id.status_text_view)
statusTextView.setText(R.string.auth_failed)
}
}
تسمح لك الكلمة الرئيسية lateinit
بتجنّب إعداد موقع عند
إنشاء الكائن. إذا تمت الإشارة إلى موقعك قبل إعداده،
تُطرح لغة Kotlin UninitializedPropertyAccessException
، لذا يُرجى التأكّد من
لإعداد موقعك في أسرع وقت ممكن.