استفاده از Glide به جای picasso

یک سالی بود در اندروید برای load عکس ها از picasso استفاده می کردم.مدتی قبل به این نتیجه رسیدم بهتر است به جای picasso از Glide استفاده کنم.قبل استفاده از Glide ، این مقاله را مطالعه کردم.

دلایل مشخصی برای این تصمیم داشتم که سعی کردم آن ها را توضیح دهم:

از نظر نحوه استفاده picasso  با Glide تفاوت چندانی نمی کند و به راحتی کد های شما قابل تبدیل است:
Picasso

Picasso.with(context)
    .load("http://inthecheesefactory.com/uploads/source/glidepicasso/cover.jpg")
    .into(ivImg);

Glide

Glide.with(context)
    .load("http://inthecheesefactory.com/uploads/source/glidepicasso/cover.jpg")
    .into(ivImg);

به صورت پیش فرض Glide از فرمت RGB_565 استفاده می کند که نسبت به picasso که از ARGB_8888 استفاده می کند دارای کیفیت کمتری است.البته این مقدار را می توان تغییر داد.ولی اگر به میزان مصرف رم توجه کنید متوجه خواهید شد که ارزش دارد از فرمت پایین تر استفاده کنید.

حال اگر تصمیم بگیرید از ARGB_8888 نیز استفاده کنید باز می توان دید که Glide بهتر عمل خواهد کرد:

در زمان تغییر سایز عکس، picasso همه عکس را در رم لود می کند و سپس از طریق GPU سایز عکس را تغییر میدهد.این در حال است که Glide دقیقا سایز مورد نظر را در رم لود می کند و این کار باعث مصرف رم کمتر می شود.

برای کش کردن عکس روی گوشی picasso عکس کامل را در حافظه گوشی ذخیره می کند.این درحالی است که Glide عکس کوچک شده را کش می کند.البته این رفتار را نیز میتوان تغییر داد.

Glide در زمان نمایش عکس ها سریعتر عمل می کند:

Glide

Glide توانایی نمایش گیف را دارد:

برای اطلاعات دقیق تر می توانید به گیت هاب پروژه سر بزنید.

معرفی library های مفید اندروید

پیش نوشت:از اونجایی که مکانیزم خاصی برای به اشتراک گذاری لینک های مفید ندارم , تصمیم گرفتم اگر منبع و یا سایت خوبی دیدم به صورت یک پست مستقل معرفی کنم و به سایت اصلی لینک بدم.

اگر بخواهید به صورت حرفه ای با اندروید کار کنید libraryهای بسیار مفیدی توسط سایر برنامه نویسان ایجاد شده است که می توانید از آن ها استفاده کنید.برای دیدن لیست کامل این کتابخانه ها روی این لینک کلیک کنید.

Name Description
Retrofit A type-safe REST client for Android which intelligently maps an API into a client interface using annotations.
Glide A powerful image downloading and caching library for Android.
ButterKnife Using Java annotations, makes Android development better by simplifying common tasks.
Parceler Android Parcelable made easy through code generation
IcePick Android Instance State made easy
LeakCanary Catch memory leaks in your apps
Espresso Powerful DSL for Android integration testing
Robolectric Efficient unit testing for Android

 

lifecycle یک Activity

همانطور که در پستهای قبلی به lifecycle یک activity اشاره کردم,طول عمر یک activity در واقع از زمان ایجاد آن activity تا زمان حذف آن activity توسط سیستم و یا کاربر ادامه دارد.activity به ازای کارهایی که کاربر با صفحه انجام می دهد ممکن است وضعیتش به وضعیت های مختلف تغییر کند.برای هر وضعیت یک callback داریم که می توانیم از callbackها برای انجام یک سری کارها استفاده کنیم.کد زیر پیاده سازی کننده تمام callback های مهم در lifecycle یک activity است.

