‏إظهار الرسائل ذات التسميات google. إظهار كافة الرسائل
‏إظهار الرسائل ذات التسميات google. إظهار كافة الرسائل

الاثنين، 6 سبتمبر 2010

جوجل كروم (ما وراء الكواليس) - جزء 1



في بداية ظهور المتصفحات , كانت تُستخدم لعرض صفحات الانترنت , و لكن اليوم ظهرت تطبيقات تعمل على شبكة الانترنت من خلال المتصفح مثل تطبيقات الفيديو و الدردشة و العاب الانترنت و غيرها الكثير من التطبيقات التي لم تكن موجودة عند بداية ظهور متصفحات الانترنت لأول مرة.

و مع انتقال الكثير من المهام التي يقوم بها المستخدم الى شبكة الانترنت مثل ارسال البريد الالكتروني و معالجة النصوص على شبكة الانترنت و في كلتا الحالتين قد تكون هناك معلومات مهمة بالنسبة للمستخدم و التي لا تحتمل حدوث أي خطأ أو توقف غير متوقع للمتصفح أثناء العمل عليه قد يؤدي الى ضياع المعلومات , فأصبح هناك حاجة ملحة لأن يكون المتصفح أكثر استقرارا و ثباتا.

كذلك السرعة في التشغيل و الاداء و عرض الصفحات أمر مهم جدا بالنسبة لأي متصفح . و كون العنصر الاساسي الذي تقوم عليه أغلب التطبيقات التي تعمل على شيكة الانترنت (مثل بريد gmail ) هو لغة جافا سكريبت JavaScript أصبح هناك ضرورة لايجاد حلول حتى يصبح تنفيذ هذه اللغة أسرع .

سنذكر بشيء من التفصيل كيف قام جوجل كروم بتوفير هذه الميزات :

1- الاستقرار و تعدد العمليات Stability and multi process architecture

تكمن المشكلة الاساسية في أغلب المتصفحات كونها "أحادية العملية" single process ! , وهذا يعني أنه يلا يمكن تنفيذ سوى مهمة واحدة في نفس اللحظة , فعلى سبيل المثال : لو أن هناك كود جافا سكريبت بتم تنفيذه سيبقى المتصفح في حالة خمول بدون اي اداء اي مهمة اخرى حتى ينتهي من تنفيذ الكود وارجاع النتائج , و من أجل تفادي هذه المشكلة قام المطورون بانشاء مكتبات برمجية بحيث تكون احادية الاتجاه "Asynchronous API".

الحل البديهي الذي ممكن ان نخرج به هو تقسيم العملية الى عدة (ثريد) threads - لم أدر ما هو معناها بالعربية - هذا ممكن !

ولكن لما لا يكون لدينا عدة عمليات multi-process , كل عملية لديها حصتها من الذاكرة الخاصة بها , و لديها نسخة خاصة بها من المتغيرات وهياكل البيانات بحيث تعمل كل عملية على حدى وبشكل منفصل بحيث لا يؤثر أداء اي عملية على الاخرى (processes isolation) , اذن لدينا أصبح عدة عمليات كل عملية يمكن تمثيلها بتوبيب tab في المتصفح. و عندها أصبح بالامكان تنفيذ كود الجافا سكريبت بدون تعطيلك عن القيام بالمهام الاخرى :)
نفس الشيء في حال حدوث أي مشكلة أو خطأ فانه لن يتم اغلاق كل المتصفح , ولكن سيتم اغلاق فقط التبويب tab الذي حدثت فيه المشكلة(من خلال انهاء العملية الخاصة به) مع بقاء باقي المتصفح يعمل بسلام.

قد يتبادر للبعض ان هذا سيؤدي الى استهلاك أكبر للذاكرة بحيث ان كل عملية لها المساحة الخاصة بها من الذاكرة و لكن في الواقع هذا غير صحيح .. ففي المتصفحات التقليدية احادية العلمية عند انشاء توبيب جديد tab فانه يأخذ حصة من مساحة الذاكرة المحجوزة للعملية التي تشغل النتصفح, ولكن عند اغلاق هذا التبويب فانه لا يتم تحرير المساحة الخاصة به من الذاكرة فاما انا تبقى مساحة غير مستخدمة ولا يوجد مؤشر يشير اليها أو يوجد مساحة لا يمكن الوصول اليها (لا يمكن تحرير المساحات المفرغة الا عند انتهاء العملية ككل ),, ففي هذه الحالة المساحة الناتجة عن اغلاق التوبيبات لا يمكن اعادة استخدامها لتشغيل تبيويات جديدة , و مع مرور الوقت سيضطر نظام التشغيل الي توسيع الحصة المخصصة للمتصفح من ذاكرة الحاسوب , و هذا بالتأكيد سيؤدي الى بطء في البرنامج و نظام التشغيل ككل (و بالتأكيد اغلاق التبويبات لن يحل المشكلة أبدا, بل سيزيدها سوءا !!) الحل هو قتل العملية وتحرير الذاكرة الخاصة بها و البدء من جديد !

