Firebase Realtime Database | استخدام قاعدة بيانات فايربيز
ماهي Firebase ؟
Firebase هي خدمة قدمتها Google منذ فترة وقد كانت تقتصر فقط على تخزين البيانات وبعض الأشياء البسيطة,ولكن في Google I/O 16 تم الإعلان عن الكثير من المميزات الجديدة والرائعة وأصبحت حديث الكثير من المطورين
مميزاتها:
Authentication:وهي عملية تسجيل الدخول سواء عن طريق حساب Facebook,Google,Twitter,Email وفي نفس الوقت حماية البيانات الموجودة في Database (بمعنى أنه يمكنك منع أي شخص من استخدام التطبيق دون عملية تسجيل الدخول وهو الوضع الإفتراضي)
Realtime Database: وهي تفيد في تخزين البيانات على السيرفر وأكثر شيئ يميزها هي أنها Realtime بمعنى أنه أي تغيير يحصل على الداتابيز سيتغير فوراً في التطبيق كما سنرى في هذا الشرح)
Storage:تخزين الملفات والصور
Hosting:لإستضافة موقعك على Firebase
Notifications: إرسال إشعارات
والعديد من المميزات يمكنك تفقدها عند الدخول الى حسابك في Firebase,من الجدير بالذكر أن هذه الخدمات مجانية(ولكن ببعض الحدود,يمكنك رؤية ماهي الحدود عبر هذا الرابط) وهو مايميز Firebase
سنبدأ في هذا الدرس شرح عن Firebase Database وسنحاول مستقبلاً بإذن الله شرح باقي الأمور
بدايةً يجب أن يكون لديك حساب Google بالطبع بعد ذلك قم بالتوجه الى رابط Firebase Console
ثم نختار Add project
ثم نضع اسم المشروع الذي نريد ونضع الدولة
بعد ذلك سيتم إنشاء المشروع,نضغط على Add Firebase to Your Android App
بعد ذلك سيطلب منا اسم الpackage الخاص بتطبيق الأندرويد
نقوم بإنشاء تطبيق أندرويد جديد ثم نتوجه الى ملف build.gradle وننسخ applicationId
ونلصقه في Firebase ونضغط Register App
بعد ذلك نضغط على Download google-services.json وهو ملف إعدادات الذي يربط مشروعنا على Firebase بمشروعنا في Android Studio
سيتم تحميل هذا الملف قم بنسخه
ثم نتوجه الى Android Studio ونضغط بالزر الأيمن على مجلد app ونختار Show in Explorer
سيتم فتح مجلد المشروع في حاسوبك نقوم بلصق هذا الملف في مجلد app
الآن يجب علينا إضافة مكتبات Firebase الى مشروعنا في Android Studio
نتوجه الى ملف build.gradle(project) ونلصق هذا السطر
classpath 'com.google.gms:google-services:3.0.0'
ثم نذهب الى build.gradle(app) ونضع سطر plugin
apply plugin: 'com.google.gms.google-services'
الآن تم ربط مشروع Firebase ,وهذه الخطوات لربط أي مشروع Firebase بشكل عام سواءً كان Auth,Notifications,Storage الخ..
أما الآن سنقوم بإضافة مكتبة Firebase Realtime Database الى ملف build.gradle
compile 'com.google.firebase:firebase-database:10.2.1'
أخيراً نقوم بالضغط على Sync now ونشغل التطبيق لنتأكد من أن كل شيئ يعمل.
إذا واجهتك هذه المشكلة
تأكد من وضع سطر plugin في آخر ملف build.gradle.
الآن نتوجه الى Firebase Console الى Database ثم Rules ونقوم بتغييره الى
{
"rules": {
".read": true,
".write": true
}
}
ثم نضغط على Publish لحفظ التغييرات لكي نستطيع الكتابة والقراءة لأي شخص يستخدم التطبيق(في الوضع الإفتراضي فقط المستخدمين الذين قامو بتسجيل الدخول باستخدام Firebase Auth يستطيعون قراءة أو كتابة البيانات ويمكنك تحديد هذه الأمور في Rules)
وستجد هذه الرسالة وتفيد بأنه لا يفضل وضع هذه القواعد ويجب عليك فقط جعل المستخدمين الذين قاموا بتسجيل الدخول استخدام التطبيق
عموماً سنبدأ بالتوجه الى التطبيق ونبدأ بتخزين البيانات
السطر الأول لتعريف database
اما السطر الثاني هو لأخذ Reference ال root
سنضع قيمة child اسمها “Samsung” وقيمتها “S8”
نشغل التطبيق وسنجد أنه تم إضافة هذه البيانات الى Firebase
تعتمد الFirebase على مبدأ key و value
ملاحظة: عند استدعاء ref.child فإنه يتحقق إذا كان child موجود مسبقاً فسيقوم بإنشاءه وإلا فسيقوم فقط بوضع القيمة
ننتقل الآن الى كيفية عرض البيانات من Firebase وسنقوم بعرض كلمة S8 في TextView ونجرب تغييرها من Firebase Console لنرى سرعة التغيير في التطبيق
قمنا بوضع ref.child(“Samsung”) وقمنا باستدعاء الميثود addValueEventListener ومهمة هذه الميثود هي الإستماع على أية تغيرات تحصل على child Samsung وبالطبع ال childs الموجودة داخل child Samsung
وتقوم بعمل Override ل onDataChange وهي تنادى عند حدوث أي تغيير
و onCancelled تنادى عند حدوث أي خطأ
في onDataChange تقدم لنا الميثود DataSnapshot وهي البيانات الموجودة في Database ممكن ان تحتوي على String,int,long,double,boolean الخ..
قمنا بوضع setText ل textView بالقيمة الموجودة داخل Firebase ,وبما أنني أعرف نوع المتغير الذي وضعته في Firebase وهو ("S8”) فقمت بعمل cast له ك String.class
نشغل التطبيق وسنجد أنه قد قام بوضع كلمة S8 في ال TextView,وعند تغيير القيمة في Firebase Console سيتم تغييرها فوراً في التطبيق
نلاحظ بأنه اذا قمت بتغيير القيمة في Firebase Console الى 1 مثلا فسيعتبره متغير من نوع int ويقوم التطبيق بعمل كراش وذلك لأنه قد قمنا بعمل cast له ك String
هذه كانت مقدمة بسيطة عن كيفية حفظ وعرض البيانات
سنقوم الآن بعمل تطبيق بسيط يخزن أسماء بعض الطلاب مع معدلاتهم وعرضهم في RecyclerView
وكالعادة سنبدأ بإنشاء كلاس Model وسنسميه Student ونضع به الاسم String name و المعدل int average
الآن سنقوم بإدخال بعض الطلاب على Firebase
قمنا بإنشاء اوبجكت من Student ووضعنا الاسم Khalid و average85
ثم قمنا باستدعاء الchild الstudents وقمنا بعمل push وهذه الميثود تقوم بإنشاء key بشكل عشوائي (لكل student)
ثم وضعنا setValue لوضع القيمة وهي اوبجكت student الذي أنشأناه
سنقوم بإنشاء المزيد من الطلاب للتجربة
نأتي الآن الى عرض البيانات في RecyclerView نقوم بإنشاء RecyclerView Adapter
نعرف List<Student> و adapter ثم نستدعي ميثود addValueEventListener وداخل onDataChange نقوم بعمل for على DataSnapshot للحصول على جميع المعلومات
وأنشأنا Student وقيمته تساوي snapshot وقمنا بعمل cast ك Student.class لأننا نعلم أن نوع المتغيرات الموجودة في Firebase هي نفسها الموجودة في Student Class وهي int و String
ثم أضفنا هذا student الى studentList وأخيراً قمنا باستدعاء الميثود adapter.notifyDataSetChanged لتحديث البيانات في Adapter
أخيراً نقوم بتعريف RecyclerView و adapter (خارج valueEventListener)
نقوم بتشغيل التطبيق وستجد البيانات تم عرضها بهذا الشكل
نجرب تغيير قيمة أي عنصر (من Firebase Console) على سبيل المثال نغير معدل Muhammad الى 98
وستجد أنه قد تم تكرار هذه البيانات ?
وهذا لأن الميثود onDataChange يتم استدعاؤها عند كل حدث تغيير على قاعدة بيانات وبالتالي إعادة إضافة العناصر الList
ولحل هذه المشكلة نقوم فقط بتفريغ List في onDataChange
أما إذا أردنا عرض العناصر الحديثة من الأعلى (بمعنى أنه أي عنصر جديد يتم إضافته يظهر في الأعلى)
فقط نقوم بعكس ال List عبر الميثود
Collections.reverse(studentList);
وستظهر بهذا الشكل
Firebase Query عملية البحث داخل Firebase
نبدأ بإنشاء SearchView في MainActivity ومن ثم نقوم باستدعاء الميثود setOnQueryTextListener وداخل onQueryTextSubmit(هذه الميثود تستدعى عندما يتم الضغط على زر البحث في لوحة المفاتيح)
نقوم بتعريف Query
Query fireQuery = ref.child("students").orderByChild("name").equalTo(query);
ثم نبحث داخل الchild الstudents ونقوم بالترتيب على حسب child (orderByChild) في حالتنا هذه نود البحث عن الإسم فوضعنا name (يجب أن يكون نفس الإسم في Firebase)
عندما يكون يساوي الQuery الذي كتبه المستخدم في SearchView query (.equalTo)
بعد ذلك نقوم باستدعاء addListenerForSingleValueEvent هذه الميثود تشبه تماماً الميثود addValueEventListener ولكن الفرق أن هذه الميثود تستدعى مرة واحدة فقط بدلاً من الإستماع كل مرة.
داخل onDataChange قمنا بإنشاء List<Student> جديد
وقمنا بعمل for على snapshot وتنفيذ نفس الخطوات التي شرحناها سابقاً
ثم عرفنا نفس adapter ولكن أعطيناه searchList الجديدة التي أنشأناها
وأخيراً قمنا بعمل setAdapter
نشغل التطبيق ونضع اسم Ahmad ونضغط على زر البحث لنرى النتيجة
وللتأكد من وجود الاسم Ahmad ام لا في Firebase نقوم بالتحقق اذا كانت قيمة dataSnapshot.getValue == null عندها قم بإظهار رسالة Toast وإلا قم بوضع العناصر داخل list وأظهرها
نجرب وضع كلمة ما مثلا test وسنجد أنه تم إظهار رسالة Toast ERROR
وللخروج من وضع البحث نقوم باستدعاء الميثود setOnCloseListener وداخل onClose
نقوم بتعريف نفس Adapter وإعطاءه studentList التي يوجد داخلها كافة البيانات ثم setAdapter
تعديل البيانات على Firebase
الآن نذهب الى RecyclerView Row ونضيف 2Buttons واحد للتعديل والآخر للحذف
ثم نذهب الى StudentAdapter وعند الضغط على زر editStudent سنقوم بإنشاء Intent الى أكتفتيEditStudentActivity.class الذي سنقوم بإنشاءه بعد قليل
وأرسلنا name (اسم الطالب الذي تم الضغط عليه) عبر الintent وأخيراً شغلنا الأكتفتي
الآن نقوم بإنشاء EditStudentActivity.class ونضع به 2EditText واحد لتعديل الإسم والآخر للمعدل ونضع 1Button لحفظ القيم الى Firebase
بالطبع نقوم بتعريف String name القادم عبر intent ونعيد تعريف FirebaseDatabase و Reference و EditTexts
بعدها نقوم بتنفيذ Query على name القادم عبر intent ,وداخل onDataChange نقوم بعمل for كما فعلنا سابقاً وأخيراً قمنا بعمل setText ل EditText
(تم استخدام String.ValueOf لأن getAverage تعيد int ويجب تحويلها ل String لوضعها في EditText)
وبهذا نكون قد وضعنا اسم الطالب ومعدله فيEditTexts
ولحفظ القيم بعد تعديلها ,عند الضغط على زر Save نقوم بإنشاء Student جديد ونضع الإسم name قيمة editText الأول ,ووضعنا المعدل average قيمة EditText الثاني وقمنا بتحويله الى Integer
ثم نفذنا Query جديدة وقمنا بعمل for على dataSnapshot
ثم snapshot.getRef() هذه الميثود تعيد لنا key الموجود في الداتابيز (على سبيل المثال -Kgzq-ktAGSpAjJRqk2i) وجميع childs الموجودة داخله
ثم استدعينا setValue وقمنا بإعطاءه student الذي أنشأناه,وبهذا يكون قد تم التعديل
عملية الحذف من Firebase
نطبق نفس الخطوات التي طبقناها في عملية التعديل ولكن هذه المرة بدل من setValue نقوم بعملremoveValue() للحذف
ملاحظة:المشروع على Github للمعاينة فقط ولايمكنك تجربته على Android Studio لعدم وجود google-services.json الخاص بك
التعليقات (6)
معلومات قيمة ومجهود أكثر من رائع شكراً لك
وياليت لو تتكلم أيضاً عن Analytics في ال firebase وكيفية الاستفادة منها
في 20/11/2017 at 03:18, ساره علي said:معلومات قيمة ومجهود أكثر من رائع شكراً لك
وياليت لو تتكلم أيضاً عن Analytics في ال firebase وكيفية الاستفادة منها
شكراً لدعمك, سأحاول مستقبلاً ان شاء الله
مقال جداً مفيد ورائع وياليت لو تعلمنا كيف نضيف اساسيات برامج التواصل مثل لايك وكومنت وعدد المشاهدة 🌹
السلام عليكم
كيف استطيع ان اعرض صورة واحدة في recyclerview من عدة صور محملة في storage
جزاكم الله خيرا
أخيراً مقال عربي بنفس كفائة المواقع الأجنبية , أحييك جددا على هذا الشرح
لايوجد لديك حساب في عالم البرمجة؟
تحب تنضم لعالم البرمجة؟ وتنشئ عالمك الخاص، تنشر المقالات، الدورات، تشارك المبرمجين وتساعد الآخرين، اشترك الآن بخطوات يسيرة !