public class ExampleActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // The activity is being created.
    }
    @Override
    protected void onStart() {
        super.onStart();
        // The activity is about to become visible.
    }
    @Override
    protected void onResume() {
        super.onResume();
        // The activity has become visible (it is now "resumed").
    }
    @Override
    protected void onPause() {
        super.onPause();
        // Another activity is taking focus (this activity is about to be "paused").
    }
    @Override
    protected void onStop() {
        super.onStop();
        // The activity is no longer visible (it is now "stopped")
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        // The activity is about to be destroyed.
    }
}

همچنین شکل زیر نشان دهنده lifecycle یک activity  است.توجه کنید که مستطیل ها درواقع همان callbackهایی هستند که در کد بالا پیاده سازی کرده ایم.
activity-lifecycle

کل طول عمر یک activity بین متدهای onCreate() و onDestroy() خلاصه شده است.در متدها onCreate() ما باید کارهای اولیه مربوط به راه اندازی یک activity را انجام دهیم و همچنین در onDestroy() کارهای مربوط به آزاد سازی منابع را انجام دهیم.برای مثال اگر می خواهیم یک thread برای انجام عملیات دانلود یک فایل از اینترنت را اجرا کنیم باید آن را onCreate() اجرا کنیم و در onDestroy() آن thread را منوقف کنیم.
کل زمانی که کاربر می تواند activity را ببیند و با آن کار کند بین متدهای onStart() و onStop() خلاصه شده است.زمانی که onStop() صدا زده می شود activity دیگر برای کاربر قابل مشاهده نیست.
طول عمر زمانی کهactivity بالاتر از باقی activityها قرار دارد و فوکس بر روی آن است بین onResume() و onPause() است.onPause زمانی صدا زده می شود که مثلا دستگاه به خواب رفته یا یک دیالوگ باز شده است.برای این که ما به صورت مکرر ممکن است بین این دو وضعیت سوئیج کنیم بنابراین نیاز است کارهای سنگینی در این دو متد انجام ندهیم که موجب کندی نشود.

Activity #2

اجرا کردن یک Activity

برای اجرای Activity به راحتی می توانید یک Intent ایجاد کنید و مشخص کنید که چه activity را می خواهید اجرا کنید.همچنین می توانید به intent مقداری داده اضافی برای اجرا شدن صحیح activity مورد نظر ارسال کنید.سپس شما باید متد startActivity() را صدا بزنید.
به کد زیر توجه کنید:

Intent intent = new Intent(this, SignInActivity.class);
startActivity(intent);

شرایطی وجود دارد که نیاز دارید کاری را انجام دهید که برنامه شما قادر به انجام آن کار نیست در این حالت در صورتیکه این امکان توسط برنامه دیگر فراهم شده است می توانید از آن برنامه ها استفاده کنید.برای مثال زمانیکه شما می خواهید یک ایمیل ارسال کنید نیاز نیست خودتان کدهای مربوط به آن را بنویسید و می توانید از intent خاصی بدین منظور استفاده کنید.به کد زیر دقت کنید:

Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);
startActivity(intent);

Intent.EXTRA_EMAIL مشخص کننده آدرسی است که می خواهید به آن ایمیل ارسال کنید.

اجرا کردن یک activity برای دریافت نتیجه

ممکن است شما نیاز داشته باشید تا یک activity را صدا بزنید و نتیجه را از آن activity دریافت کنید.در این صورت شما activity خود را به وسیله startActivityForResult() باید اجرا کنید.برای گرفتن نتیجه نیاز است callbackی به اسم onActivityResult() را پیاده سازی کنید:

private void pickContact() {
    // Create an intent to "pick" a contact, as defined by the content provider URI
    Intent intent = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI);
    startActivityForResult(intent, PICK_CONTACT_REQUEST);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // If the request went well (OK) and the request was PICK_CONTACT_REQUEST
    if (resultCode == Activity.RESULT_OK && requestCode == PICK_CONTACT_REQUEST) {
        // Perform a query to the contact's content provider for the contact's name
        Cursor cursor = getContentResolver().query(data.getData(),
        new String[] {Contacts.DISPLAY_NAME}, null, null, null);
        if (cursor.moveToFirst()) { // True if the cursor is not empty
            int columnIndex = cursor.getColumnIndex(Contacts.DISPLAY_NAME);
            String name = cursor.getString(columnIndex);
            // Do something with the selected contact's name...
        }
    }
}