ولكن بالطريقة التي يعمل بها الكروم فانه قدم الحل الامثل لهذه المشكلة بتعامله مع كل تبويب على انه عملية مستقلة فعند اغلاق التبويب فانه ببساطة سيتم تحرير حصتها من الذاكرة لتكون متاحة للاستخدام لاي عملية اخرى (قد تكون تبويب أخر) . تماما كما في انظمة التشغيل اصبح بامكان متصفح كروم من خلال "مدير المهام Google chrome task manger" الخاص به , أصبح بالامكان مراقبة المواقع التي يتم العمل عليها و أخذ احصائيات عن مقدار استهلاك كل موقع من الذاكرة و سرعة الانترنت و من المعالج , و هذا يعطي مرونة كبيرة في التحكم و ادارة موارد النظام بشكل فعال. و عندها تستطيع القاء اللوم على الموقع الذي يستحق ذلك و الذي يسرف في استهلاك موارد النظام (Placing blame where blame belongs ) :) :)


يتبع ,,

السبت، 28 أغسطس 2010

تطبيقي الأول على نظام الأندرويد


بسم الله ,

اليوم ان شاء الله سوف أتحدث عن أولى تجاربي - التي كتب لها ان تنجح بفضل الله -لبناء تطبيق يعمل على نظام الاندوريد , فقد كانت هناك محاولات سابقة و لكنها كانت فقط للتجريب والتعود على استخدم الادوات المطلوبة للتطوير برمجيات على هذه المنصة ..

"ملاحظة مهمة : لقد افترضت عند كتاتبتي لهذه التدوينة ان لدى القارئ الحد الأدنى من المعرفة حول كيفية اعداد بيئة التطوير الخاصة بنظان الاندرويد, وان لديه معلومات حول الملفات و المجلدت التي يتم انشاؤها عند انشاء مشروع جديد , فبالتالي بدأت من نقطة متقدمة بدون شرح هذه الأمور , ولكن انوه انه سأعود و أتطرق لهذه المواضيع بالتفصيل الممل لاحقا "

فلنبدأ عل ىبركة الله , التطبيق هو عبارة عن ألة حاسبة و حتى يكون المووضع سهل الفهم , سيتم تقسيم الشرح الى 3 أجزاء رئيسية :
الاول : يشرح كيف نحدد الاطار العام الذي سوف يحكم ترتيب العانصر في الواجهة.
الثاني : ربط عناصر الواجهات (من ملف main.xml ) مع اكواد الجافا.
الثالث : تنفيذ العمليات الخاصة بالالة الحاسبة

اولا : سنبدأ بتصميم واجهات البرنامج , و التي كما قلنا فان نظام الاندرويد يقوم باستخدام ملف xml من اجل تكوين عناصر الواجهات (مع وجود طريقة اخرى من خلال كود الجافا). ولكن هذه الطريقة هي الأفضل .

الملف المسؤول عن تصميم الواجهات يطلق عليه main.xml , و للوصول اليع نذهب الى مجلد المشروع , و من ثم الى مجلد res ومن ثم مجلد layout فنجد المف بداخله , سوف نضع فيه أكواد xml التي سوف تعطينا الشكل التالي :




من الصورة نلاحظ ان العنصر الاساسي الذي يحتوي كل العناصر هو LinearLayout والذي يقوم بتريتب العناصر في عمود واحد او سطر واحد (جنبا الى جنب ) في مثالنا هذا استخدمنا الترتيب العمودي للعناصر , بداخله يحتوي على 3 عناصر أخرى : الاول هو EditText لعرض القيم , والعنصر الثاني هو Button والعنصر الثالث هو TableLayout والذي يمثل الحاوية لمجموعة الأزرار , بحيث يتم التعامل معه على مجموعة من السطور TableRow كل سطر يحتوي على 4 Button و هي الطريقة الانسب لعرضهم هو استخدام الجدول, بامكانك نسخ الكود التالي في الملف خاصتك لتحصل على الشكل الظاره في الصورة أعلاه :


