OOZOU
تواصلوا معنا
العودة إلى المدونة

الوصول إلى نصوص الموارد في ViewModel من دون تسريب الـ Context

كيف تصلون إلى نصوص الموارد (Resource Strings) من دون استخدام AndroidViewModel

19 ديسمبر 2020
3 دقائق للقراءة
الوصول إلى نصوص الموارد في ViewModel من دون تسريب الـ Context

مقدمة

إذا كنتم تكتبون كود Android منذ فترة، فلا بد أنكم وجدتم أنفسكم في موقف أردتم فيه الوصول إلى نصوص الموارد (resource strings) داخل الـ ViewModel. والحل البديهي لدى معظم المطوّرين هو استخدام AndroidViewModel، الذي يمنحكم الوصول إلى الـ application context.

المشكلة

عيب هذا الأسلوب أنه يصعّب كتابة اختبارات الوحدة (unit tests) للـ ViewModel، لأنكم ستضطرون إلى التعامل مع محاكاة (mocking) الـ context الخاص بـ Android. كما أنه لا يتوسع جيدًا مع التطبيقات التي تدعم عدة لغات، لأن دورة حياة الـ ViewModel منفصلة عن دورة حياة الـ activities والـ fragments. إذا كان تطبيقكم يدعم عدة لغات، فأنتم تعرفون أنه حين يغيّر المستخدمون لغة التطبيق، يُعاد إنشاء الـ activity ويُحدَّث الـ context الخاص بها، وبذلك يرى المستخدم نصوص التطبيق باللغة الجديدة. لكن تذكروا أن الـ ViewModel ما زال يحتفظ بمرجع إلى الـ application context، الذي لا يُحدَّث حين تُدمَّر الـ activity ويُعاد إنشاؤها، لأن الـ application context يبقى كما هو طوال عمر العملية (process) الجارية حاليًا للتطبيق. لذلك سيستمر الـ application context في الـ ViewModel في جلب نصوص الموارد باللغة القديمة، رغم أن المستخدم غيّر اللغة. ولكي يرى المستخدم نصوص التطبيق باللغة الجديدة، سيضطر إلى إنهاء عملية التطبيق ثم إعادة تشغيله، وعندها سيُحدَّث الـ application context بطبيعة الحال. وهذه على الأرجح ليست التجربة التي نريدها لمستخدمينا. فكيف نحل هذه المشكلة بطريقة نظيفة؟

الحل

أنشئوا extension function تعمل كغلاف للخاصية التي تحتاج إلى نص المورد في الواجهة. على سبيل المثال، لنفترض أننا نريد عرض رسائل الخطأ في TextInputLayout. سيكون لدينا:

fun TextInputLayout.setResError(resError: Int?) {
    resError?.<em>let </em><strong>{
        </strong>setError(<em>context</em>.resources.getString(<strong>it</strong>))
    <strong>} </strong>?: setError(null)
}

بعد ذلك ننشئ binding adapter للوصول إلى الـ extension function أعلاه من كود الـ XML الخاص بالواجهة.

@BindingAdapter("app:errorRes")
fun setErrorMessage(view: TextInputLayout, resError: Int?): Unit {
    view.<em>setResError</em>(resError)
}

ثم يكون لدينا في الـ ViewModel:

class ExampleViewModel: ViewModel() {<pre>    
    <strong>val error = MutableLiveData<Int>()
</strong>
    init {
       validateForm()
    }

    fun validateForm() {
       <strong>error.value = R.string.error_not_empty</strong>
    }
}

وأخيرًا، نعرض الـ TextInputLayout في ملف XML كما يلي:

<com.google.android.material.textfield.TextInputLayout
    android:id="@+id/field_password"
    <strong>app:errorRes="@{viewModel.error}"</strong>
    >

    <com.google.android.material.textfield.TextInputEditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</com.google.android.material.textfield.TextInputLayout>
<br>

كيف يعمل ذلك؟

كلما أطلقت الخاصية error في الـ ViewModel قيمة من نوع Int (وهي معرّف نص المورد)، يُستدعى الـ binding adapter app:errorRes، الذي يستدعي بدوره الـ extension function setResError. تستخدم هذه الدالة بعد ذلك الـ context الخاص بالواجهة (وهو الـ context الخاص بالـ activity وليس الـ application context) لجلب النص. ثم يُستخدم النص الناتج لتعيين قيمة خاصية error في TextInputLayout. وهكذا، كلما غيّر المستخدم لغة التطبيق وتحدّث الـ context الخاص بالـ activity، لن يكون لديكم ما يقلقكم بعد الآن. إذا كنتم تحبون العمل في بيئة تتيح لكم الإبداع التقني، ففكروا في الانضمام إلى فريقنا في Oozou.

Related Articles

كيف أصمّم برمجيات؟ دليل المبتدئين لأصحاب الأعمال

كيف أصمّم برمجيات؟ دليل المبتدئين لأصحاب الأعمال

تصميم البرمجيات عملية ممتعة لكنها معقدة، تتطلب الإبداع والتفكير المنطقي ومهارات حل المشكلات.

اقرأوا المزيد
مستقبل الحوسبة الطرفية: ما تحتاج الشركات إلى معرفته

مستقبل الحوسبة الطرفية: ما تحتاج الشركات إلى معرفته

يتطور المشهد الرقمي بسرعة، وعلى الشركات أن تتكيّف لتواكب الطلب المتزايد على السرعة والكفاءة والمعالجة في الوقت الفعلي.

اقرأوا المزيد
مستقبل قطاع التجزئة: الذكاء الاصطناعي والواقع المعزّز واتجاهات التحوّل الرقمي

مستقبل قطاع التجزئة: الذكاء الاصطناعي والواقع المعزّز واتجاهات التحوّل الرقمي

يتطور قطاع التجزئة بوتيرة غير مسبوقة بفضل الذكاء الاصطناعي (AI) والواقع المعزّز (AR) وتقنيات التحوّل الرقمي. فلم تعد المتاجر التقليدية مجرد أماكن لبيع المنتجات، بل أصبحت متاجر ذكية وتفاعلية.

اقرأوا المزيد

Have a Project in Mind?

Let's discuss how we can help bring your ideas to life with our expertise in web and mobile development.

ابدأوا المحادثةhello@oozou.com
OOZOU Logo

بانكوك · سنغافورة · هونغ كونغ

X
Facebook
Instagram
LinkedIn
OOZOU Co., Ltd.
548 One City Centre
Ploenchit Road
Bangkok 10330
Thailand
+66 2544 0000
hello@oozou.com

الخدمات

  • تطوير الويب
  • وكلاء الذكاء الاصطناعي والذكاء الاصطناعي التوليدي
  • تطوير تطبيقات الجوال
  • تحليلات البيانات وهندستها
  • تصميم تجربة المستخدم وواجهته (UX/UI) وتصميم المنتجات
  • التحوّل الرقمي

الشركة

  • من نحن
  • الوظائف
  • المدونة
  • دراسات الحالة
  • عروض حية
  • تعلّمت اليوم
  • تواصل معنا

المزيد

  • القطاعات
  • شبكة الشركاء
© 2026 OOZOU. جميع الحقوق محفوظة.
سياسة الخصوصيةمدونة قواعد السلوكسياسة مكافحة الرشوة والفساد