درکد بالا نحوه انتخاب یک آیتم از دفترچه تلفن کاربر را مشاهده می کنید.

از بین بردن یک Activity

اگر نیاز داشتید یک activity را به صورت صریح shut down کنید از متد finish() می توانید استفاده کنید.البته در مطالب بعدی متوجه خواهید شد که نیاز نیست خودتان دستی این کار را انجام دهید و سیستم اندروید به صورت اتوماتیک این کار را برای ما انجام خواهد داد.

Activity #1

در پست نگاه اجمالی به یک برنامه اندروید component های اصلی سازنده یک برنامه اندروید را به صورت مختصر معرفی کردم.در این پست قصد دارم به صورت جزئی تر به Activity در اندروید بپردازم.

Activity یک ازcomponent های اصلی یک برنامه اندروید که فراهم کننده رابط کاربری است که کاربر می تواند به وسیله آن با سیستم ارتباط برقرار کند.در صورتیکه برنامه نویس وب بوده باشید یک Activity را می توانید مانند یک صفحه html در نظر بگیرید.

هر برنامه معمولا شامل چندین Activity است که که بدون وابستگی به یکدیگر با هم ارتباط دارند.همچنین اغلب در یک برنامه یک activity به عنوان activity اصلی شناخته می شود و مشخص کننده اولین صفحه ای است که کاربر پس از ورود به برنامه با آن روبرو می شود.

هر activity می تواند یک activity دیگر را اجرا کند در این حالت  activity جدید فعال می شود و activity قبلی به حالت stop شده توسط سیستم در یک stack به اسم back stack نگه داری می شود.به عبارتی زمانی کهactivity جدید اجرا شود سیستم آنactivity را درون stack اضافه می کند. هر زمان کاربر کارش با activity جدید تمام شد و دکمه back را فشار داد سیستم آن activity را از stack بیرون می کشد و  از بین (destroyed)می برد.در این حالت activity قبلی دوباره شروع به کار می کند.

به ازای هر تغییر وضعیت در activity یک callback صدا زده می شود.برای مثال در زمانی که activity به حالت stopped می رود یک callback اجرا می شود.در هر callback ما می توانیم کارهای مربوط به آن حالت را انجام دهیم برای مثال دروضعیت stopped باید از شر اشیا بزرگ (large objects) خلاص شویم و همچنین  کارهای سنگین مثل کارهای شبکه و دیتابسی را متوقف کنیم.همچنین به طور مثال اگر وضعیت activity به وضعیت resume تغییر کرد باید کارهای لازم در آن وضعیت را انجام دهیم.

ساخت یک Activity

برای ساخت یک activity نیاز دارید تا کلاسی بسازید که از کلاس پایه Activity به ارث برده است.همچنین نیاز است که یک سری از callback هایی را که سیستم در هنگام تغییر وضعیت activity أن ها را صدا می زند را پیاده سازی کنید.دو  callback اصلی عبارت انداز :

onCreate():این متد را سیستم زمانی که activity ما ساخته شد صدا می زدند در این متد باید کارهای اساسی مثل تعیین رابط کاربری یک activity به وسیله setContentView() انجام شود.

onPause():این متد زمانی که کاربر از activity جاری خارج می شود صدا زده می شود.البته صدا زده شدن این متد به این معنی نیست که activity از بین می رود.کارهایی مثل نگهداری و ذخیره اطلاعات اساسی در این متد می تواند انجام شود زیرا ممکن است کاربر دیگر به این activity باز نگردد و داده های آن از بین برود.

پیاده سازی رابط کاربری

هرactivity دارای یک رابط کاربری و هر رابط کاربری دارای viewهای متفاوتی است.

هر رابط کاربری از ساختار سلسله مراتبی تعدادی از viewها که از کلاس View به ارث برده اند ایجاد شده است.هر view یک قسمت مشخص مستطیلی شکل را از یک activity اشغال می کند که کاربر می تواند به وسیله آن با برنامه ارتباط برقرار کند.برای مثال دکمه یک view است که کاربر برای انجام دادن یک کار مشخص روی آن کلیک میکند.