<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<EditText
android:id="@+id/txtDisplay"
android:layout_width="320px"
android:layout_height="130px">
</EditText>
<Button
android:id="@+id/btnReset"
android:layout_width="fill_parent"
android:layout_height="60px"
android:text="Clear Screen"

></Button>

<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:stretchColumns="1">

<TableRow>
<Button
android:id="@+id/btn7"
android:layout_width="80px"
android:layout_height="60px"
android:text="7"

></Button>
<Button
android:id="@+id/btn8"
android:layout_width="80px"
android:layout_height="60px"
android:text="8"
></Button>
<Button
android:id="@+id/btn9"
android:layout_width="80px"
android:layout_height="60px"
android:text="9"
>
</Button>
<Button
android:id="@+id/btnDiv"
android:layout_width="80px"
android:layout_height="60px"
android:text="/"
>
</Button>
</TableRow>

<TableRow>
<Button
android:id="@+id/btn4"
android:layout_width="80px"
android:layout_height="60px"
android:text="4"

></Button>
<Button
android:id="@+id/btn5"
android:layout_width="80px"
android:layout_height="60px"
android:text="5"
></Button>
<Button
android:id="@+id/btn6"
android:layout_width="80px"
android:layout_height="60px"
android:text="6"
>
</Button>
<Button
android:id="@+id/btnMulti"
android:layout_width="80px"
android:layout_height="60px"
android:text="*"
>
</Button>
</TableRow>

<TableRow>
<Button
android:id="@+id/btn1"
android:layout_width="80px"
android:layout_height="60px"
android:text="1"

></Button>
<Button
android:id="@+id/btn2"
android:layout_width="80px"
android:layout_height="60px"
android:text="2"
></Button>
<Button
android:id="@+id/btn3"
android:layout_width="80px"
android:layout_height="60px"
android:text="3"

>
</Button>
<Button
android:id="@+id/btnSub"
android:layout_width="80px"
android:layout_height="60px"
android:text="-"
>
</Button>
</TableRow>
<TableRow>
<Button
android:id="@+id/btnFloat"
android:layout_width="80px"
android:layout_height="60px"
android:text="."

></Button>
<Button
android:id="@+id/btn0"
android:layout_width="80px"
android:layout_height="60px"
android:text="0"
></Button>
<Button
android:id="@+id/btnEqual"
android:layout_width="80px"
android:layout_height="60px"
android:text="="

>
</Button>
<Button
android:id="@+id/btnAdd"
android:layout_width="80px"
android:layout_height="60px"
android:text="+"
>
</Button>
</TableRow>

</TableLayout>
</LinearLayout>


ثانيا : سنقوم باستدعاء عناصر واجهة الرنامج و التي تم تعريفه مفي ملف main.xml كم رأينا سابقا , و تم انشاء علامات مرجعية اليهم في ملف R.java الموجود بداخل المجلد gen , و سيتم الاستعداء باستخدان المعرف (id) لكل عنصر كما في الكود التالي (والذي سيتم كتابته في الملف المصدري الرئيسي للبرنامج )


private void initControl()
{
btn0=(Button)findViewById(R.id.btn0);
btn1=(Button)findViewById(R.id.btn1);
btn2=(Button)findViewById(R.id.btn2);
btn3=(Button)findViewById(R.id.btn3);
btn4=(Button)findViewById(R.id.btn4);
btn5=(Button)findViewById(R.id.btn5);
btn6=(Button)findViewById(R.id.btn6);
btn7=(Button)findViewById(R.id.btn7);
btn8=(Button)findViewById(R.id.btn8);
btn9=(Button)findViewById(R.id.btn9);
btnAdd=(Button)findViewById(R.id.btnAdd);
btnMulti=(Button)findViewById(R.id.btnMulti);
btnSub=(Button)findViewById(R.id.btnSub);
btnDiv=(Button)findViewById(R.id.btnDiv);
btnFloat=(Button)findViewById(R.id.btnFloat);
btnEqual=(Button)findViewById(R.id.btnEqual);
txtDisplay=(EditText)findViewById(R.id.txtDisplay);
btnReset=(Button)findViewById(R.id.btnReset);

setListener(btn0); setListener(btn1);
setListener(btn2); setListener(btn3);
setListener(btn4); setListener(btn5);
setListener(btn6); setListener(btn7);
setListener(btn8); setListener(btn9);
setListener(btnFloat);


setOperatorListener(btnAdd); setOperatorListener(btnSub);
setOperatorListener(btnMulti); setOperatorListener(btnDiv);
setOperatorListener(btnEqual); setOperatorListener(btnReset);


}

