![]() |
حقن التبعيات في Android: لماذا Hilt هو الحل الأمثل؟ |
كيف تجعل كود Android أكثر نظافة مع Hilt و ViewModel؟
في تطوير تطبيقات Android باستخدام Jetpack Compose، يعد استخدامك للـ ViewModel أداة مهمة لفصل واجهة المستخدم (UI) عن Logic الخاص بمشروعك. حيث في هذه المقالة، سنشرح لكم بإيجاز كيفية استخدام ViewModel وHilt معًا داخل مشروعك ، مع التركيز على كيفية قيام Hilt تلقائيًا بتوفير التعبئة التلقائيه إلى ViewModel، مما يجعل من السهل إدارة الحالة في التطبيقات الحديثة.
ما هو ViewModel؟
يعد ViewModel أحد مكونات مكتبة Android Jetpack المصممة لإدارة بيانات واجهة المستخدم والتي تساعد في فصل واجهة المستخدم (UI) عن اللوجيك الخاص بالمشروع الخاص بك. فهو يساعد في الحفاظ على البيانات أثناء تغييرات التكوين (مثل تدوير الجهاز) او الانتقال الى صفحات اخرى وهو مصمم ليكون نشطًا طالما أن واجهة المستخدم نفسها نشطة. وبشكل عام فإن ViewModel يمنع فقدان البيانات (Memory Leaks) ويحافظ على تناسق الحالة دون الحاجه الى إعادة تحميل البيانات في كل مرة.
ما هو Hilt ؟
Hilt هي مكتبة تعتمد على Dagger تستخدم لإدارة التبعيات. باستخدام مكتبه Hilt، والتي تمكنك من إعداد التبعيات وتكوينها تلقائيًا دون الحاجة إلى كتابة الكثير من الاكواد البرمجية. يُسهل Hilt توصيل ViewModel الخاص بك بكل التبعيات التي تحتاجها.
ما هو Dagger؟
Dagger هي مكتبة مفتوحة المصدر تُستخدم لتسهيل عملية حقن التبعيات في تطبيقات Android. حيث تركز Dagger على مبدأ إنشاء الكائنات وإدارتها تلقائيًا، مما يقلل من الحاجة إلى كتابة كود في كل مره
مميزات Dagger:
تقليل اعادة كتابه الاكواد : يقوم Dagger بإنشاء الكائنات وإدارتها تلقائيًا.
تحسين الأداء: يعتمد Dagger على معالجة الكود في وقت التجميع (Compile-time)، مما يجعله أسرع من بعض مكتبات حقن التبعيات الأخرى.
سهولة الاختبار: يسهل فصل التبعيات، مما يجعل الاختبار أسهل.
التكامل مع Android: يدعم دورة حياة Android مثل Activity وFragment.
كيف يعمل Dagger؟
Dagger يعتمد على ثلاثة مفاهيم رئيسية:
Module: هو الفصل الذي يحدد كيفية إنشاء الكائنات. يمكنك اعتباره "مصنعًا" للكائنات.
Component: هو الجسر الذي يربط بين Module والفصول التي تحتاج إلى التبعيات. يقوم Component بحقن التبعيات في الأماكن المطلوبة.
Inject: هو الواجهة التي تُستخدم لطلب التبعيات من Dagger.
كود لعمل counter باستخدام viewmodel بواسطة compose
@HiltViewModel
class CounterViewModel : ViewModel() {
private val _state = MutableStateFlow<Int>(0)
val state = _state.asStateFlow()
fun add() {
_state.update { it + 1 }
}
fun minus() {
_state.update {
if (it != 0) {
it - 1
} else {
it
}
}
}
}
تحتوي التعليمة البرمجية التالية على تطبيق مبدأ ViewModel الذي يدير حالة العداد البسيط. يتم استخدام Hilt لتوفير ViewModel وإدارته في Composable.
@HiltViewModel: هي annotation تُستخدم لتعريف أن هذا الـ ViewModel سيتم حقنه بواسطة Hilt.
CounterViewModel: هو الـ ViewModel الذي يحتوي على حالة عداد (_state) يتم تتبعها باستخدام MutableStateFlow.
add(): دالة لإضافة 1 إلى قيمة العداد.
minus(): دالة لإنقاص 1 من قيمة العداد إذا كانت القيمة أكبر من صفر.
استخدام ViewModel في Composable
@Composable
fun CounterController(viewModel: CounterViewModel = hiltViewModel()) {
val state by viewModel.state.collectAsState()
ShowDesign(
counter = state.toString(),
pluse = viewModel::add,
minuse = viewModel::minus
)
}
شرح الكود الخاص المسؤول عن controller
تصميم الواجهه لعرض التصميم
@Composable
private fun ShowDesign(
counter: String = "0",
pluse: () -> Unit,
minuse: () -> Unit
) {
Scaffold(
topBar = {
TopAppBar(
title = { Text("مرحبا") },
colors = TopAppBarDefaults.topAppBarColors(
containerColor = Color.Blue.copy(0.8f)
)
)
},
floatingActionButton = {
FloatingActionButton(onClick = {}) {}
}
) { paddingValues ->
ConstraintLayout(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues)
) {
val (text, button1, button2) = createRefs()
Column(
modifier = Modifier.constrainAs(text) {
top.linkTo(parent.top)
start.linkTo(parent.start)
end.linkTo(parent.end)
bottom.linkTo(parent.bottom)
},
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(text = counter)
OutlinedButton(onClick = pluse) {
Text("+")
}
OutlinedButton(onClick = minuse) {
Text("-")
}
}
}
}
}