اندروید شامل یک سری از viewهای از پیش ساخته شده برای استفاده در برنامه های مختلف است.برای مثال Widgetهایی مانند text field ,checkbox و image.همچنین شامل Layoutهای متفاوتی است که می توانند سامان دهنده viewهای متفاوتی باشند.Layoutها از کلاس ViewGroup مشتق شده اند.

همچنین در صورت نیاز می توانیم از کلاس های View و  ViewGroup به ارث ببریم و viewهای مورد نیاز خودمان را بسازیم.

نحوه تعریفactivity در manifest

برای دسترسی سیستم به activity های برنامه به منظور اجرای آن activityها نیاز است تا آنها را در فایل manifest تعریف کنیم.بدین منظور مانند زیر عمل می کنیم:

<manifest ... >
  <application ... >
      <activity android:name=".ExampleActivity" />
      ...
  </application ... >
  ...
</manifest >

خواص متفاوتی وجود دارند که در تگ activity می توانیم تعریف کنیم.برای مثال می توانیم برای activity خود یک label در نظر بگیریم و یا مثلا یک icon مشخص کنیم ولی هیچ کدام از این ها برای تعریف activity در فایل manifest اجباری نیستند.به غیر از android:name که نام activity است باید تعریف شود.
بعد از اینکه برنامه را منتشر کردیم نباید نام activity را تغییر دهیم زیرا ممکن است باعث از کار افتادن برنامه بعد از آپدیت برنامه توسط کاربرها شود.یک سری تغیرات را نباید بعد از پابلیش برنامه انجام دهیم.لیست آن ها را می توانید در اینجا مشاهده کنید.

استفاده ازintent filterها

یک activity ممکن است شامل چند intent filter مختلف باشد و هر intent filter مشخص کننده نحوه اجرا کردن این activity توسط سایر componentها است.اگر برنامه ای که می نویسید قرار نیست توسط سایر برنامه های دیگر اجرا شود بنابراین نیاز نیست که intent filter خاصی به غیر از android.intent.action.MAIN که برای مشخص کننده نقطه ورود به برنامه هست نوشته شود.

دریافت implicit intent

به کمک implicit intent می توانیم از سایر برنامه ها intent دریافت کنیم.بدین جهت برای هر component در فایل manifest می توانیم تعدادی <intent-filter> تعریف کنیم.هر intent filter مشخص کننده نوع intentهایی است که برنامه ما با توجه به action, data, و  category می تواند قبول کند.سیستم تنها در صورتی یک intent را به برنامه ما ارسال می کند که با یک intent filter همخوانی داشته باشید.

نکته:explicit intent ها بدون توجه به intent filter تحویل داده می شوند.

هر component باید intent filterهای مجزایی به ازای کارهایی که می تواند انجام دهد تعریف کند.به عنوان مثال اگر یک activity در یک برنامه گالری , عکس را نمایش می دهد و هم عکس را ویرایش می کند نیاز دارد که دو intent filter تعریف کند.یکی برای نمایش و یکی برای ویرایش و زمانی که activity باز شد با توجه به intent ارسالی رفتار مناسب را برگزیند.

مثال زیر نمایش دهنده تعریف یک intent filter برای یک activity است:

<activity android:name="ShareActivity">
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="text/plain"/>
    </intent-filter>
</activity>

برای اینکه سیستم اندروید یک intent را به برنامه تحویل دهد باید action,categoryو data باintent filter تعریفی ما مطابقت داشته باشد و حتی اگر یکی از آنها با intent filter همخوانی نداشت intent به برنامه ارسال نمی شود.
نکته:برای دریافت implicit intents نیاز است category به اسم CATEGORY_DEFAULT تعریف شود.در غیر این صورت ما implicit intentی دریافت نخواهیم کرد.
حال به مثال زیر دقت کنید:

<activity android:name="MainActivity">
    <!-- This activity is the main entry, should appear in app launcher -->
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

