Rami Shalah

Members
  • عدد منشوراتي

    7
  • تاريخ الإنضمام

  • تاريخ اخر زياره

السمعه بالموقع

3 Neutral

عن العضو Rami Shalah

  • الرتبه
    مبدع جديد
  • تاريخ الميلاد 01/01/97

معلومات عامة

  • الجنس
    ذكر
  • السكن
    KFUPM
  1. السلام عليكم و رحمة الله و بركاته. ما هو الـException ؟ ببساطه Exception هو حدث معين يعمل على تغيير المجرى الطبيعي للبرنامج اذا حدث خطأ بحيث يتم التعامل معه بطريقة معينة. ماذا يحدث عند ظهور Exception ؟ يتم حفظ الحالة الحالية للكود. يتم تحويل مجرى البرنامج الى function معينة تتعامل مع هذا الـException. و أخير، على حسب تصميم البرنامج يتم استكمال البرنامج من نقطة الحفظ أو ايقاف عمل البرنامج أو تحويل مجرى البرنامج الى مكان آخر في الكود. ملاحظة: يجب استخدام الـException فقط عند ظهور الخطأ ولا يجب استخدامه فقط للانتقال الى مكان آخر في الكود. في هذا الدرس سوف: نشرح الاستخدام الأساسي للـExceptions. كيفية بناء Exception خاص(Custom Exception). الإستخدام الأساسي: يتم استخدام (throw) لالقاء Exception بحيث يتم انشاء اوبجت من الكلاس Exception و تمرير اليه الرسالة المراد اظهارها كما موضح الكود بالأسفل. <?php //انشاء fucntion و القاء بداخلها Exception function checkNum($number) { if($number>1) { throw new Exception("Value must be 1 or below"); } return true; } //هذا الاستدعاء سوف يظهر الـExcpetion checkNum(2); ?> و اذا أجرينا excute لهذا الكود سوف يظهر لنا التالي: Fatal error: Uncaught exception 'Exception' with message 'Value must be 1 or below' in C:\webfolder\test.php:6 Stack trace: #0 C:\webfolder\test.php(12): checkNum(28) #1 {main} thrown in C:\webfolder\test.php on line 6 كما نلاحظ عند استدعاء الـFunction تم اظهار الـException و اظهار الرسالة معه، و لكن يجب علينا التعامل مع هذا الـException. Try and Catch: حتى نتعامل مع الـException الظاهر في المثال السابق يجب علينا استخدام try and catch كما موضح أدناه. <?php //انشاء function و القاء Exception function checkNum($number) { if($number>1) { throw new Exception("Value must be 1 or below"); } return true; } //الـException سوف يظهر في الـtry try { checkNum(2); //اذا تم اظهار الـException الكود بالأسفل لن يتم عمله. echo 'If you see this, the number is 1 or below'; } //الامساك بالـException و عمل شيء معين به. catch(Exception $e) { echo 'Message: ' .$e->getMessage(); } ?> و اذا أجرينا excute لهذا الكود سوف يظهر لنا التالي: Message: Value must be 1 or below شرح المثال السابق: تم انشاء checkNum() و التي تعمل على التحقق من أن الرقم أكبر من 1، فاذا كان كذلك يتم القاء الـException. الـfunction و التي تسمى checkNum() يتم استدعاؤها في داخل الـtry block حتى يتم التعامل مع احتمالية ظهور الException من الـfunction المستدعاة الـcatch block تستقبل الـexception و تتعامل معه بحيث يتم طبع الرسالة عن طريق استخدام الـgetMessage(). كيفية انشاء Exception خاص: حتى يتم انشاء Exception خاص ( Custom Exception handler) يجب علينا انشاء كلاس و يقوم هذا الكلاس بـextends للكلاس Exception كما هو موضح أدناه. <?php class InvalidCCNumberException extends Exception { public function __construct($message = 'No CC Number', $code = 0, $previous = null) { parent::__construct($message, $code, $previous); } } function processCC($num = null) { if (is_null($num)) { throw new InvalidCCNumberException(); } //سوف يتم استدعاء الاكود بالاسفل اذا لم يحصل الـException echo 'processed'; } try{ processCC(); } catch (InvalidCCNumberException $e) { echo "<pre>"; echo $e->getMessage(); echo "<br>"; echo get_class($e); } finally { echo "\nfinal!"; } ?> قمنا بعمل التالي: انشاء كلاس و سميناه على سبيل المثال InvalidCCNumberException بحيث يقوم بـextends الكلاس Exception فيتم inherit جميع الميثودز و المتغيرات. قمنا بعمل override للميثود __construct() و التي تقوم بتمرير الرسالة المعطاة للأوبجكت من كلاس Exception. انشاء function وتسميتها processCC و التي بدورها تقوم بـthrow الـException اذا كان الـparameter فارغ (null). قمنا باستدعاء الـfunction داخل الـtry block حتى نتعامل مع الـException اذا ظهر. في الـcatch block طبعنا الرسالة و الكلاس الخاص بأوجكت الـException. و بالنهاية أضفنا الـfinally block و التي سوف يتم تنفيذ الكود بداخلها سواء ظهر الـException او لم يظهر. و اذا أجرينا excute لهذا الكود سوف يظهر لنا التالي: No CC Number InvalidCCNumberException final! في النهاية، هناك بعض كلاسات الـException المعرفة سابقا و المتواجدة في مكتبات اللغة الخاصة بالـPHP و منها الموضح أدناه في الصورة. بحيث يتم استخدامها لتسهيل عملية الـdebugging. و هنا وصلنا الى نهاية هذا الدرس.😄 أتمنى أني قد وفقت بايصال المعلومة.
  2. السلام عليكم و رحمة الله و بركاته. ما هو الـException ؟ ببساطه Exception هو حدث معين يعمل على تغيير المجرى الطبيعي للبرنامج اذا حدث خطأ بحيث يتم التعامل معه بطريقة معينة. ماذا يحدث عند ظهور Exception ؟ يتم حفظ الحالة الحالية للكود. يتم تحويل مجرى البرنامج الى function معينة تتعامل مع هذا الـException. و أخير، على حسب تصميم البرنامج يتم استكمال البرنامج من نقطة الحفظ أو ايقاف عمل البرنامج أو تحويل مجرى البرنامج الى مكان آخر في الكود. ملاحظة: يجب استخدام الـException فقط عند ظهور الخطأ ولا يجب استخدامه فقط للانتقال الى مكان آخر في الكود. في هذا الدرس سوف: نشرح الاستخدام الأساسي للـExceptions. كيفية بناء Exception خاص(Custom Exception). الإستخدام الأساسي: يتم استخدام (throw) لالقاء Exception بحيث يتم انشاء اوبجت من الكلاس Exception و تمرير اليه الرسالة المراد اظهارها كما موضح الكود بالأسفل. <?php //انشاء fucntion و القاء بداخلها Exception function checkNum($number) { if($number>1) { throw new Exception("Value must be 1 or below"); } return true; } //هذا الاستدعاء سوف يظهر الـExcpetion checkNum(2); ?> و اذا أجرينا excute لهذا الكود سوف يظهر لنا التالي: Fatal error: Uncaught exception 'Exception' with message 'Value must be 1 or below' in C:\webfolder\test.php:6 Stack trace: #0 C:\webfolder\test.php(12): checkNum(28) #1 {main} thrown in C:\webfolder\test.php on line 6 كما نلاحظ عند استدعاء الـFunction تم اظهار الـException و اظهار الرسالة معه، و لكن يجب علينا التعامل مع هذا الـException. Try and Catch: حتى نتعامل مع الـException الظاهر في المثال السابق يجب علينا استخدام try and catch كما موضح أدناه. <?php //انشاء function و القاء Exception function checkNum($number) { if($number>1) { throw new Exception("Value must be 1 or below"); } return true; } //الـException سوف يظهر في الـtry try { checkNum(2); //اذا تم اظهار الـException الكود بالأسفل لن يتم عمله. echo 'If you see this, the number is 1 or below'; } //الامساك بالـException و عمل شيء معين به. catch(Exception $e) { echo 'Message: ' .$e->getMessage(); } ?> و اذا أجرينا excute لهذا الكود سوف يظهر لنا التالي: Message: Value must be 1 or below شرح المثال السابق: تم انشاء checkNum() و التي تعمل على التحقق من أن الرقم أكبر من 1، فاذا كان كذلك يتم القاء الـException. الـfunction و التي تسمى checkNum() يتم استدعاؤها في داخل الـtry block حتى يتم التعامل مع احتمالية ظهور الException من الـfunction المستدعاة الـcatch block تستقبل الـexception و تتعامل معه بحيث يتم طبع الرسالة عن طريق استخدام الـgetMessage(). كيفية انشاء Exception خاص: حتى يتم انشاء Exception خاص ( Custom Exception handler) يجب علينا انشاء كلاس و يقوم هذا الكلاس بـextends للكلاس Exception كما هو موضح أدناه. <?php class InvalidCCNumberException extends Exception { public function __construct($message = 'No CC Number', $code = 0, $previous = null) { parent::__construct($message, $code, $previous); } } function processCC($num = null) { if (is_null($num)) { throw new InvalidCCNumberException(); } //سوف يتم استدعاء الاكود بالاسفل اذا لم يحصل الـException echo 'processed'; } try{ processCC(); } catch (InvalidCCNumberException $e) { echo "<pre>"; echo $e->getMessage(); echo "<br>"; echo get_class($e); } finally { echo "\nfinal!"; } ?> قمنا بعمل التالي: انشاء كلاس و سميناه على سبيل المثال InvalidCCNumberException بحيث يقوم بـextends الكلاس Exception فيتم inherit جميع الميثودز و المتغيرات. قمنا بعمل override للميثود __construct() و التي تقوم بتمرير الرسالة المعطاة للأوبجكت من كلاس Exception. انشاء function وتسميتها processCC و التي بدورها تقوم بـthrow الـException اذا كان الـparameter فارغ (null). قمنا باستدعاء الـfunction داخل الـtry block حتى نتعامل مع الـException اذا ظهر. في الـcatch block طبعنا الرسالة و الكلاس الخاص بأوجكت الـException. و بالنهاية أضفنا الـfinally block و التي سوف يتم تنفيذ الكود بداخلها سواء ظهر الـException او لم يظهر. و اذا أجرينا excute لهذا الكود سوف يظهر لنا التالي: No CC Number InvalidCCNumberException final! في النهاية، هناك بعض كلاسات الـException المعرفة سابقا و المتواجدة في مكتبات اللغة الخاصة بالـPHP و منها الموضح أدناه في الصورة. بحيث يتم استخدامها لتسهيل عملية الـdebugging. و هنا وصلنا الى نهاية هذا الدرس.😄 أتمنى أني قد وفقت بايصال المعلومة.
  3. السلام عليكم و رحمة الله و بركاته. في هذه المقالة سنتعلم كيفية قراءة و استخراج بيانات الـJSON في الـAndroid Studio. ملاحظة: يفضل أن تكون قد قرأت مقالتي السابقة عن كيفية تحميل بيانات الـJSON في Android Studio من هنا. قبل أن نبدأ باستخراج البيانات أود أن نلقي نظرة على ماهية الـJSON المتعلق ب Flicker Api. باستخدام موقع jsonlint حيث يمكننا أن نرى التكوين الداخلي للـJSON بالاضافة الى التأكد من أن الملف هوة عبارة عن JSON. رابط ملف الـJSON هو: https://api.flickr.com/services/feeds/photos_public.gne?format=json&nojsoncallback=1 كما نلاحظ أعلاه، الأشياء المحاطة بـ{} هي عبارة عن object و الأشياء المحاطة بـ[] هي عبارة عن array، لذلك نستنتج بأن الـJSON هو عبارة عن objects و arrays. في هذا الدرس سوف نقوم باستخراج الـtitle و الـtags من الـarray التي تدعى items. و الآن ننتقل الى التطبيق في الـ Android Studio... في البداية يجب علينا عمل التالي: ننشئ كلاس ونسميه photo و الذي يحتوي على متغيرات: title, tags و الذي بدوره سوف يخزن البيانات المطلوبة من الـJSON. إضافة getters and setters لهذه المتغيرات. package org.example.rami.flickerbrowser; import java.io.Serializable; /** * Created by Rami on 5/2/2017. */ class Photo implements Serializable{ private static final long serialVersionUID = 1L; private String mTitle; private String mTags; public Photo(String title, String tags) { mTitle = title; mTags = tags; } String getTitle() { return mTitle; } String getTags() { return mTags; } @Override public String toString() { return "Photo{" + "mTitle='" + mTitle + '\'' + ", mTags='" + mTags + '\'' + '}'; } } ثم ننشئ كلاس آخر و نسميه على سبيل المثال GetFlickerJsonData و الذي بدوره سوف يحتوي على الميثود onDownloadComplete التي تقوم بقراءة و استخراج المعلومات المطلوبة من الـJSON بالاضافة الى تخزينها في الاوبجكت من نوع Photo. ملاحظة: الميثود onDownloadComplete يتم استدعاؤها من الكلاس GetRawData الموجود في الدرس السابق الذي قام بتحميل ملف الـJSON و تمرير بياناته على شكل String للميثود. package org.example.rami.flickerbrowser; import android.util.Log; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.util.ArrayList; import java.util.List; /** * Created by Rami on 5/3/2017. */ class GetFlickerJsonData implements GetRawData.OnDownloadComplete { private static final String TAG = "GetFlickerJsonData"; private List<Photo> mPhotoList = null; public GetFlickerJsonData() { Log.d(TAG, "GetFlickerJsonData called"); //here you do somthing additional } @Override public void onDownloadComplete(String data) { mPhotoList = new ArrayList<>(); try { JSONObject jsonData = new JSONObject(data); JSONArray itemsArray = jsonData.getJSONArray("items"); for(int i = 0; i < itemsArray.length(); i++){ JSONObject jsonPhoto = itemsArray.getJSONObject(i); String title = jsonPhoto.getString("title"); String tags = jsonPhoto.getString("tags"); Photo photoObject = new Photo(title, tags); mPhotoList.add(photoObject); Log.d(TAG, "onDownloadComplete: " + photoObject.toString()); } }catch (JSONException jsone){ jsone.printStackTrace(); Log.e(TAG, "onDownloadComplete: Error processing json data " + jsone.getMessage()); } } Log.d(TAG, "onDownloadComplete ends"); } لقد قمنا بعمل التالي: احاطة الكود بالكامل بtry و catch لمعالجة ظهور أي خطأ في ملف الـJSON. اضافة متغير mPhotoList من نوع List و الذي سوف يتم تخزين فيه الـphotos و التي تحتوي على بيانات الـJSON المستخرجة. اضافة Constructor لانشاء object من هذا الكلاس بحيث يتم اضافة أي شيء فيه على حسب تصميمك للبرنامج الكامل و طريقة عمله. اضافة الـmethod و هي onDownloadComplete و التي بدورها سوف تستخرج المعلومات المطلوبة من الـJSON المحمل كما هو موضح أعلاه. و هذه الـmethod تحتوي على: المتغير jsonData من نوع ـJSONObject و الذي يحتوي على كامل ملف الـJSON. المتغير itemsArray من نوع JSONArray والذي يحتوي على الـarray و التي تدعى items. و الآن نقوم باضافة loop و التي بدورها تقوم بالتالي: استخراج الـtitle و تخزينه بالمتغير title من نوع String. استخراج الـtags و تخزينه بالمتغير tags من نوع String. في النهاية نقوم بانشاء اوبجكت من نوع Photo و اضافته الى الـmPhotoList و التي تحتوي على جميع الـobjects من نوع Photo. لمزيد من المعلومات عن org.json package و الكلاسات الموجودة فيه: https://developer.android.com/reference/org/json/package-summary.html و هنا وصلنا الى نهاية هذا الدرس.😄 أتمنى أني قد وفقت بايصال المعلومة.
  4. السلام عليكم و رحمة الله و بركاته. في هذه المقالة سنتعلم كيفية قراءة و استخراج بيانات الـJSON في الـAndroid Studio. ملاحظة: يفضل أن تكون قد قرأت مقالتي السابقة عن كيفية تحميل بيانات الـJSON في Android Studio من هنا. قبل أن نبدأ باستخراج البيانات أود أن نلقي نظرة على ماهية الـJSON المتعلق ب Flicker Api. باستخدام موقع jsonlint حيث يمكننا أن نرى التكوين الداخلي للـJSON بالاضافة الى التأكد من أن الملف هوة عبارة عن JSON. رابط ملف الـJSON هو: https://api.flickr.com/services/feeds/photos_public.gne?format=json&nojsoncallback=1 كما نلاحظ أعلاه، الأشياء المحاطة بـ{} هي عبارة عن object و الأشياء المحاطة بـ[] هي عبارة عن array، لذلك نستنتج بأن الـJSON هو عبارة عن objects و arrays. في هذا الدرس سوف نقوم باستخراج الـtitle و الـtags من الـarray التي تدعى items. و الآن ننتقل الى التطبيق في الـ Android Studio... في البداية يجب علينا عمل التالي: ننشئ كلاس ونسميه photo و الذي يحتوي على متغيرات: title, tags و الذي بدوره سوف يخزن البيانات المطلوبة من الـJSON. إضافة getters and setters لهذه المتغيرات. package org.example.rami.flickerbrowser; import java.io.Serializable; /** * Created by Rami on 5/2/2017. */ class Photo implements Serializable{ private static final long serialVersionUID = 1L; private String mTitle; private String mTags; public Photo(String title, String tags) { mTitle = title; mTags = tags; } String getTitle() { return mTitle; } String getTags() { return mTags; } @Override public String toString() { return "Photo{" + "mTitle='" + mTitle + '\'' + ", mTags='" + mTags + '\'' + '}'; } } ثم ننشئ كلاس آخر و نسميه على سبيل المثال GetFlickerJsonData و الذي بدوره سوف يحتوي على الميثود onDownloadComplete التي تقوم بقراءة و استخراج المعلومات المطلوبة من الـJSON بالاضافة الى تخزينها في الاوبجكت من نوع Photo. ملاحظة: الميثود onDownloadComplete يتم استدعاؤها من الكلاس GetRawData الموجود في الدرس السابق الذي قام بتحميل ملف الـJSON و تمرير بياناته على شكل String للميثود. package org.example.rami.flickerbrowser; import android.util.Log; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.util.ArrayList; import java.util.List; /** * Created by Rami on 5/3/2017. */ class GetFlickerJsonData implements GetRawData.OnDownloadComplete { private static final String TAG = "GetFlickerJsonData"; private List<Photo> mPhotoList = null; public GetFlickerJsonData() { Log.d(TAG, "GetFlickerJsonData called"); //here you do somthing additional } @Override public void onDownloadComplete(String data) { mPhotoList = new ArrayList<>(); try { JSONObject jsonData = new JSONObject(data); JSONArray itemsArray = jsonData.getJSONArray("items"); for(int i = 0; i < itemsArray.length(); i++){ JSONObject jsonPhoto = itemsArray.getJSONObject(i); String title = jsonPhoto.getString("title"); String tags = jsonPhoto.getString("tags"); Photo photoObject = new Photo(title, tags); mPhotoList.add(photoObject); Log.d(TAG, "onDownloadComplete: " + photoObject.toString()); } }catch (JSONException jsone){ jsone.printStackTrace(); Log.e(TAG, "onDownloadComplete: Error processing json data " + jsone.getMessage()); } } Log.d(TAG, "onDownloadComplete ends"); } لقد قمنا بعمل التالي: احاطة الكود بالكامل بtry و catch لمعالجة ظهور أي خطأ في ملف الـJSON. اضافة متغير mPhotoList من نوع List و الذي سوف يتم تخزين فيه الـphotos و التي تحتوي على بيانات الـJSON المستخرجة. اضافة Constructor لانشاء object من هذا الكلاس بحيث يتم اضافة أي شيء فيه على حسب تصميمك للبرنامج الكامل و طريقة عمله. اضافة الـmethod و هي onDownloadComplete و التي بدورها سوف تستخرج المعلومات المطلوبة من الـJSON المحمل كما هو موضح أعلاه. و هذه الـmethod تحتوي على: المتغير jsonData من نوع ـJSONObject و الذي يحتوي على كامل ملف الـJSON. المتغير itemsArray من نوع JSONArray والذي يحتوي على الـarray و التي تدعى items. و الآن نقوم باضافة loop و التي بدورها تقوم بالتالي: استخراج الـtitle و تخزينه بالمتغير title من نوع String. استخراج الـtags و تخزينه بالمتغير tags من نوع String. في النهاية نقوم بانشاء اوبجكت من نوع Photo و اضافته الى الـmPhotoList و التي تحتوي على جميع الـobjects من نوع Photo. لمزيد من المعلومات عن org.json package و الكلاسات الموجودة فيه: https://developer.android.com/reference/org/json/package-summary.html و هنا وصلنا الى نهاية هذا الدرس.😄 أتمنى أني قد وفقت بايصال المعلومة. تم ترقية هذا الطرح المميز الى صفحة المقالات
  5. السلام عليكم و رحمة الله و بركاته. في هذه المقالة سنتعلم كيفية تحميل الـJSON في الـAndroid Studio. في البداية، ما هو الـJSON ؟ JSON هو عبارة عن كائن JavaScript حيث يتم تمثيل البيانات و المصفوفات من خلالها. عندما تتخاطب المنصات أو البرمجيات أو الأنظمة مع بعضها البعض فهي تتبادل البيانات بهذا الشكل. تخيل لو كنت تود ارسال قائمة ببيانات الموظفين المحالين للتقاعد إلى جهة أخرى فحينها سترسلها مرتبة ومصاغة بهذا الشكل. و الآن ننتقل الى التطبيق في الـ Android Studio... في البداية نقوم بفتح Android Studio ثم نقوم بالضغط على Start a new Android Studio project و نبقي الخيارات الافتراضية على حالها و نقوم بتسميته و حفظه. و الآن حتى يتم تحميل الــJSON يجب علينا: انشاء thread منفصل و لحسن الحظ يتوفر على الـ Android Studio كلاس يسمى بالـ AsyncTask يقوم بأغلب المهام. نقوم بانشاء class و نسميه على سبيل المثال GetRawData و الذي بدوره يقوم بـ AsyncTask class" extends"، ثم نضيف الmethods وهي onPostExecute ،doInBackground كما هو موضح ادناه: /** * Created by Rami on 4/20/2017. */ public class GetRawData extends AsyncTask<String, Void, String> { private static final String TAG = "GetRawData"; @Override protected void onPostExecute(String s) { super.onPostExecute(s); } @Override protected String doInBackground(String... params) { return null; } } ملاحظة: الكلاس AsyncTask يحتوي على عدة functions مهمة يجب عمل implements لهما و منها: onPreExcute, doInBackground, onPostExcute. onPreExcute: يتم استدعاؤها في الـUI thread قبل استدعاء الميثود doInBackground بحيث يتم من خلالها عمل مهمة معينة مثل اظهار الـprogress bar في الـinterface. doInBackground: يتم اسدعاؤها في thread منفصل (background thread) بحيث يتم من خلالها تحميل جميع بيانات الـJSON و بالنهاية يتم عمل pass للبيانات المحملة للميثود onPostExcute. onPostExcute: يتم اسدعاؤها تلقائيا في UI thread بعد الانتهاء من تحميل البيانات بحيث يتم من خلالها اشعار الـcaller بانتهاء التحميل. و لكن للتبسيط سوف نستخدم في هذا الدرس الميثود doInBackground و الميثود onPostExcute. الآن نقوم بانشاء interface في داخل GetRawData كلاس ونسميها على سبيل المثال OnDownloadComplete و التي بدورها سوف تحتوي على ميثود الـonDownloadComplete و التي تقوم بإشعار الكلاس المستعدي (caller) بانتهاء تحميل البيانات. /** * Created by Rami on 4/20/2017. */ public class GetRawData extends AsyncTask<String, Void, String> { private static final String TAG = "GetRawData"; private final OnDownloadComplete mCallback; interface OnDownloadComplete{ void onDownloadComplete(String data); } public GetRawData(OnDownloadComplete callback) { this.mCallback = callback; } private static final String TAG = "DownloadData"; @Override protected void onPostExecute(String s) { super.onPostExecute(s); } @Override protected String doInBackground(String... params) { return null; } } كما هو موضح أعلاه الـ GetRawData تتلقى parameter و الذي هو عبارة عن اوبجكت يسمى بالـcallback و الذي يعتبر كـreference للكلاس المستدعي(caller) حيث أن الكلاس المستعدي يعمل على implements الـinterface والمسمى OnDownloadComplete. ملاحظة: بهذه الطريقة يتم فصل كلاس GetRawData عن بقية الكلاسات و الذي بدوره يعزز الـreusability و يتم اشعار الكلاس المستعدي عند انتهاء تحميل البيانات دون ايقاف أي عملية أخرى. الآن نقوم بإضافة الكود في داخل الـميثود doInBackground و التي بدورها سوف تكون المسؤولة عن تحميل بيانات الـJSON. @Override protected String doInBackground(String... params) { HttpURLConnection connection = null; BufferedReader reader = null; if(params == null){ return null; } try{ URL url = new URL(params[0]); connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.connect(); int response = connection.getResponseCode(); Log.d(TAG, "doInBackground: The response code is: " + response); StringBuilder result = new StringBuilder(); reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); String line; while(null != (line = reader.readLine())){ result.append(line).append('\n'); } return result.toString(); }catch (MalformedInputException e){ Log.e(TAG, "doInBackground: Invalid URL" + e.getMessage()); }catch (IOException e){ Log.e(TAG, "doInBackground: IO Exception reading data" + e.getMessage()); }catch (SecurityException e){ Log.e(TAG, "doInBackground: Error connetino to internet. neeed permision" + e.getMessage()); }finally { if(connection != null){ connection.disconnect(); } if(reader != null){ try{ reader.close(); }catch (IOException e){ Log.e(TAG, "doInBackground: Error closing the reader" + e.getMessage()); } } } return null; } و لقد قمنا بعمل التالي: doInBackground تتلقى الـ URL الذي يوجد فيه ملف الـJson و المتمثل في الـparameter المسمى params. نسند قيمة مبدئية null للمتغيرين reader, connection. نتحقق من الـparameter المسمى params على احتوائه على ملف JSON من عدمه. انشاء الإتصال بالإنترنت. انشاء StringBuilder object حتى يتم الحاق كامل ملف JSON بهذا object. قراءة كامل ملف JSON عن طريق BufferReader و يمكن أن تتساءل ما الفائدة من المتغير response؟ عن طريقه يمكن معرفة نجاح الاتصال بالانترنت او فشله. حيث انه اذا ظهر لك المتغير response بقيمة 200 هذا يعني نجاح الاتصال، غير ذلك يعني فشله. قراءة الملف سطر بعد سطر عن طريق المتغير line و الحاقها بالـتغير result حيث أن الـloop سوف تنتهى عند انتهاء ملفJSON. أحطنا الـ code بـ try and catch حتى نتعامل مع الأخطاء المحتملة منها: فقدان الاتصال بالانترنت، او خطأ في عنوان الرابط.. الخ. إذا حصل خطأ نقوم بـreturn null. نقوم بإضافة الكود في داخل الميثود onPostExecute و التي بدورها سوف تستعدي الميثود onDownloadComplete المتواجدة في كلاس المستعدي(caller) لإشعاره بانتهاء تحميل البيانات مع تمرير الـstring الخاص بالـJSON. @Override protected void onPostExecute(String s) { Log.d(TAG, "onPostExecute: The parameter is: " + s); if(mCallback != null){ mCallback.onDownloadComplete(s); } Log.d(TAG, "onPostExecute: Ends"); } وبالنهاية نقوم بانشاء الكلاس caller وليكن على سبيل المثال الـMainActivity. public class MainActivity extends AppCompatActivity implements GetRawData.OnDownloadComplete{ private static final String TAG = "MainActivity"; @Override protected void onCreate(Bundle savedInstanceState) { Log.d(TAG, "onCreate: starts"); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); GetRawData getRawData = new GetRawData(this); getRawData.excute("https://api.flickr.com/services/feeds/photos_public.gne"); Log.d(TAG, "onCreate: ends"); } @Override public void onDownloadComplete(String data) { Log.d(TAG, "onDownloadComplete: starts"); //Do something here. Log.d(TAG, "onDownloadComplete ends"); } } كما موضح أعلاه: انشاء الكلاس MainActivity و قمنا بعمل implements للـinterface المسمى OnDownloadComplete. انشاء اوبجكت من النوع GetRawData. استدعاء الميثود excute و تمرير الرابط الذي يحتوي على بيانات الـJSON و التي بدورها سوف تقوم بانشاء الـthread المنفصل. قمنا بـimplements للميثود onDownloadComplete بحيث سوف يتم استدعاؤها تلقائيا عند انتهاء الكلاس GetRawData من تحميل البيانات و هذا هو المقصود من اشعار الـCaller. لا ننسى الخطوة المهمة و التي لا يكتمل التطبيق إلا بها و هي أخذ الإذن للإتصال بالإنترنت. حيث تتم هذه العملية بإضافة السطر البرمجي الموضح أدناه في ملف AndroidManifest.xml المتواجد في مجلد Manifests. <uses-permission android:name="android.permission.INTERNET"/> و هنا وصلنا الى نهاية هذا الدرس.🙂 في الدروس القادمة سوف أتناول كيفية معالجة و قراءة الـJSON المحملة.
  6. السلام عليكم و رحمة الله و بركاته. في هذه المقالة سنتعلم كيفية تحميل الـJSON في الـAndroid Studio. في البداية، ما هو الـJSON ؟ JSON هو عبارة عن كائن JavaScript حيث يتم تمثيل البيانات و المصفوفات من خلالها. عندما تتخاطب المنصات أو البرمجيات أو الأنظمة مع بعضها البعض فهي تتبادل البيانات بهذا الشكل. تخيل لو كنت تود ارسال قائمة ببيانات الموظفين المحالين للتقاعد إلى جهة أخرى فحينها سترسلها مرتبة ومصاغة بهذا الشكل. و الآن ننتقل الى التطبيق في الـ Android Studio... في البداية نقوم بفتح Android Studio ثم نقوم بالضغط على Start a new Android Studio project و نبقي الخيارات الافتراضية على حالها و نقوم بتسميته و حفظه. و الآن حتى يتم تحميل الــJSON يجب علينا: انشاء thread منفصل و لحسن الحظ يتوفر على الـ Android Studio كلاس يسمى بالـ AsyncTask يقوم بأغلب المهام. نقوم بانشاء class و نسميه على سبيل المثال GetRawData و الذي بدوره يقوم بـ AsyncTask class" extends"، ثم نضيف الmethods وهي onPostExecute ،doInBackground كما هو موضح ادناه: /** * Created by Rami on 4/20/2017. */ public class GetRawData extends AsyncTask<String, Void, String> { private static final String TAG = "GetRawData"; @Override protected void onPostExecute(String s) { super.onPostExecute(s); } @Override protected String doInBackground(String... params) { return null; } } ملاحظة: الكلاس AsyncTask يحتوي على عدة functions مهمة يجب عمل implements لهما و منها: onPreExcute, doInBackground, onPostExcute. onPreExcute: يتم استدعاؤها في الـUI thread قبل استدعاء الميثود doInBackground بحيث يتم من خلالها عمل مهمة معينة مثل اظهار الـprogress bar في الـinterface. doInBackground: يتم اسدعاؤها في thread منفصل (background thread) بحيث يتم من خلالها تحميل جميع بيانات الـJSON و بالنهاية يتم عمل pass للبيانات المحملة للميثود onPostExcute. onPostExcute: يتم اسدعاؤها تلقائيا في UI thread بعد الانتهاء من تحميل البيانات بحيث يتم من خلالها اشعار الـcaller بانتهاء التحميل. و لكن للتبسيط سوف نستخدم في هذا الدرس الميثود doInBackground و الميثود onPostExcute. الآن نقوم بانشاء interface في داخل GetRawData كلاس ونسميها على سبيل المثال OnDownloadComplete و التي بدورها سوف تحتوي على ميثود الـonDownloadComplete و التي تقوم بإشعار الكلاس المستعدي (caller) بانتهاء تحميل البيانات. /** * Created by Rami on 4/20/2017. */ public class GetRawData extends AsyncTask<String, Void, String> { private static final String TAG = "GetRawData"; private final OnDownloadComplete mCallback; interface OnDownloadComplete{ void onDownloadComplete(String data); } public GetRawData(OnDownloadComplete callback) { this.mCallback = callback; } private static final String TAG = "DownloadData"; @Override protected void onPostExecute(String s) { super.onPostExecute(s); } @Override protected String doInBackground(String... params) { return null; } } كما هو موضح أعلاه الـ GetRawData تتلقى parameter و الذي هو عبارة عن اوبجكت يسمى بالـcallback و الذي يعتبر كـreference للكلاس المستدعي(caller) حيث أن الكلاس المستعدي يعمل على implements الـinterface والمسمى OnDownloadComplete. ملاحظة: بهذه الطريقة يتم فصل كلاس GetRawData عن بقية الكلاسات و الذي بدوره يعزز الـreusability و يتم اشعار الكلاس المستعدي عند انتهاء تحميل البيانات دون ايقاف أي عملية أخرى. الآن نقوم بإضافة الكود في داخل الـميثود doInBackground و التي بدورها سوف تكون المسؤولة عن تحميل بيانات الـJSON. @Override protected String doInBackground(String... params) { HttpURLConnection connection = null; BufferedReader reader = null; if(params == null){ return null; } try{ URL url = new URL(params[0]); connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.connect(); int response = connection.getResponseCode(); Log.d(TAG, "doInBackground: The response code is: " + response); StringBuilder result = new StringBuilder(); reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); String line; while(null != (line = reader.readLine())){ result.append(line).append('\n'); } return result.toString(); }catch (MalformedInputException e){ Log.e(TAG, "doInBackground: Invalid URL" + e.getMessage()); }catch (IOException e){ Log.e(TAG, "doInBackground: IO Exception reading data" + e.getMessage()); }catch (SecurityException e){ Log.e(TAG, "doInBackground: Error connetino to internet. neeed permision" + e.getMessage()); }finally { if(connection != null){ connection.disconnect(); } if(reader != null){ try{ reader.close(); }catch (IOException e){ Log.e(TAG, "doInBackground: Error closing the reader" + e.getMessage()); } } } return null; } و لقد قمنا بعمل التالي: doInBackground تتلقى الـ URL الذي يوجد فيه ملف الـJson و المتمثل في الـparameter المسمى params. نسند قيمة مبدئية null للمتغيرين reader, connection. نتحقق من الـparameter المسمى params على احتوائه على ملف JSON من عدمه. انشاء الإتصال بالإنترنت. انشاء StringBuilder object حتى يتم الحاق كامل ملف JSON بهذا object. قراءة كامل ملف JSON عن طريق BufferReader و يمكن أن تتساءل ما الفائدة من المتغير response؟ عن طريقه يمكن معرفة نجاح الاتصال بالانترنت او فشله. حيث انه اذا ظهر لك المتغير response بقيمة 200 هذا يعني نجاح الاتصال، غير ذلك يعني فشله. قراءة الملف سطر بعد سطر عن طريق المتغير line و الحاقها بالـتغير result حيث أن الـloop سوف تنتهى عند انتهاء ملفJSON. أحطنا الـ code بـ try and catch حتى نتعامل مع الأخطاء المحتملة منها: فقدان الاتصال بالانترنت، او خطأ في عنوان الرابط.. الخ. إذا حصل خطأ نقوم بـreturn null. نقوم بإضافة الكود في داخل الميثود onPostExecute و التي بدورها سوف تستعدي الميثود onDownloadComplete المتواجدة في كلاس المستعدي(caller) لإشعاره بانتهاء تحميل البيانات مع تمرير الـstring الخاص بالـJSON. @Override protected void onPostExecute(String s) { Log.d(TAG, "onPostExecute: The parameter is: " + s); if(mCallback != null){ mCallback.onDownloadComplete(s); } Log.d(TAG, "onPostExecute: Ends"); } وبالنهاية نقوم بانشاء الكلاس caller وليكن على سبيل المثال الـMainActivity. public class MainActivity extends AppCompatActivity implements GetRawData.OnDownloadComplete{ private static final String TAG = "MainActivity"; @Override protected void onCreate(Bundle savedInstanceState) { Log.d(TAG, "onCreate: starts"); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); GetRawData getRawData = new GetRawData(this); getRawData.excute("https://api.flickr.com/services/feeds/photos_public.gne"); Log.d(TAG, "onCreate: ends"); } @Override public void onDownloadComplete(String data) { Log.d(TAG, "onDownloadComplete: starts"); //Do something here. Log.d(TAG, "onDownloadComplete ends"); } } كما موضح أعلاه: انشاء الكلاس MainActivity و قمنا بعمل implements للـinterface المسمى OnDownloadComplete. انشاء اوبجكت من النوع GetRawData. استدعاء الميثود excute و تمرير الرابط الذي يحتوي على بيانات الـJSON و التي بدورها سوف تقوم بانشاء الـthread المنفصل. قمنا بـimplements للميثود onDownloadComplete بحيث سوف يتم استدعاؤها تلقائيا عند انتهاء الكلاس GetRawData من تحميل البيانات و هذا هو المقصود من اشعار الـCaller. لا ننسى الخطوة المهمة و التي لا يكتمل التطبيق إلا بها و هي أخذ الإذن للإتصال بالإنترنت. حيث تتم هذه العملية بإضافة السطر البرمجي الموضح أدناه في ملف AndroidManifest.xml المتواجد في مجلد Manifests. <uses-permission android:name="android.permission.INTERNET"/> و هنا وصلنا الى نهاية هذا الدرس.🙂 في الدروس القادمة سوف أتناول كيفية معالجة و قراءة الـJSON المحملة.
  7. السلام عليكم و رحمة الله وبركاته. في هذه المقالة سنتعلم كيفية التعامل مع ListView في Android Studio و كيفية إنشائه وبنائه داخل تطبيقك. ملاحظة: يفضل أن تكون قد قرأت مقالتي السابقة عن كيفية التعامل مع RSS Feed في Android Studio من هنا. في البداية، ما هو الـListView ؟ الـListView هو أداة من أدوات واجهة المستخدم (View) و التي تستخدم لعرض مجموعة من البيانات من خلالها و التي بدورها تتيح ميزة الـScroll Bar. و تحديدا تستخدم في عرض البيانات التي تكون على شكل مجموعة عناصر مثل قائمة لمجموعة من الصور أو أسماء فريق كرة القدم ..الخ. علما أنه لا يكاد يوجد تطبيق في Play Store إلا ويوجد فيه الـListView بما في تلك التطبيقات الشهيرة كتطبيق Facebook فكل البوستات الموجودة في الـFacebook و التي تشاهدها في الصفحة الرئيسية عند فتح التطبيق ما هي إلا شرائح من البيانات المعروضة باستخدام الـListView و كذلك في Twitter وInstagram و غيرها.. . و لذلك يعتبر الـListView من أهم الأدوات الموجودة في برنامج الـAndroid Studio و من أكثر الأدوات استخداما في بناء التطبيقات إن لم يكن أكثرها لذلك من المهم لمبرمج التطبيقات أن يتعلم طريقة إنشائه و التعامل معه في التطبيق و ما سنقوم بعمله في هذه المقالة هو عرض قائمة للبيانات المحملة و المعالجة في المقالة السابقة و هي Top10Appsباستخدام الـListView. ما هي آلية عمل الـListView؟ لإنشاء View لكل شريحة من البيانات يتطلب هذا الأمر الكثير من الوقت و المساحة من الـComputer حيث أن كل View تحتاج تقريبا اللى 1 Kb من RAM فتخيل لو تم انشاء الألاف من Views. فهنا تكمن فائدة الـListView، حيث أنها تعمل على إعادة استخدام الـView المنشأة سابقا عندما يقوم المستخدم بالنزول أو الطلوع بالقائمة (Scrolling). تتلقى الـListView بياناتها من Adapter و الذي بدوره يقوم بتوفير البيانات و تنسيق الـView المراد عرض البيانات عليها كما هو موضح أدناه. و الآن ننتقل للتطبيق في الـAndroid Studio: في البداية نقوم بفتح Android Studio ثم نقوم بالضغط على File ثم Open و ننتقل الى الـProject الذي يحتوي على الملفات و الكلاسات التي تم انشاؤها في المقالة السابقة. و الآن حتى يتم إنشاء ListView يجب علينا ما يلي: الانتقال الى ملف activity_main.xml. من قائمة Pallete ثم container نبحث عن الـListView و نقوم بسحبها الى Layout. نعدل الـID و لتكن على سبيل المثال xmlListView. نعدل الـMargins و التي هي: 16,16,16,16 كما هو موضح ادناه. و الآن نقوم بانشاء layout حيث ان هذا الـlayout يحتوي على الـViews المراد تنسيقها ووضع البيانات بداخلها عن طريق الـAdapter: من قائمة File ثم new ثم نقوم بالضغط على Layout resource file. نقوم بتسميته على سبيل المثال list_record.xml. نضيف اليه ثلاثة Text View من قائمة Pallete. نعدل الـID لهذه الـText Views وليكن على سبيل المثال: tvName, tvArtist, tvSummary. نعدل الـMargins على عحسب الرغبة. نعدل الـConstraints كما هو موضح أدناه. و الآن حتى نقوم بانشاء الـAdapter يجب علينا ما يلي: انشاء كلاس و نسميه على سبيل المثال FeedAdapter. حيث أن هذا الكلاس Extends الـArrayAdapter. و يحتوي أيضا على Inner Class ويسمى بالـViewHolder. package com.example.rami.top10apps; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.TextView; import java.util.List; /** * Created by Rami on 2/19/2017. */ public class FeedAdapter extends ArrayAdapter { private static final String TAG = "FeedAdapter"; private final int layoutResource; private final LayoutInflater layoutInflater; private List<FeedEntry> applications; public FeedAdapter(Context context, int resource, List<FeedEntry> applications) { super(context, resource); this.layoutResource = resource; this.layoutInflater = LayoutInflater.from(context); this.applications = applications; } @Override public int getCount() { return applications.size(); } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder; if (convertView == null) { convertView = layoutInflater.inflate(layoutResource, parent, false); viewHolder = new ViewHolder(convertView); convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } FeedEntry currentApp = applications.get(position); viewHolder.tvName.setText(currentApp.getName()); viewHolder.tvArtist.setText(currentApp.getArtist()); viewHolder.tvSummary.setText(currentApp.getSummary()); return convertView; } private class ViewHolder { final TextView tvName; final TextView tvArtist; final TextView tvSummary; ViewHolder(View v) { this.tvArtist = (TextView) v.findViewById(R.id.tvArtist); this.tvName = (TextView) v.findViewById(R.id.tvName); this.tvSummary = (TextView) v.findViewById(R.id.tvSummary); } } } و لقد قمنا بعمل التالي: إنشاء layoutResource variable من نوع int و الذي يحتوي على Layout الذي أنشأناه و أسميناه بالـList_record.xml. إنشاء layoutInflator variable من نوع LayoutInflator و الذي يقوم بتحويل الـLayout الى اوبجكت يمكن التعديل عليه. إنشاء applications variable من نوع <List<FeedEntry و الذي يحتوي على البيانات المراد عرضها. إنشاء Constructor يتلقى الباراميترز الخاصة بالـinstance variables. عمل override للـmethods التالية:() getCount(), getView. الميثود getCount تقوم بإرجاع عدد العناصر الموجودة بالـList. الميثود getView يتم استدعاؤها تلقائيا من ListView عند الحاجة الى بيانات جديدة و يتم تمرير الـParameters التالية اليها: position, convertView, parent. و تقوم هذه الميثود بعمل التالي: إنشاء اوبجكت من الـViewHolder بحيث يتم تخزين الـTextViews بهذا الاوجكت لمرة واحدة. حفظ هذا الاوبجكت في الـTag الخاص بالـconvertView. يتم تعديل الـTextViews وفقا للبيانات المستخرجة من الاوبجكت currentApp. بالنهاية، يتم إنشاء Inner class و تسميته بالـViewHolder. من الممكن أن تتساءل ما فائدة الـViewHolder؟ كما تلاحظ يتم استدعاء الميثود findViewById لمرة واحدة في بداية تشغيل التطبيق بينما من دون هذا الكلاس سوف يتم استدعاء هذه الميثود كل ما احتاج الـListView الى بيانات جديدة. و الآن نذهب الى الـInner class في الـكلاس MainActivity و الذي يسمى DownloadData، و نقوم بوضع هذا الكود ادناه في الميثود onPostExcute. @Override protected void onPostExecute(String s) { super.onPostExecute(s); Log.d(TAG, "onPostExecute: parameter is " + s); ParseApplications parseApplications = new ParseApplications(); parseApplications.parse(s); FeedAdapter feedAdapter = new FeedAdapter(MainActivity.this, R.layout.list_record, parseApplications.getApplications()); appList.setAdapter(feedAdapter); } كم نلاحظ أعلاه: تم إنشاء اوبجكت من الكلاس ParseApplications و الذي بدوره يقوم بمعالجة البيانات المحملة. إنشاء اوبجكت من الكلاس FeedAdapter و تمرير الـarguments اللازمة للـAdapter و أخيرا يتم استدعاء الميثود setAdapter على الاوبجكت appList و الذي يمثل الـxmlListView. ملاحظة: الكلاس DownloadData تم إنشاؤه في المقالة السابقة. و أخيرا نقوم بتشغيل البرنامج وهذه هي النتيجة النهائية. و هنا وصلنا الى نهاية هذا الدرس.😄 في الدروس القادمة سوف أتناول كيفية التعامل مع ملفات الـJson في الـAndroid.
  8. السلام عليكم و رحمة الله وبركاته. في هذه المقالة سنتعلم كيفية التعامل مع ListView في Android Studio و كيفية إنشائه وبنائه داخل تطبيقك. ملاحظة: يفضل أن تكون قد قرأت مقالتي السابقة عن كيفية التعامل مع RSS Feed في Android Studio من هنا. في البداية، ما هو الـListView ؟ الـListView هو أداة من أدوات واجهة المستخدم (View) و التي تستخدم لعرض مجموعة من البيانات من خلالها و التي بدورها تتيح ميزة الـScroll Bar. و تحديدا تستخدم في عرض البيانات التي تكون على شكل مجموعة عناصر مثل قائمة لمجموعة من الصور أو أسماء فريق كرة القدم ..الخ. علما أنه لا يكاد يوجد تطبيق في Play Store إلا ويوجد فيه الـListView بما في تلك التطبيقات الشهيرة كتطبيق Facebook فكل البوستات الموجودة في الـFacebook و التي تشاهدها في الصفحة الرئيسية عند فتح التطبيق ما هي إلا شرائح من البيانات المعروضة باستخدام الـListView و كذلك في Twitter وInstagram و غيرها.. . و لذلك يعتبر الـListView من أهم الأدوات الموجودة في برنامج الـAndroid Studio و من أكثر الأدوات استخداما في بناء التطبيقات إن لم يكن أكثرها لذلك من المهم لمبرمج التطبيقات أن يتعلم طريقة إنشائه و التعامل معه في التطبيق و ما سنقوم بعمله في هذه المقالة هو عرض قائمة للبيانات المحملة و المعالجة في المقالة السابقة و هي Top10Appsباستخدام الـListView. ما هي آلية عمل الـListView؟ لإنشاء View لكل شريحة من البيانات يتطلب هذا الأمر الكثير من الوقت و المساحة من الـComputer حيث أن كل View تحتاج تقريبا اللى 1 Kb من RAM فتخيل لو تم انشاء الألاف من Views. فهنا تكمن فائدة الـListView، حيث أنها تعمل على إعادة استخدام الـView المنشأة سابقا عندما يقوم المستخدم بالنزول أو الطلوع بالقائمة (Scrolling). تتلقى الـListView بياناتها من Adapter و الذي بدوره يقوم بتوفير البيانات و تنسيق الـView المراد عرض البيانات عليها كما هو موضح أدناه. و الآن ننتقل للتطبيق في الـAndroid Studio: في البداية نقوم بفتح Android Studio ثم نقوم بالضغط على File ثم Open و ننتقل الى الـProject الذي يحتوي على الملفات و الكلاسات التي تم انشاؤها في المقالة السابقة. و الآن حتى يتم إنشاء ListView يجب علينا ما يلي: الانتقال الى ملف activity_main.xml. من قائمة Pallete ثم container نبحث عن الـListView و نقوم بسحبها الى Layout. نعدل الـID و لتكن على سبيل المثال xmlListView. نعدل الـMargins و التي هي: 16,16,16,16 كما هو موضح ادناه. و الآن نقوم بانشاء layout حيث ان هذا الـlayout يحتوي على الـViews المراد تنسيقها ووضع البيانات بداخلها عن طريق الـAdapter: من قائمة File ثم new ثم نقوم بالضغط على Layout resource file. نقوم بتسميته على سبيل المثال list_record.xml. نضيف اليه ثلاثة Text View من قائمة Pallete. نعدل الـID لهذه الـText Views وليكن على سبيل المثال: tvName, tvArtist, tvSummary. نعدل الـMargins على عحسب الرغبة. نعدل الـConstraints كما هو موضح أدناه. و الآن حتى نقوم بانشاء الـAdapter يجب علينا ما يلي: انشاء كلاس و نسميه على سبيل المثال FeedAdapter. حيث أن هذا الكلاس Extends الـArrayAdapter. و يحتوي أيضا على Inner Class ويسمى بالـViewHolder. package com.example.rami.top10apps; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.TextView; import java.util.List; /** * Created by Rami on 2/19/2017. */ public class FeedAdapter extends ArrayAdapter { private static final String TAG = "FeedAdapter"; private final int layoutResource; private final LayoutInflater layoutInflater; private List<FeedEntry> applications; public FeedAdapter(Context context, int resource, List<FeedEntry> applications) { super(context, resource); this.layoutResource = resource; this.layoutInflater = LayoutInflater.from(context); this.applications = applications; } @Override public int getCount() { return applications.size(); } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder; if (convertView == null) { convertView = layoutInflater.inflate(layoutResource, parent, false); viewHolder = new ViewHolder(convertView); convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } FeedEntry currentApp = applications.get(position); viewHolder.tvName.setText(currentApp.getName()); viewHolder.tvArtist.setText(currentApp.getArtist()); viewHolder.tvSummary.setText(currentApp.getSummary()); return convertView; } private class ViewHolder { final TextView tvName; final TextView tvArtist; final TextView tvSummary; ViewHolder(View v) { this.tvArtist = (TextView) v.findViewById(R.id.tvArtist); this.tvName = (TextView) v.findViewById(R.id.tvName); this.tvSummary = (TextView) v.findViewById(R.id.tvSummary); } } } و لقد قمنا بعمل التالي: إنشاء layoutResource variable من نوع int و الذي يحتوي على Layout الذي أنشأناه و أسميناه بالـList_record.xml. إنشاء layoutInflator variable من نوع LayoutInflator و الذي يقوم بتحويل الـLayout الى اوبجكت يمكن التعديل عليه. إنشاء applications variable من نوع <List<FeedEntry و الذي يحتوي على البيانات المراد عرضها. إنشاء Constructor يتلقى الباراميترز الخاصة بالـinstance variables. عمل override للـmethods التالية:() getCount(), getView. الميثود getCount تقوم بإرجاع عدد العناصر الموجودة بالـList. الميثود getView يتم استدعاؤها تلقائيا من ListView عند الحاجة الى بيانات جديدة و يتم تمرير الـParameters التالية اليها: position, convertView, parent. و تقوم هذه الميثود بعمل التالي: إنشاء اوبجكت من الـViewHolder بحيث يتم تخزين الـTextViews بهذا الاوجكت لمرة واحدة. حفظ هذا الاوبجكت في الـTag الخاص بالـconvertView. يتم تعديل الـTextViews وفقا للبيانات المستخرجة من الاوبجكت currentApp. بالنهاية، يتم إنشاء Inner class و تسميته بالـViewHolder. من الممكن أن تتساءل ما فائدة الـViewHolder؟ كما تلاحظ يتم استدعاء الميثود findViewById لمرة واحدة في بداية تشغيل التطبيق بينما من دون هذا الكلاس سوف يتم استدعاء هذه الميثود كل ما احتاج الـListView الى بيانات جديدة. و الآن نذهب الى الـInner class في الـكلاس MainActivity و الذي يسمى DownloadData، و نقوم بوضع هذا الكود ادناه في الميثود onPostExcute. @Override protected void onPostExecute(String s) { super.onPostExecute(s); Log.d(TAG, "onPostExecute: parameter is " + s); ParseApplications parseApplications = new ParseApplications(); parseApplications.parse(s); FeedAdapter feedAdapter = new FeedAdapter(MainActivity.this, R.layout.list_record, parseApplications.getApplications()); appList.setAdapter(feedAdapter); } كم نلاحظ أعلاه: تم إنشاء اوبجكت من الكلاس ParseApplications و الذي بدوره يقوم بمعالجة البيانات المحملة. إنشاء اوبجكت من الكلاس FeedAdapter و تمرير الـarguments اللازمة للـAdapter و أخيرا يتم استدعاء الميثود setAdapter على الاوبجكت appList و الذي يمثل الـxmlListView. ملاحظة: الكلاس DownloadData تم إنشاؤه في المقالة السابقة. و أخيرا نقوم بتشغيل البرنامج وهذه هي النتيجة النهائية. و هنا وصلنا الى نهاية هذا الدرس.😄 في الدروس القادمة سوف أتناول كيفية التعامل مع ملفات الـJson في الـAndroid.
  9. السلام عليكم و رحمة الله و بركاته. في هذه المقالة سنتعلم كيفية التعامل مع RSS Feed عن طريق تحميلها و قرائتها بالإضافة الى استخراجها في الـAndroid Studio. في البداية، ما هي RSS ؟ خدمة RSS هي خدمة لمتابعة آخر الأخبار بشكل مباشر وبدون الحاجة إلى زيارة الموقع ، ستقدم لك خدمة RSS الكثير من المعلومات منها: عنوان الخبر ، ومختصر لنص الخبر ، ووصلة أو رابط لنص الخبر الكامل على الموقع ، و صورة عن الخبر، بالإضافة إلى عدد التعليقات الموجودة ... الخ. و الآن ننتقل الى التطبيق في الـ Android Studio... في البداية نقوم بفتح Android Studio ثم نقوم بالضغط على Start a new Android Studio project و نبقي الخيارات الافتراضية على حالها و نقوم بتسميته و حفظه. و الآن حتى يتم تحميل XML file يجب علينا: انشاء thread منفصل و لحسن الحظ يتوفر على الـ Android Studio كلاس يسمى بالـ AsyncTask يقوم باغلب المهام. نقوم بانشاء Inner class في MainActivity.java و الذي بدوره يقوم بـ AsyncTask class" extends"، ثم نضيف الmethods وهي onPostExecute ،doInBackground كما هو موضح ادناه: public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } private class DownloadData extends AsyncTask<String, Void, String> { private static final String TAG = "DownloadData"; @Override protected void onPostExecute(String s) { super.onPostExecute(s); } @Override protected String doInBackground(String... params) { return null; } الآن نقوم بانشاء method في داخل DownloadData كلاس ونسميها على سبيل المثال downloadXML و التي بدورها سوف تقوم بتحميل ملف XML كاملا حيث سيتم استدعاء هذه الـmethod في doInBackround @Override protected String doInBackground(String... params) { String rssFeed = downloadXML(params[0]); if (rssFeed == null) { Log.e(TAG, "doInBackground: Error downloading"); } return rssFeed; } private String downloadXML(String urlPath) { StringBuilder XMLResult = new StringBuilder(); try { URL url = new URL(urlPath); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); int response = connection.getResponseCode(); BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); int charRead; char[] inputBuffer = new char[500]; while (true) { charRead = reader.read(inputBuffer); if (charRead < 0) { break; } if (charRead > 0) { XMLResult.append(String.copyValueOf(inputBuffer, 0, charRead)); } } reader.close(); return XMLResult.toString(); } catch (MalformedURLException e) { Log.e(TAG, "downloadXML: Invalid URL " + e.getMessage()); } catch (IOException e) { Log.e(TAG, "downloadXML: IO Exception reading Data: " + e.getMessage()); } catch (SecurityException e) { Log.e(TAG, "downloadXML: Permesion denied. " + e.getMessage()); } return null; } كم هو موضح أعلاه الـ downloadXML تتلقى parameter و الذي هو عبارة عن URL لملف XML. ملاحظة: سوف يتم استخدام RSS Feed الموجودة في apple.com و المتعلقة Top10FreeApps. و لقد قمنا بعمل التالي: انشاء StringBuilder object حتى يتم الحاق كامل ملف XML بهذا object. انشاء الإتصال بالإنترنت. قراءة كامل ملف XML عن طريق BufferReader و يمكن أن تتساءل ما الفائدة من المتغير response؟ عن طريقه يمكن معرفة نجاح الاتصال بالانترنت او فشله. حيث انه اذا ظهر لك المتغير response بقيمة 200 هذا يعني نجاح الاتصال، غير ذلك يعني فشله. قراءة عدد الأحرف الموجودة في ملف XML كما هو موضح أعلاه و إلحاقها بالمتغير XMLResult حيث أن الـloop سوف تنتهى عند انتهاء ملف XML. أحطنا الـ code بـ try and catch حتى نتعامل مع الأخطاء المحتملة منها: فقدان الاتصال بالانترنت، او خطأ في عنوان الرابط.. الخ. بالنهاية اذا حصل خطأ نقوم بـreturn null. قبل أن نبدأ باستخراج المعلومات أود أن نلقي نظرة عن ماهية ملف XML المتعلق ب Top10FreeApp. باستخدام موقع code beautify يمكننا أن نرى التكوين الداخلي لملف XML. كما نلاحظ أعلاه، ال Entry TAG يحتوي على name TAG ,summary TAG , artist TAG و التي تمثل بعضا من المعلومات الممكن استخراجها. ننتقل الآن الى كيفية استخراج المعلومات المطلوبة من ملف XML. في البداية يجب علينا عمل التالي: انشاء كلاس يحتوي على fields و التي سوف تخزن بها المعلومات المطلوبة من ملف XML. ننشئ كلاس ونسميه FeedEntry و الذي يحتوي على متغيرات: name, Artist, Summary. إضافة getters and setters لهذه المتغيرات. public class FeedEntry { private String name; private String artist; private String summary; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getArtist() { return artist; } public void setArtist(String artist) { this.artist = artist; } public String getSummary() { return summary; } public void setSummary(String summary) { this.summary = summary; } } ثم ننشئ كلاس آخر و نسميه على سبيل المثال PareseApplication و الذي بدوره سوف يحتوي على method التي تقوم بقراءة و استخراج المعلومات المطلوبة من XML file و تخزينها في array تحتوي على objects من الكلاس FeedEntry. public class ParseApplications { private ArrayList<FeedEntry> applications; public ParseApplications() { this.applications = new ArrayList<>(); } public ArrayList<FeedEntry> getApplications() { return applications; } public boolean parse(String xmlData) { boolean status = true; FeedEntry currentRecord = null; boolean inEntry = false; String textValue = ""; try { XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); factory.setNamespaceAware(true); XmlPullParser xpp = factory.newPullParser(); xpp.setInput(new StringReader(xmlData)); int eventType = xpp.getEventType(); while (eventType != XmlPullParser.END_DOCUMENT) { String tagName = xpp.getName(); switch (eventType) { case XmlPullParser.START_TAG: if ("entry".equalsIgnoreCase(tagName)) { inEntry = true; currentRecord = new FeedEntry(); } break; case XmlPullParser.TEXT: textValue = xpp.getText(); break; case XmlPullParser.END_TAG: if (inEntry) { if ("entry".equalsIgnoreCase(tagName)) { applications.add(currentRecord); inEntry = false; } else if ("name".equalsIgnoreCase(tagName)) { currentRecord.setName(textValue); } else if ("artist".equalsIgnoreCase(tagName)) { currentRecord.setArtist(textValue); }else if ("summary".equalsIgnoreCase(tagName)) { currentRecord.setSummary(textValue); } } break; default: //Nothing else to do. } eventType = xpp.next(); } } catch (Exception e) { status = false; e.printStackTrace(); } return status; } } لقد قمنا بعمل التالي: اضافة متغير applications من نوع ArrayList و الذي سوف يتم تخزين فيه objects من نوع FeedEntry. اضافة Constructor لانشاء object من هذا الكلاس و احتوائه على Getter للوصول الى المتغير applications. انشاء method و نسميها parse و التي بدورها سوف تستخرج المعلومات المطلوبة من ملف XML المحمل كما هو موضح أعلاه. هذه الـmethod تحتوي على اربع متغيرات: متغير Status من نوع boolean و الذي يدل على نجاح الـmethod او فشلها. و متغير currentRecord من نوع FeedEntry و الذي سوف يتم تخزين المعلومات المطلوبة فيه. و متغير InEntry من نوع boolean الذي سوف يعطينا إشارة بوصولنا الى Entry TAG. بالإضافة الى متغير textValue من نوع String الذي سوف يقوم بتخزين النص الموجود في الـTAG. ملاحظة: لحسن الحظ Android Studio توفر لنا كلاس اسمه XmlPullParserFactory و الذي بدوره سوف يقوم بكثير من مهام معالجة ملف XML. هذا الكلاس يعتمد على قيم ثوابت(Constatns) معرفة في الكلاس و التي تسمى بالـevents. بعض الأمثلة عليها: END_DOCUMENT, START_TAG, TEXT , END_TAG. انشاء اوبجكت من XmlPullParserFactory ثم نمرر إليه محتويات الـXML كـparameter. نقوم باستخراج المعلومات المطلوبة من ملف XML و تخزينها في currentRecord ثم اضافة هذا object الى applications. احاطة الكود بـ try and catch لتلافي الأخطاء التي من الممكن وقوعها أثناء استخراج المعلومات. و بالنهاية لا ننسى الخطوة المهمة و التي لا يكتمل التطبيق إلا بها و هي أخذ الإذن للإتصال بالإنترنت. حيث تتم هذه العملية بإضافة السطر البرمجي الموضح أدناه في ملف AndroidManifest.xml المتواجد في مجلد Manifests. <uses-permission android:name="android.permission.INTERNET"/> و هنا وصلنا الى نهاية هذا الدرس.😄 في الدروس القادمة سوف أتناول كيفية عرض المعلومات المستخرجة باستخدام ListViews.
  10. السلام عليكم و رحمة الله و بركاته. في هذه المقالة سنتعلم كيفية التعامل مع RSS Feed عن طريق تحميلها و قرائتها بالإضافة الى استخراجها في الـAndroid Studio. في البداية، ما هي RSS ؟ خدمة RSS هي خدمة لمتابعة آخر الأخبار بشكل مباشر وبدون الحاجة إلى زيارة الموقع ، ستقدم لك خدمة RSS الكثير من المعلومات منها: عنوان الخبر ، ومختصر لنص الخبر ، ووصلة أو رابط لنص الخبر الكامل على الموقع ، و صورة عن الخبر، بالإضافة إلى عدد التعليقات الموجودة ... الخ. و الآن ننتقل الى التطبيق في الـ Android Studio... في البداية نقوم بفتح Android Studio ثم نقوم بالضغط على Start a new Android Studio project و نبقي الخيارات الافتراضية على حالها و نقوم بتسميته و حفظه. و الآن حتى يتم تحميل XML file يجب علينا: انشاء thread منفصل و لحسن الحظ يتوفر على الـ Android Studio كلاس يسمى بالـ AsyncTask يقوم باغلب المهام. نقوم بانشاء Inner class في MainActivity.java و الذي بدوره يقوم بـ AsyncTask class" extends"، ثم نضيف الmethods وهي onPostExecute ،doInBackground كما هو موضح ادناه: public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } private class DownloadData extends AsyncTask<String, Void, String> { private static final String TAG = "DownloadData"; @Override protected void onPostExecute(String s) { super.onPostExecute(s); } @Override protected String doInBackground(String... params) { return null; } الآن نقوم بانشاء method في داخل DownloadData كلاس ونسميها على سبيل المثال downloadXML و التي بدورها سوف تقوم بتحميل ملف XML كاملا حيث سيتم استدعاء هذه الـmethod في doInBackround @Override protected String doInBackground(String... params) { String rssFeed = downloadXML(params[0]); if (rssFeed == null) { Log.e(TAG, "doInBackground: Error downloading"); } return rssFeed; } private String downloadXML(String urlPath) { StringBuilder XMLResult = new StringBuilder(); try { URL url = new URL(urlPath); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); int response = connection.getResponseCode(); BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); int charRead; char[] inputBuffer = new char[500]; while (true) { charRead = reader.read(inputBuffer); if (charRead < 0) { break; } if (charRead > 0) { XMLResult.append(String.copyValueOf(inputBuffer, 0, charRead)); } } reader.close(); return XMLResult.toString(); } catch (MalformedURLException e) { Log.e(TAG, "downloadXML: Invalid URL " + e.getMessage()); } catch (IOException e) { Log.e(TAG, "downloadXML: IO Exception reading Data: " + e.getMessage()); } catch (SecurityException e) { Log.e(TAG, "downloadXML: Permesion denied. " + e.getMessage()); } return null; } كم هو موضح أعلاه الـ downloadXML تتلقى parameter و الذي هو عبارة عن URL لملف XML. ملاحظة: سوف يتم استخدام RSS Feed الموجودة في apple.com و المتعلقة Top10FreeApps. و لقد قمنا بعمل التالي: انشاء StringBuilder object حتى يتم الحاق كامل ملف XML بهذا object. انشاء الإتصال بالإنترنت. قراءة كامل ملف XML عن طريق BufferReader و يمكن أن تتساءل ما الفائدة من المتغير response؟ عن طريقه يمكن معرفة نجاح الاتصال بالانترنت او فشله. حيث انه اذا ظهر لك المتغير response بقيمة 200 هذا يعني نجاح الاتصال، غير ذلك يعني فشله. قراءة عدد الأحرف الموجودة في ملف XML كما هو موضح أعلاه و إلحاقها بالمتغير XMLResult حيث أن الـloop سوف تنتهى عند انتهاء ملف XML. أحطنا الـ code بـ try and catch حتى نتعامل مع الأخطاء المحتملة منها: فقدان الاتصال بالانترنت، او خطأ في عنوان الرابط.. الخ. بالنهاية اذا حصل خطأ نقوم بـreturn null. قبل أن نبدأ باستخراج المعلومات أود أن نلقي نظرة عن ماهية ملف XML المتعلق ب Top10FreeApp. باستخدام موقع code beautify يمكننا أن نرى التكوين الداخلي لملف XML. كما نلاحظ أعلاه، ال Entry TAG يحتوي على name TAG ,summary TAG , artist TAG و التي تمثل بعضا من المعلومات الممكن استخراجها. ننتقل الآن الى كيفية استخراج المعلومات المطلوبة من ملف XML. في البداية يجب علينا عمل التالي: انشاء كلاس يحتوي على fields و التي سوف تخزن بها المعلومات المطلوبة من ملف XML. ننشئ كلاس ونسميه FeedEntry و الذي يحتوي على متغيرات: name, Artist, Summary. إضافة getters and setters لهذه المتغيرات. public class FeedEntry { private String name; private String artist; private String summary; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getArtist() { return artist; } public void setArtist(String artist) { this.artist = artist; } public String getSummary() { return summary; } public void setSummary(String summary) { this.summary = summary; } } ثم ننشئ كلاس آخر و نسميه على سبيل المثال PareseApplication و الذي بدوره سوف يحتوي على method التي تقوم بقراءة و استخراج المعلومات المطلوبة من XML file و تخزينها في array تحتوي على objects من الكلاس FeedEntry. public class ParseApplications { private ArrayList<FeedEntry> applications; public ParseApplications() { this.applications = new ArrayList<>(); } public ArrayList<FeedEntry> getApplications() { return applications; } public boolean parse(String xmlData) { boolean status = true; FeedEntry currentRecord = null; boolean inEntry = false; String textValue = ""; try { XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); factory.setNamespaceAware(true); XmlPullParser xpp = factory.newPullParser(); xpp.setInput(new StringReader(xmlData)); int eventType = xpp.getEventType(); while (eventType != XmlPullParser.END_DOCUMENT) { String tagName = xpp.getName(); switch (eventType) { case XmlPullParser.START_TAG: if ("entry".equalsIgnoreCase(tagName)) { inEntry = true; currentRecord = new FeedEntry(); } break; case XmlPullParser.TEXT: textValue = xpp.getText(); break; case XmlPullParser.END_TAG: if (inEntry) { if ("entry".equalsIgnoreCase(tagName)) { applications.add(currentRecord); inEntry = false; } else if ("name".equalsIgnoreCase(tagName)) { currentRecord.setName(textValue); } else if ("artist".equalsIgnoreCase(tagName)) { currentRecord.setArtist(textValue); }else if ("summary".equalsIgnoreCase(tagName)) { currentRecord.setSummary(textValue); } } break; default: //Nothing else to do. } eventType = xpp.next(); } } catch (Exception e) { status = false; e.printStackTrace(); } return status; } } لقد قمنا بعمل التالي: اضافة متغير applications من نوع ArrayList و الذي سوف يتم تخزين فيه objects من نوع FeedEntry. اضافة Constructor لانشاء object من هذا الكلاس و احتوائه على Getter للوصول الى المتغير applications. انشاء method و نسميها parse و التي بدورها سوف تستخرج المعلومات المطلوبة من ملف XML المحمل كما هو موضح أعلاه. هذه الـmethod تحتوي على اربع متغيرات: متغير Status من نوع boolean و الذي يدل على نجاح الـmethod او فشلها. و متغير currentRecord من نوع FeedEntry و الذي سوف يتم تخزين المعلومات المطلوبة فيه. و متغير InEntry من نوع boolean الذي سوف يعطينا إشارة بوصولنا الى Entry TAG. بالإضافة الى متغير textValue من نوع String الذي سوف يقوم بتخزين النص الموجود في الـTAG. ملاحظة: لحسن الحظ Android Studio توفر لنا كلاس اسمه XmlPullParserFactory و الذي بدوره سوف يقوم بكثير من مهام معالجة ملف XML. هذا الكلاس يعتمد على قيم ثوابت(Constatns) معرفة في الكلاس و التي تسمى بالـevents. بعض الأمثلة عليها: END_DOCUMENT, START_TAG, TEXT , END_TAG. انشاء اوبجكت من XmlPullParserFactory ثم نمرر إليه محتويات الـXML كـparameter. نقوم باستخراج المعلومات المطلوبة من ملف XML و تخزينها في currentRecord ثم اضافة هذا object الى applications. احاطة الكود بـ try and catch لتلافي الأخطاء التي من الممكن وقوعها أثناء استخراج المعلومات. و بالنهاية لا ننسى الخطوة المهمة و التي لا يكتمل التطبيق إلا بها و هي أخذ الإذن للإتصال بالإنترنت. حيث تتم هذه العملية بإضافة السطر البرمجي الموضح أدناه في ملف AndroidManifest.xml المتواجد في مجلد Manifests. <uses-permission android:name="android.permission.INTERNET"/> و هنا وصلنا الى نهاية هذا الدرس.😄 في الدروس القادمة سوف أتناول كيفية عرض المعلومات المستخرجة باستخدام ListViews. تم ترقية هذا الطرح المميز الى صفحة المقالات
  11. مؤخرا نسمع كثيرا عن مصطلح البيانات الضخمة Big Data و سرعة انتشار هذا المجال في سوق العمل. و لكن هل تساءلنا ما هي البيانات الضخمة Big Data؟ لكي نتفق مبدئيا هناك اكثر من تعريف لمصطلح البيانات الضخمة Big Data وكما أوضح الاتحاد الدولي للاتصالات(ITU) بأنه لا يوجد تعريف دقيق للبيانات الضخمة . و بشكل عام فإننا حين نتحدث عن البيانات الضخمة فنحن نتحدث عن بيانات متعددة الأنواع والمصادر والأحجام. تعريف: قبل ان نتطرق لتعريف البيانات الضخمة، يجب علينا معرفة ما هي البيانات؟ البيانات Data: هي الصورة الخام للمعلومات قبل عمليات الفرز والترتيب والمعالجة ولا يمكن الاستفادة منها بصورتها الأولية قبل المعالجة. و يمكن ان تقسم البيانات الخام الى ثلاثة انواع: بيانات مهيكلة: وهى البيانات المنظمة في جداول او قواعد بيانات. بيانات غير مهيكلة: تشكل النسبة الأكبر من البيانات، وهى البيانات التي يولدها الأشخاص يوميا من كتابات نصية وصور وفيديو ورسائل ونقرات على مواقع الانترنت... الخ. بيانات شبه مهيكلة: تعتبر نوعا من البيانات المهيكلة الا ان البيانات لا تكون في صورة جداول او قواعد بيانات. و الآن ما هي البيانات الضخمة؟ يعرف الخبراء البيانات الضخمة بأنها أي مجموعة من البيانات التي هي بحجم يفوق قدرة معالجتها باستخدام أدوات قواعد البيانات التقليدية من التقاط، ومشاركة ونقل، وتخزين، وإدارة و تحليل في غضون فترة زمنية مقبولة لتلك البيانات؛ و من وجهة نظر مقدمي الخدمات، هي الأدوات والعمليات التي تحتاجها المنظمات للتعامل مع كمية كبيرة من البيانات لغرض التحليل. الطرفان اتفقا على إنها بيانات هائلة لا يمكن معالجتها بالطرق التقليدية في ظل تلك القيود المذكورة آنفاً. إليكم بعض التعاريف لمنظمات وجهات عالمية والتي تصف البيانات الضخمة: تعرف شركة جارتنر (Gartner Inc) المتخصصة في أبحاث واستشارات تقنية المعلومات بأنها "الأصول المعلوماتية كبيرة الأحجام وسريعة التدفق وكثيرة التنوع، والتي تتطلب طرق معالجة مجدية اقتصادياً ومبتكرة من أجل تطوير البصائر وطرق اتخاذ القرارات". كما تعرفها شركة (IBM) " تنشأ البيانات الضخمة عن طريق كل شيء من حولنا وفي كل الأوقات كل عملية رقمية وكل تبادل في وسائل التواصل الاجتماعي ينتج لنا البيانات الضخمة، تتناقلها الأنظمة، وأجهزة الاستشعار، والأجهزة النقالة البيانات الضخمة لها مصادر متعددة في السرعة والحجم والتنوع ولكي نستخرج منفعة معنوية من البيانات الضخمة نحتاج إلى معالجة مثالية، وقدرات تحليلية، ومهارات ". أما المنظمة الدولية للمعايير(ISO) فتعرفها بأنها "مجموعة أو مجموعات من البيانات لها خصائصها الفريدة (مثل الحجم، السرعة، التنوع، التباين، صحة البيانات... إلخ) ، لا يمكن معالجتها بكفاءة باستخدام التكنولوجيا الحالية والتقليدية لتحقيق الاستفادة منها" . ويعرفها الاتحاد الدولي للاتصالات (ITU) "يشير مصطلح البيانات الضخمة إلى مجموعات البيانات التي تتميز بأنها فائقة حجماً وسرعة أو تنوعاً، بالقياس إلى أنواع مجموعات البيانات المعهودة الاستخدام" . بسبب الوقت والجهد والتكلفة الكبيرة التي تحتاجها البيانات الضخمة لتحليلها ومعالجتها اضطر التقنيون على الاعتماد على أنظمة الذكاء الاصطناعي Artificial Intelligence التي لديها القدرة على التعلم والاستنتاج ورد الفعل على أوضاع لم تبرمج في الآلة باستخدام خوارزميات معقدة للعمل عليها، بالإضافة إلى استخدام تقنيات الحوسبة السحابية لإتمام عملها. عادة يكون المقصود به البيانات الضخمة هي البيانات التي تقاس بالبيتا بايت petabyte (ألف تيرا بايت) أو الايكسا بايت exabyte (مليون تيرابيات)؛ ووفقاً لــ IBM فإنها ابتداءاً من العام 2012 الميلادية فإننا يومياً ننشأ ما يقارب 2.5 كوينتيليون بايت من البيانات الضخمة (كوينتيليون هو الرقم واحد متبوعاً بثمانية عشرة (18)صفر ). و للمعلومية تمت اضافة كلمة Big Data الى قاموس Oxford ككلمة انجليزية مستحدثة. تصنيف البيانات الضخمة: كثير منا يعتقد بأن البيانات الضخمة تصنف وفقا للحجم فقط، في الحقيقة هي تصنف وفقا لمبدأ (3V's) و يتكون من: الحجم Volume: و هي حجم البيانات المستخرجة من مصدر ما، وهو ما يحدد قيمة وامكانات البيانات لكي تصنف من ضمن البيانات الضخمة؛ و قد يكون الخاصية الأكثر أهمية في تحليل البيانات الضخمة .كما أن وصفها بالضخمة لا يحدد كمية معينة؛ فكما ذكرنا آنفا بأن الحجم يقاس عادة بالبيتا بايت او بالإكسا بايت. و للمعلومية بحلول العام 2020 سيحتوى الفضاء الإلكتروني على ما يقرب من 40.000 ميتابايت من البيانات الجاهزة للتحليل واستخلاص المعلومات؛ ويقدر أن %90 من البيانات الموجودة في العالم اليوم قد استحدثت خلال السنتين الأخيرتين، بواسطة أجهزة وعلى أيدي بشر ساهم كلاهما في تزايد البيانات. التنوع Variety: و يقصد بها تنوع البيانات المستخرجة، والتي تساعد المستخدمين سواء كاموا باحثين أو محللين على اختيار البيانات المناسبة لمجال بحثهم و تتضمن بيانات مهيكلة في قواعد بيانات و بيانات غير مهيكلة تأتي من طابعها غير الممنهج، مثل: الصور ومقاطع وتسجيلات الصوت وأشرطة الفيديو والرسائل القصيرة وسجلات المكالمات وبيانات الخرائط (GPS)... وضيرها الكثير؛ وتتطلب وقتاً وجهداً لتهيئتها في شكل مناسب للتجهيز والتحليل. السرعة Velocity: و يقصد بها سرعة إنتاج واستخراج البيانات لتغطية الطلب عليها؛ حيث تعتبر السرعة عنصراً حاسماً في اتخاذ القرار بناء على هذه البيانات، وهو الوقت الذي نستغرقه من لحظة وصول هذه البيانات إلى لحظة الخروج بالقرار بناء عليها. سابقا كانت الشركات تستخدم لمعالجة مجموعة صغيرة من البيانات المخزنة في صورة بيانات مهيكلة في قواعد بيانات عملية تسمى بال ” Batch Process“ حيث كان يتم تحليل كل مجموعة بيانات واحدة تلو الأخرى في انتظار وصول النتائج. مع الازدياد الضخم في حجم البيانات وسرعة تواترها أصبحت الحاجة أكثر إلحاحا الى نظام يضمن سرعة فائقة في تحليل البيانات الضخمة في الوقت اللحظي “Real Time“ أو سرعة تقارب الوقت اللحظي. أدت تلك الحاجة الى ابتكار تقنيات وحلول مثل Apache و SAP HANA و Hadoop وغيرها الكثير. كما أضيف مؤخراً لتلك المبادئ الثلاث وفقاً لخصائص البيانات الضخمة "مبدأ صحة البيانات الضخمة": فيمثل التمتع بالقدرة على تقييمها عنصراً جوهرياً في وضع الأساس لاتخاذ القرارات الهامة بناءً عليها. ويجب الأخذ بالاعتبار تباين هذه البيانات وعدم التأكد من صحتها في عملية اتخاذ القرار. مصادر البيانات الضخمة: قامت اللجنة الاقتصادية لأوروبا، بتقديم تقرير بعنوان ”ماذا تعنيه البيانات الضخمة للإحصاءات الرسمية“ آذار مارس و قد أوردت فيه تصنيفا لمصادر البيانات الضخمة على النحو التالي: المصادر الناشئة عن إدارة أحد البرامج، سواء كان برنامجا حكوميا أو غير حكومي، كالسجلات الطبية الإلكترونية وزيارات المستشفيات وسجلات التأمين والسجلات المصرفية وبنوك الطعام. المصادر التجارية أو ذات الصلة بالمعاملات، الناشئة عن معاملات بين كيانين، على سبيل المثال معاملات البطاقات الائتمانية والمعاملات التي تجرى عن طريق الإنترنت بوسائل منها الأجهزة المحمولة. مصادر شبكات أجهزة الاستشعار، على سبيل المثال، التصوير بالأقمار الصناعية، وأجهزة استشعار الطرق، وأجهزة استشعار المناخ. مصادر أجهزة التتبع، على سبيل المثال تتبع البيانات المستمدة من الهواتف المحمولة والنظام العالمي لتحديد المواقع. مصادر البيانات السلوكية، على سبيل المثال، مرات البحث على الإنترنت عن منتج أو خدمة ما أو أي نوع آخر من المعلومات، ومرات مشاهدة إحدى الصفحات على الإنترنت. مصادر البيانات المتعلقة بالآراء، على سبيل المثال، التعليقات على وسائط التواصل الاجتماعي. أمثلة من الواقع على البيانات الضخمة: لدى واتس آب أكثر من مليار مستخدم، و يتم تداول اكثر من 42 مليار رسالة و حوالي 1.6 مليار صورة بشكل يومي. فيسبوك تتعامل مع أكثر من 50 مليار صورة من مستخدميها. جووجل Google تتعامل مع حوالي 100 مليار عملية بحث في الشهر. أهمية البيانات الضخمة: للبيانات الضخمة اهمية عالية فهي تقدم ميزة تنافسية عالية للشركات اذا استطاعت الاستفادة منها ومعالجتها لأنها تقدم فهما أعمق لعملائها ومتطلباتهم ويساعد ذلك على اتخاذ القرارات المناسبة و الملائمة داخل الشركة بطريقة أكثر فعالية و ذلك بناء على المعلومات المستخرجة من قواعد بيانات العملاء وبالتالي زيادة الكفاءة والربح وتقليل الخسائر. فباستخدام تقنيات و أدوات تحليل البيانات الضخمة استطاعت وول مارت تحسين نتائج البحث عن منتجاتها عبر الأنترنت بنسبة 10-15% بينما في تقرير لماكينزى-وهى شركة رائدة في مجال استشارات الاعمال- ان القطاع الصحي بالولايات المتحدة لو كان يستخدم تقنيات تحليل البيانات الضخمة بفاعليه وكفاءه لكان قد أنتج أكثر من 300 مليون دولار أمريكى كفائض سنوى من ميزانيه الصحة ثلثيها بسبب خفض تكاليف الانفاق بنسبة 8%(1). الخاتمة: في زمننا هذا نشهد انفجارا ضخما في البيانات فتحليل و معالجة هذه البيانات يزيد بشكل رئيسي في فهم و استيعاب متطلبات العملاء و بالتالي زيادة الكفاءة و الانتاجية و تقليل الخسائر بالنسبة للشركات. إلا أن هنالك العديد من التحديات والمعوقات التي تعيق استخدام البيانات الضخمة أو التوسع في استخدامها والتي ممكن تناولها في مقال آخر بإذن الله تعالى . ومع مرور الوقت والتقدم التكنولوجي، فمن المتوقع إحراز تقدم كبير فيما يتعلق بمعالجة تحديات ومعوقات استخدام البيانات الضخمة بشكل أوسع. و في النهاية اتمنى ان تكون هذه المقالة قد لاقت اعجابكم و أن تثري المحتوى العربي على الانترنت. المصادر: 1- Mckinsey&Company: Big Data: The next frontier for innovation,competition and productivity. May 2011
  12. مؤخرا نسمع كثيرا عن مصطلح البيانات الضخمة Big Data و سرعة انتشار هذا المجال في سوق العمل. و لكن هل تساءلنا ما هي البيانات الضخمة Big Data؟ لكي نتفق مبدئيا هناك اكثر من تعريف لمصطلح البيانات الضخمة Big Data وكما أوضح الاتحاد الدولي للاتصالات(ITU) بأنه لا يوجد تعريف دقيق للبيانات الضخمة . و بشكل عام فإننا حين نتحدث عن البيانات الضخمة فنحن نتحدث عن بيانات متعددة الأنواع والمصادر والأحجام. تعريف: قبل ان نتطرق لتعريف البيانات الضخمة، يجب علينا معرفة ما هي البيانات؟ البيانات Data: هي الصورة الخام للمعلومات قبل عمليات الفرز والترتيب والمعالجة ولا يمكن الاستفادة منها بصورتها الأولية قبل المعالجة. و يمكن ان تقسم البيانات الخام الى ثلاثة انواع: بيانات مهيكلة: وهى البيانات المنظمة في جداول او قواعد بيانات. بيانات غير مهيكلة: تشكل النسبة الأكبر من البيانات، وهى البيانات التي يولدها الأشخاص يوميا من كتابات نصية وصور وفيديو ورسائل ونقرات على مواقع الانترنت... الخ. بيانات شبه مهيكلة: تعتبر نوعا من البيانات المهيكلة الا ان البيانات لا تكون في صورة جداول او قواعد بيانات. و الآن ما هي البيانات الضخمة؟ يعرف الخبراء البيانات الضخمة بأنها أي مجموعة من البيانات التي هي بحجم يفوق قدرة معالجتها باستخدام أدوات قواعد البيانات التقليدية من التقاط، ومشاركة ونقل، وتخزين، وإدارة و تحليل في غضون فترة زمنية مقبولة لتلك البيانات؛ و من وجهة نظر مقدمي الخدمات، هي الأدوات والعمليات التي تحتاجها المنظمات للتعامل مع كمية كبيرة من البيانات لغرض التحليل. الطرفان اتفقا على إنها بيانات هائلة لا يمكن معالجتها بالطرق التقليدية في ظل تلك القيود المذكورة آنفاً. إليكم بعض التعاريف لمنظمات وجهات عالمية والتي تصف البيانات الضخمة: تعرف شركة جارتنر (Gartner Inc) المتخصصة في أبحاث واستشارات تقنية المعلومات بأنها "الأصول المعلوماتية كبيرة الأحجام وسريعة التدفق وكثيرة التنوع، والتي تتطلب طرق معالجة مجدية اقتصادياً ومبتكرة من أجل تطوير البصائر وطرق اتخاذ القرارات". كما تعرفها شركة (IBM) " تنشأ البيانات الضخمة عن طريق كل شيء من حولنا وفي كل الأوقات كل عملية رقمية وكل تبادل في وسائل التواصل الاجتماعي ينتج لنا البيانات الضخمة، تتناقلها الأنظمة، وأجهزة الاستشعار، والأجهزة النقالة البيانات الضخمة لها مصادر متعددة في السرعة والحجم والتنوع ولكي نستخرج منفعة معنوية من البيانات الضخمة نحتاج إلى معالجة مثالية، وقدرات تحليلية، ومهارات ". أما المنظمة الدولية للمعايير(ISO) فتعرفها بأنها "مجموعة أو مجموعات من البيانات لها خصائصها الفريدة (مثل الحجم، السرعة، التنوع، التباين، صحة البيانات... إلخ) ، لا يمكن معالجتها بكفاءة باستخدام التكنولوجيا الحالية والتقليدية لتحقيق الاستفادة منها" . ويعرفها الاتحاد الدولي للاتصالات (ITU) "يشير مصطلح البيانات الضخمة إلى مجموعات البيانات التي تتميز بأنها فائقة حجماً وسرعة أو تنوعاً، بالقياس إلى أنواع مجموعات البيانات المعهودة الاستخدام" . بسبب الوقت والجهد والتكلفة الكبيرة التي تحتاجها البيانات الضخمة لتحليلها ومعالجتها اضطر التقنيون على الاعتماد على أنظمة الذكاء الاصطناعي Artificial Intelligence التي لديها القدرة على التعلم والاستنتاج ورد الفعل على أوضاع لم تبرمج في الآلة باستخدام خوارزميات معقدة للعمل عليها، بالإضافة إلى استخدام تقنيات الحوسبة السحابية لإتمام عملها. عادة يكون المقصود به البيانات الضخمة هي البيانات التي تقاس بالبيتا بايت petabyte (ألف تيرا بايت) أو الايكسا بايت exabyte (مليون تيرابيات)؛ ووفقاً لــ IBM فإنها ابتداءاً من العام 2012 الميلادية فإننا يومياً ننشأ ما يقارب 2.5 كوينتيليون بايت من البيانات الضخمة (كوينتيليون هو الرقم واحد متبوعاً بثمانية عشرة (18)صفر ). و للمعلومية تمت اضافة كلمة Big Data الى قاموس Oxford ككلمة انجليزية مستحدثة. تصنيف البيانات الضخمة: كثير منا يعتقد بأن البيانات الضخمة تصنف وفقا للحجم فقط، في الحقيقة هي تصنف وفقا لمبدأ (3V's) و يتكون من: الحجم Volume: و هي حجم البيانات المستخرجة من مصدر ما، وهو ما يحدد قيمة وامكانات البيانات لكي تصنف من ضمن البيانات الضخمة؛ و قد يكون الخاصية الأكثر أهمية في تحليل البيانات الضخمة .كما أن وصفها بالضخمة لا يحدد كمية معينة؛ فكما ذكرنا آنفا بأن الحجم يقاس عادة بالبيتا بايت او بالإكسا بايت. و للمعلومية بحلول العام 2020 سيحتوى الفضاء الإلكتروني على ما يقرب من 40.000 ميتابايت من البيانات الجاهزة للتحليل واستخلاص المعلومات؛ ويقدر أن %90 من البيانات الموجودة في العالم اليوم قد استحدثت خلال السنتين الأخيرتين، بواسطة أجهزة وعلى أيدي بشر ساهم كلاهما في تزايد البيانات. التنوع Variety: و يقصد بها تنوع البيانات المستخرجة، والتي تساعد المستخدمين سواء كاموا باحثين أو محللين على اختيار البيانات المناسبة لمجال بحثهم و تتضمن بيانات مهيكلة في قواعد بيانات و بيانات غير مهيكلة تأتي من طابعها غير الممنهج، مثل: الصور ومقاطع وتسجيلات الصوت وأشرطة الفيديو والرسائل القصيرة وسجلات المكالمات وبيانات الخرائط (GPS)... وضيرها الكثير؛ وتتطلب وقتاً وجهداً لتهيئتها في شكل مناسب للتجهيز والتحليل. السرعة Velocity: و يقصد بها سرعة إنتاج واستخراج البيانات لتغطية الطلب عليها؛ حيث تعتبر السرعة عنصراً حاسماً في اتخاذ القرار بناء على هذه البيانات، وهو الوقت الذي نستغرقه من لحظة وصول هذه البيانات إلى لحظة الخروج بالقرار بناء عليها. سابقا كانت الشركات تستخدم لمعالجة مجموعة صغيرة من البيانات المخزنة في صورة بيانات مهيكلة في قواعد بيانات عملية تسمى بال ” Batch Process“ حيث كان يتم تحليل كل مجموعة بيانات واحدة تلو الأخرى في انتظار وصول النتائج. مع الازدياد الضخم في حجم البيانات وسرعة تواترها أصبحت الحاجة أكثر إلحاحا الى نظام يضمن سرعة فائقة في تحليل البيانات الضخمة في الوقت اللحظي “Real Time“ أو سرعة تقارب الوقت اللحظي. أدت تلك الحاجة الى ابتكار تقنيات وحلول مثل Apache و SAP HANA و Hadoop وغيرها الكثير. كما أضيف مؤخراً لتلك المبادئ الثلاث وفقاً لخصائص البيانات الضخمة "مبدأ صحة البيانات الضخمة": فيمثل التمتع بالقدرة على تقييمها عنصراً جوهرياً في وضع الأساس لاتخاذ القرارات الهامة بناءً عليها. ويجب الأخذ بالاعتبار تباين هذه البيانات وعدم التأكد من صحتها في عملية اتخاذ القرار. مصادر البيانات الضخمة: قامت اللجنة الاقتصادية لأوروبا، بتقديم تقرير بعنوان ”ماذا تعنيه البيانات الضخمة للإحصاءات الرسمية“ آذار مارس و قد أوردت فيه تصنيفا لمصادر البيانات الضخمة على النحو التالي: المصادر الناشئة عن إدارة أحد البرامج، سواء كان برنامجا حكوميا أو غير حكومي، كالسجلات الطبية الإلكترونية وزيارات المستشفيات وسجلات التأمين والسجلات المصرفية وبنوك الطعام. المصادر التجارية أو ذات الصلة بالمعاملات، الناشئة عن معاملات بين كيانين، على سبيل المثال معاملات البطاقات الائتمانية والمعاملات التي تجرى عن طريق الإنترنت بوسائل منها الأجهزة المحمولة. مصادر شبكات أجهزة الاستشعار، على سبيل المثال، التصوير بالأقمار الصناعية، وأجهزة استشعار الطرق، وأجهزة استشعار المناخ. مصادر أجهزة التتبع، على سبيل المثال تتبع البيانات المستمدة من الهواتف المحمولة والنظام العالمي لتحديد المواقع. مصادر البيانات السلوكية، على سبيل المثال، مرات البحث على الإنترنت عن منتج أو خدمة ما أو أي نوع آخر من المعلومات، ومرات مشاهدة إحدى الصفحات على الإنترنت. مصادر البيانات المتعلقة بالآراء، على سبيل المثال، التعليقات على وسائط التواصل الاجتماعي. أمثلة من الواقع على البيانات الضخمة: لدى واتس آب أكثر من مليار مستخدم، و يتم تداول اكثر من 42 مليار رسالة و حوالي 1.6 مليار صورة بشكل يومي. فيسبوك تتعامل مع أكثر من 50 مليار صورة من مستخدميها. جووجل Google تتعامل مع حوالي 100 مليار عملية بحث في الشهر. أهمية البيانات الضخمة: للبيانات الضخمة اهمية عالية فهي تقدم ميزة تنافسية عالية للشركات اذا استطاعت الاستفادة منها ومعالجتها لأنها تقدم فهما أعمق لعملائها ومتطلباتهم ويساعد ذلك على اتخاذ القرارات المناسبة و الملائمة داخل الشركة بطريقة أكثر فعالية و ذلك بناء على المعلومات المستخرجة من قواعد بيانات العملاء وبالتالي زيادة الكفاءة والربح وتقليل الخسائر. فباستخدام تقنيات و أدوات تحليل البيانات الضخمة استطاعت وول مارت تحسين نتائج البحث عن منتجاتها عبر الأنترنت بنسبة 10-15% بينما في تقرير لماكينزى-وهى شركة رائدة في مجال استشارات الاعمال- ان القطاع الصحي بالولايات المتحدة لو كان يستخدم تقنيات تحليل البيانات الضخمة بفاعليه وكفاءه لكان قد أنتج أكثر من 300 مليون دولار أمريكى كفائض سنوى من ميزانيه الصحة ثلثيها بسبب خفض تكاليف الانفاق بنسبة 8%(1). الخاتمة: في زمننا هذا نشهد انفجارا ضخما في البيانات فتحليل و معالجة هذه البيانات يزيد بشكل رئيسي في فهم و استيعاب متطلبات العملاء و بالتالي زيادة الكفاءة و الانتاجية و تقليل الخسائر بالنسبة للشركات. إلا أن هنالك العديد من التحديات والمعوقات التي تعيق استخدام البيانات الضخمة أو التوسع في استخدامها والتي ممكن تناولها في مقال آخر بإذن الله تعالى . ومع مرور الوقت والتقدم التكنولوجي، فمن المتوقع إحراز تقدم كبير فيما يتعلق بمعالجة تحديات ومعوقات استخدام البيانات الضخمة بشكل أوسع. و في النهاية اتمنى ان تكون هذه المقالة قد لاقت اعجابكم و أن تثري المحتوى العربي على الانترنت. المصادر: 1- Mckinsey&Company: Big Data: The next frontier for innovation,competition and productivity. May 2011 تم ترقية هذا الطرح المميز الى صفحة المقالات

عالم البرمجة

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