بالنسبة للدالتين setListener و setOperatorListener اضافة listener لكل زر موجود في الواجهة كي يتم التعامل معه , و التنصت على الحدث الذي يحدث عليه (click) من أجل تنفيذ عملية معينة .. كما نرى في الاسفل الكود الكامل الخاص بالبرنامج بما فيهم الكود الخاص هاتين الدالتين , و المسؤول عن التعرف على الزر الذي تم الضغط عليه و اجراء عملية معينة بناء على ذلك ...



package com.android;

import android.app.Activity;
import android.os.Bundle;
import java.lang.String;
import android.widget.Button;
import android.widget.EditText;
import android.view.View;
public class tipcalc extends Activity {

public static String bufferString;
public static String operator;
private Button btn0,btn1,btn2,btn3,btn4,btn5,btn6,btn7,btn8,btn9,btnAdd,btnSub,btnMulti,btnDiv,btnFloat,btnEqual,btnReset;
private EditText txtDisplay;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
initControl();
}

private void initControl()
{
btn0=(Button)findViewById(R.id.btn0);
btn1=(Button)findViewById(R.id.btn1);
btn2=(Button)findViewById(R.id.btn2);
btn3=(Button)findViewById(R.id.btn3);
btn4=(Button)findViewById(R.id.btn4);
btn5=(Button)findViewById(R.id.btn5);
btn6=(Button)findViewById(R.id.btn6);
btn7=(Button)findViewById(R.id.btn7);
btn8=(Button)findViewById(R.id.btn8);
btn9=(Button)findViewById(R.id.btn9);
btnAdd=(Button)findViewById(R.id.btnAdd);
btnMulti=(Button)findViewById(R.id.btnMulti);
btnSub=(Button)findViewById(R.id.btnSub);
btnDiv=(Button)findViewById(R.id.btnDiv);
btnFloat=(Button)findViewById(R.id.btnFloat);
btnEqual=(Button)findViewById(R.id.btnEqual);
txtDisplay=(EditText)findViewById(R.id.txtDisplay);
btnReset=(Button)findViewById(R.id.btnReset);

setListener(btn0); setListener(btn1);
setListener(btn2); setListener(btn3);
setListener(btn4); setListener(btn5);
setListener(btn6); setListener(btn7);
setListener(btn8); setListener(btn9);
setListener(btnFloat);


setOperatorListener(btnAdd); setOperatorListener(btnSub);
setOperatorListener(btnMulti); setOperatorListener(btnDiv);
setOperatorListener(btnEqual); setOperatorListener(btnReset);


}

private void setListener(final Button btn)
{
btn.setOnClickListener(new Button.OnClickListener()

{
public void onClick(View v)
{
String value=btn.getText().toString();
txtDisplay.append(value);
}
}
);
}

private void setOperatorListener(final Button btn)
{
btn.setOnClickListener(new Button.OnClickListener()

{
tipcalc t=new tipcalc();
public void onClick(View v)
{
String value_operator=btn.getText().toString();
if(value_operator.equals("+")||value_operator.equals("-")||value_operator.equals("*")||value_operator.equals("/"))
{
t.operator=value_operator;
t.bufferString=txtDisplay.getText().toString();
txtDisplay.setText("");
}
else if(value_operator.equals("="))
{


double val1=Double.parseDouble(t.bufferString),val2=Double.parseDouble(txtDisplay.getText().toString());
double result=0.0;

if(t.operator.equals("+"))result=val1+val2;
else if(t.operator.equals("-"))result=val1-val2;
else if(t.operator.equals("*"))result=val1*val2;
else if(t.operator.equals("/"))result=val1/val2;

txtDisplay.setText(""+result);


}
else if(value_operator.equals("Clear Screen"))
{
txtDisplay.setText("");
t.bufferString="";
t.operator="";
}

//tipcalc.bufferString=txtDisplay.getText().toString();
}
}
);
}


}




في النهاية اتنمى ان يكون الشرح واضحا , رغم انني اعتقد انه كان موجزا و غير مفصل, لكن أن كان يوجد أي استفسار سأكون سعيد بالاجابة عليه .. :) :)