<activity android:name="ShareActivity">
    <!-- This activity handles "SEND" actions with text data -->
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="text/plain"/>
    </intent-filter>
    <!-- This activity also handles "SEND" and "SEND_MULTIPLE" with media data -->
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <action android:name="android.intent.action.SEND_MULTIPLE"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="application/vnd.google.panorama360+jpg"/>
        <data android:mimeType="image/*"/>
        <data android:mimeType="video/*"/>
    </intent-filter>
</activity>

MainActivity که به عنوان activity اول تعریف شده و به عنوان نقطه ورودی برنامه محسوب می شود. ACTION_MAIN مشخص کننده این موضوع است و همچنین مشخص می کند که این activity انتظار دریافت داده خاصی به وسیله intent را ندارد.CATEGORY_LAUNCHER مشخص کننده این است که از icon این activity به عنوان icon برنامه استفاده شود.البته اگر هیچ iconی مشخص نکرده بود در این صورت icon از تگ application خوانده خواهد شد.

ShareActivity نیز امکان به اشتراک گذاری متن و مدیا را برای ما فراهم می کند.

استفاده از pending intent:

pending intent یک توکن است که برنامه های دیگر داده می شود و به وسیله آن برنامه های دیگر می تواند یک قطعه کد با دسترسی های مثل برنامه ما را اجرا کنند.به عبارت دیگر این pendingintent به ما اجازه می دهد که یک intent ایجاد کنیم و آن را به یک برنامه دیگر پاس دهیم و اجازه بدهیم که آن برنامه آن intent را در آینده با دسترسی های مشابه دسترسی های برنامه ما اجرا کند.

موارد استفاده:
تعریف یک Intent برای اجرا در قسمت Notification.( سیستم اندروید از طریق NotificationManagerدر آینده Intent مورد نظر را اجرا خواهد کرد)
تعریف یک Intent برای اجرا در قسمت App Widget(صفحه اصلی Intent مورد نظر را اجرا خواهد کرد)
تعریف یک Intent برای اجرا در آینده( AlarmManager در سیستم اندروید Intent مورد نظر را اجرا خواهد کرد)

اجباری کردن app chooser

زمانی که ما از implicit intent استفاده می کنیم سیستم به دنبال برنامه هایی می گردد که قابلیت اجرا کردن درخواست ما را داشته باشند.در این صورت اگر بیشتر از یک برنامه این قابلیت را داشته باشند سیستم به کاربر قابلیت انتخاب یکی(app chooser) از آنها را می دهد.همیچنین کاربر نیز می تواند با انتخاب یکی از آن ها به عنوان پیش فرض آن برنامه را برای یک intent خواص انتخاب کند.این موضوع به کاربر کمک می کند که مثلا هر زمان که خواست یک صفحه وب را مشاهده کند,برنامه گوگل کروم باز شود و هر بار از کاربر سوال نشود.

app chooser

اما زمان هایی و جود دارد که ما می خواهیم  کاربر را فورس کنیم تا همیشه از لیست برنامه ها برای پردازش یک intent یکی را انتخاب کند.مثلا فرض کنید میخواهید به وسیله ACTION_SEND یک intent برای به اشتراک گذاری محتوا بسازید.در این صورت صحیح نیست که مثلا اگر کاربر app فیس بوک را به عنوان پیش فرض انتخاب کرده باشد همیشه با آن بخواهد محتوا را با فیس بوک به اشتراک بگذارد.

بنابراین نیاز است app chooser را اجباری کنیم.برای این موضوع یک intent به وسیلهcreateChooser() می سازیم.

Intent sendIntent = new Intent(Intent.ACTION_SEND);
...

// Always use string resources for UI text.
// This says something like "Share this photo with"
String title = getResources().getString(R.string.chooser_title);
// Create intent to show the chooser dialog
Intent chooser = Intent.createChooser(sendIntent, title);

// Verify the original intent will resolve to at least one activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
    startActivity(chooser);
}

Intent و Intent Filter

Intent یک شی حاوی یک سری اطلاعات که برای درخواست یک کار از  برنامه دیگر مورد استفاده قرار می گیرد.همچنین Intent ارتباط بین اجزای اصلی یک برنامه را تسهیل می کند.سه مورد کاربرد اصلی را می توان برای Intent نام برد:

  1. اجرا کردن یک activity
  2. اجرا کردن یک service
  3. تحویل دادن یک broadcast

انواع Intent

Intentها را می توان به دو نوع تقسیم بندی کرد:

  1. Explicit intent:استفاده از intent به وسیله نام کامل component مورد نظر.برای مثال زمانی که شما می خواهید یک activity را اجرا کنید و آن activity در برنامه خودتان وجود دارد.
  2. Implicit intent:به جای استفاده از نام کامل component, یک action کلی را مشخص می کنید ,که کدام یک از سایر برنامه های قابلیت اجرای action مورد نظر ما را دارند.برای مثال اگر می خواهید موقعیت کاربر را در نقشه نشانش دهید از Implicit intent استفاده می کنید و به وسیله آن یک درخواست برای برنامه هایی که قادر به نشان دادن نقشه هستند ارسال می کنید.

intent-filters

شکل بالا نشان دهنده چگونگی باز کردن یک activity بوسیلهImplicit intent است.

زمانی که ما از Implicit intent استفاده می کنیم سیستم اندروید بدنبال برنامه ای می گردد که قادر به پردازش درخواست ما باشد.سیستم از طریق intent filterهایی که در مانیفست باقی برنامه نوشته شده این کار را انجام می دهد.اگر یک برنامه پیدا کند آن برنامه را باز می کند ولی اگر بیشتر از یک برنامه پیدا کند سیستم به ما قابلیت انتخاب بین آنها را می دهد.

intent filter عبارتی است که در  فایل manifest نوشته می شود و به عبارتی انواع intentی است که برنامه تمایل به دریافت آن ها را دارد.همچنین با تعریف intent filter برای یک activity باقی برنامه ها قادر به اجرای activity شما از طریق intentها خواهند بود.

نکته امنیتی:برای اجرا کردن سرویس ها همیشه سعی کنید از explicit intent استفاده کنید.بنابراین سعی کنید که intent filter برای سرویسهای خود تعریف نکنید.از Android 5.0 به بعد اگر بخواهید bindService() را به وسیله implicit intent فراخوانی کنید سیستم خطا می دهد.

استفاده ازintent

شی intent شامل اطلاعاتی که سیستم برای اجرا کردن یک component از آن استفاده می کند و همچنین دارای اطلاعاتی برای انجام دادن عملیات مورد نظر توسط component درخواستی نیز است.

اطلاعات اصلی intent:

  • نام component:این مقدار optional است .ولی وجه تمایز بین یک implicit intent و explicit intent است.به عبارتی با مشخص کردن نام component باعث ساخت یک explicit intent می شویم ولی اگر ذکر نکنیم باعث می شود که سیستم تصمیم بگیرد که کدام component  از کدام app باید اجرا شود.همچنین برای set کردن این مقدار از نام کامل باید استفاده شود.برای مثال com.example.ExampleActivity.
  • Action:این مقدار مشخص کننده یک action عمومی برای انجام است.برای مثال استفاده از ACTION_VIEW به همراه startActivity() زمانی استفاده می شود که نیاز باشد به کاربر چیزی را نشان دهیم.مثل عکسی که در گالری ذخیره شده و یا آدرسی در نقشه.همچنین از ACTION_SEND به همراه startActivity() زمانی استفاده می شود که داده ای داریم که کاربر می تواند آن را به اشتراک بگذارد.
  • Data:یک URI است که به یک داده ی خاص اشاره می کند.همچنین بهتر است هنگام استفاده از اطلاعات MIME type آن را نیز مشخص کنید.برای مثال activity که قابلیت نمایش عکس را دارد با activity که قابلیت پخش فایل موسیقی را دارد با هم متفاوت هستند برای همین موضوع بهتر است MIME type را مشخص کنیم.MIME type کمک می کند که سیستم اندروید بتواند بهترین component را برای رسیدگی به درخواست ما پیدا کند.
  • Category:یک رشته حاوی اطلاعاتی اضافی برای مشخص کردن componentهایی که باید intent مورد نظر ما را هندل کنند.

همچنین intent شامل یک سری اطلاعات دیگر نیز می شود:

  • Extra:یک  Key-value pairs است که به component مورد نظر برای انجام یک action ارسال می شود.
  • Flags:مشخص کننده متادیتا برای یک intent است و همچنین تعیین می کند که سیستم اندروید چگونه یک activity اجرا کند(مثلا  به کدام Task اختصاص دهد)  و همچنین  بعد از اجرا چگونه با activity رفتار کند.

مثالی از explicit intent:

// Executed in an Activity, so 'this' is the Context
// The fileUrl is a string URL, such as "http://www.example.com/image.png"
Intent downloadIntent = new Intent(this, DownloadService.class);
downloadIntent.setData(Uri.parse(fileUrl));
startService(downloadIntent);

مثالی از implicit intent:

// Create the text message with a string
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
sendIntent.setType("text/plain");

// Verify that the intent will resolve to an activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
    startActivity(sendIntent);
}

کد بالا واضح است ولی اگر به if داخل کد دقت کنید متوجه خواهید شد که ابتدا با این کار از وجود  component مورد نظر برای پاسخگویی به intent خودمان مطمئن شده ایم  و سپس startActivity را صدا می زنیم.به این علت که اگر componentی برای هندل کردن intent ما در سیستم وجود نداشته باشد برنامه ما کرش خواهد کرد.

 

معماری اندروید

سیستم عامل اندروید یک سیستم لینوکسی و سورس باز است که در شکل زیر اجزای اصلی تشکیل دهنده سیستم اندروید را ملاحظه می کنید:

android-stack_2x

Linux Kernel

پایه و اساس سیستم عامل اندروید هسته لینوکس است.برای مثال مباحثی مانند مدیریت threadها و همچنین مدیریت memory در Android Runtime (ART) برپایه کرنل لینوکس بنا شده است.همچنین این موضوع باعث شده که از مزایا و امکانات امنیتی هسته لینوکس نیز بهره ببرد.

Hardware Abstraction Layer

یک واسط برای فراهم کردن امکانات سخت افزاری به Java API framework. است.مثلا امکاناتی مثل دوربین را فراهم می کند.

Android Runtime

برای اندروید ۵ به بالا هر برنامه روی یک پروسس و هر پروسس دارای یک Android Runtime مختص به خودش است.ART برای اجرا کردن چندین ماشین مجازی بصورت همزمان و همچنین اجرای فایل های DEX در یک محیط با memory بسیار اندک نوشته شده است.DEX فایل ها در واقع کدهای جاوا هستند که توسط ابزار بیلد مثل Jack به آن تبدیل می شوند که قابلیت اجرا شدن روی ART را دارا هستند.

مزایا ART:

  • Ahead-of-time (AOT) and just-in-time (JIT) compilation
  • Optimized garbage collection
  • امکانات دیباگ و خطایابی راحت تر

در اندروید های ۵ به قبل Dalvik در واقع Android runtime در سیستم اندرویدی بوده.اگر برنامه شما در ART اجرا می شود در Dalvik نیز می تواند اجرا شود ولی برعکس آن صدق نمی کند.

Native C/C++ Libraries

بسیاری از اصلی ترین اجزای سیستم اندروید بوسیله کتابخانه های سی و سی پلاس پلاس نوشته شده اند به عنوان مثال می توان از ART و HAL نام برد.

Java API Framework

اصلی ترین امکانات سیستم عامل اندروید از طریق APIهای جاوایی که در اندروید وجود دارند قابل دسترسی هستند و امکاناتی برای نوشتن برنامه های مختلف در اختیار ما قرار می دهند.

System Apps

یک سری برنامه به صورت پیش فرض در اندروید وجود دارند که کار کردن با این سیستم را برای ما ممکن می سازند.مانند برنامه sms برنامه calendar , مرورگر وب و …

 

معرفی Butter Knife

butterknife
Butter Knife کار پیدا کردن و cast اتوماتیک view های مورد نظر ما را از طریق Annotation انجام می دهد و استفاده از آن بسیار ساده است.همچنین در آن از reflection استفاده نشده و در واقع کدها generate می شوند.

به کدهای زیر توجه کنید:

mUserNameEditText = (EditText) view.findViewById(R.id.username);
mPasswordEditText = (EditText) view.findViewById(R.id.password);

حال به این مثال دقت کنید:

  @BindView(R.id.username) TextView username;
  @BindView(R.id.password) TextView password;

در مثال اول  مجبوریم هر جای که نیاز بود یک view خاص را پیدا کنیم یک cast اضافی نیز انجام دهیم.اما Butter Knife این کار را برای ما راحت تر و تمیزتر انجام می دهد.
برای استفاده از Butter Knife در Activity مانند زیر عمل می کنیم:

class ExampleActivity extends Activity {
    @BindView(R.id.title) TextView title;
    @BindView(R.id.subtitle) TextView subtitle;
    @BindView(R.id.footer) TextView footer;

    @Override public void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.simple_activity);
    ButterKnife.bind(this);
// TODO Use fields...
    }
}

یک امکان دیگری که Butter Knife به ما می دهد امکان bind کردن resourceهای مختلف است:


class ExampleActivity extends Activity {
  @BindString(R.string.title) String title;
  @BindDrawable(R.drawable.graphic) Drawable graphic;
  @BindColor(R.color.red) int red; // int or ColorStateList field
  @BindDimen(R.dimen.spacer) Float spacer; // int (for pixel size) or float (for exact value) field
  // ...
}

امکان جالب دیگر قابلیت جمع کردن چند view در یک لیست است:

@BindViews({ R.id.first_name, R.id.middle_name, R.id.last_name })
List&lt;EditText&gt; nameViews;

و سپس انجام یک عملیات روی تمامی view ها:


ButterKnife.apply(nameViews, DISABLE);
ButterKnife.apply(nameViews, ENABLED, false);

برای تعریف DISABLE و ENABLED هم مانند زیر عمل خواهیم کرد:


static final ButterKnife.Action<View> DISABLE = new ButterKnife.Action<View>() {
  @Override public void apply(View view, int index) {
    view.setEnabled(false);
  }
};
static final ButterKnife.Setter<View, Boolean> ENABLED = new ButterKnife.Setter<View, Boolean>() {
  @Override public void set(View view, Boolean value, int index) {
    view.setEnabled(value);
  }
};

مورد دیگر امکان listen کردن روی رویداد  OnClick  مربوط به view ها است:


@OnClick(R.id.submit)
public void submit() {
  // TODO submit data to server...
}

همچنین به روش زیر نیز می توانید از این امکان استفاده کنید:


@OnClick(R.id.submit)
public void sayHi(Button button) {
  button.setText("Hello!");
}

علاوه بر آن می توانید مثال بالا را برای چند view نیز انجام دهید:


@OnClick({ R.id.door1, R.id.door2, R.id.door3 })
public void pickDoor(DoorView door) {
  if (door.hasPrizeBehind()) {
    Toast.makeText(this, "You win!", LENGTH_SHORT).show();
  } else {
    Toast.makeText(this, "Try again", LENGTH_SHORT).show();
  }
}

به علت آنکه lifecycle یک fragment با یک activity متفاوت است در fragmentها نیاز است به شکل زیر عمل کنیم:

public class FancyFragment extends Fragment {
  @BindView(R.id.button1) Button button1;
  @BindView(R.id.button2) Button button2;
  private Unbinder unbinder;

  @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fancy_fragment, container, false);
    unbinder = ButterKnife.bind(this, view);
    // TODO Use fields...
    return view;
  }

  @Override public void onDestroyView() {
    super.onDestroyView();
    unbinder.unbind();
  }
}

برای نصب نسخه جاری می توانید از کدهای زیر در GRADLE استفاده کنید:
compile 'com.jakewharton:butterknife:8.4.0'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.4.0'

همچنین برای اطلاعات بیشتر نیز به این آدرس مراجعه کنید.