با سلام، ممکنه برای خیلی ها این سوال پیش اومده باشه که از هرکدوم از Handler یا Thread یا AsycTask استفاده کرده باشیم و لی در حقیقت تفاوت میان آنها را به درستی نشناسیم. در این مقاله می خواهیم این تفاوت ها و محل مناسب استفاده از هر یک را برسی کنیم.
اول لازم هست تا با تعریف هرکدام بیشتر آشنا شویم.
Thread
A thread is a thread of execution in a program. The Java Virtual Machine allows an application to have multiple threads of execution running concurrently.
ترد یا رشته واحد های کلی پردازش وظایف هستند که هر برنامه می تواند تعدادی ترد داشته باشد. هر ترد اولویتی در سیستم دارد و تردهای ایجاد شده توسط یک ترد دیگر، اولویت هم سطح خواهند داشت. در اندروید هر برنامه یک ترد اصلی یا Main thread دارد و وقتی thread جدیدی ایجاد می کنیم پردازش ها جدا از اتفاقات ترد اصلی روی می دهد. اما برای هماهنگ کردن و یا به عنوان مثال بازگشت جواب باید اینکار را بصورت دستی توسط message یا callback مدیریت کنیم. ( مقاله کامل در اینجا) در صورتی که اگر تردی ایجاد کنیم دستورالعمل های آن باعث freeze شدن برنامه نمی شود زیرا در یک ترد دیگری جاریست اما در عوض به عناصر UI که در ترد اصلی هستند دسترسی نداریم و نمی توانیم بطور مستقیم UI را تغییر دهیم.
1 2 3 4 5 6 |
new Thread(new Runnable() { @Override public void run() { doSomething(); } }).start(); |
Handler
A Handler allows you to send and process Message and Runnable objects associated with a thread’s MessageQueue. Each Handler instance is associated with a single thread and that thread’s message queue. When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it — from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue
طبق تعریف خود گوگل با تعریف یک هندلر می توانیم پیغام یا Runnable ای را پردازش کنیم که دقیقاً در thread کلاس تولید کننده آن قرار می گیرد و نحوه اجرا شدن آن هم به صف همان thread بستگی دارد. پس یعنی Handler های تولید شده در یک thread به ترتیب در همان thread اجرا می شوند. دستورالعمل هایی که در Handler اجرا می شوند در thread اصلی بوده و اصطلاحاً باعث freeze شدن برنامه می شود. اما اگر در ترد اصلی تولید شوند به عناصر UI برنامه دسترسی داریم و مثلا می توانیم یک ViewText ای را بروز رسانی کنیم.
1 2 3 4 5 6 |
new Handler().post(new Runnable() { @Override public void run() { doSomething(); } }); |
بطور معمول وقتی از Handler استفاده می کنیم که بخواهیم اتفاق خاصی در زمان خاصی بیافتد. مثلا فرض کنید می خواهید با تایمر View ای را آپدیت کنید.
1 2 3 4 5 6 |
new Handler().postDelayed(new Runnable() { @Override public void run() { // update UI after 1000 millisecons } },1000); |
یک اینترفیسی است که تمامی کلاس هایی که قرار است توسط Thread اجرا شوند، باید آن را پیاده سازی کنند که یک متد run دارد. پس هرکلاس مشخص می کند که هنگام اجرا شدن توسط Thread چکاری را انجام دهد. ( آن کار در متد run پیاده سازی می شود.) که در تمامی مثال های قبلی قابل مشاهده است.
AsyncTask
برای ساخت آن باید کلاسی از آن مشتق کنیم و متد های آن را Override کنیم.
- doInBackground
- onPostExecute
متد doInBackground در یک ترد مجزا انجام می گیرد و جواب آن onPostExecute در ترد اصلی یا همان UI thread اتفاق می افتد که می توانیم توسط آن UI را آپدیت کنیم. البته متد های دیگری نیز دارد که تنها به این دو متد اشاره کردم. استفاده از AsyncTask بسیار در گرفتن اطلاعات از سمت web پرکاربرد است. ( در صورتی که نخواهیم از کتابخانه های نظیر Retrofit و Volley استفاده کنیم) و اصولاً در قدیم (حدود ۶ سال قبل) ترکیب HttpConnection و AsyncTask برای صدا زدن Api های سمت وب اجتناب ناپذیر بود!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
private class MyAsycTask extends AsyncTask<Void, Void, Void> { @Override protected void onPreExecute() { //do something in Ui-thread before background work start } @Override protected Void doInBackground(Void... params) { //do something in background return null; } @Override protected void onPostExecute(Void aVoid) { //do something in Ui-thread } } |
نکته:
یک نوع استفاده دیگر از Handler وجود دارد که در ظاهر انگار Thread است اما:
1 2 3 4 5 6 |
runOnUiThread(new Runnable() { @Override public void run() { doSomething(); } }); |
توجه کنید که runOnUiThread یک نوع خاصی از Handler است که فقط در ترد اصلی اتفاق می افتد.
هرگونه سوال و یا نکته ای داشتید خوشحال می شم که کامنت کنید.
منبع: بایت کد
این جمله شما غلط هست :
دستورالعمل هایی که در Handler اجرا می شوند در thread اصلی بوده و اصطلاحاً باعث freeze شدن برنامه می شود
https://developer.android.com/reference/android/os/Handler
مثالی که در قسمت Handler زدید دقیقا یک ترد مجزا ایجاد شده و بعد از اتمام کار توسط handler با UI ارتباط برقرار میکند.
سلام و ممنون از پیامتان. به خط دوم از تعریف هندلر در مقاله من و جمله دوم در لینک ارسالی خودتان توجه کنید. “… دقیقاً در thread کلاس تولید کننده آن قرار می گیرد و نحوه اجرا شدن آن هم به صف همان thread بستگی دارد”. پس اگر بطور معمول داخل یک اکتیویتی یا فرگمنت یا هرکلاس دیگری که در ترد اصلی برنامه وجود دارد، یک هندلر بسازید آن هندلر همانطور که اشاره کردم وظیقه هندل کردن مسیج ها و runnable های همان ترد می شود که mainThread است. پس اگر دستوری را داخل آن قرار دهیم ترد اصلی را که UI در آن قرار دارد را تا تمام شدن آنها freeze می کند. البته دیدن freeze به دستور العمل های شما بستگی خواهد داشت که باید پیچیدگی نسبی داشته باشند.
سلام خسته نباشیدممنونم. من تازه کار باسرور رو شروع کردم واندروئدکارمیکنم .ازکتابخانه والی برای کلاس های جاوا میشه استفاده کرد برای دریافت و ارسال عکس و اطلاعات به سرور؟و دیگه از پی اچ پی استفاده نکرد؟وقتی ازوالی استفاده کنیم لازم نیست از Asyn Taskاستفاده کننیم؟
اشتباه نکنید!!بله از والی برای ارتباط با سرور استفاده میشه ولی ربطی به php نداره.پی اچ پی یک زبان سمت سرور برای برنامه نویسی سمت سرور است و میتوان به جای ان از Asp یا پایتون یا حتی خود جاوا و زبانای دیگه هم استفاده کرد و ربطی به کلاینت اندروید نداره.در حقیقت با رتروفیت یا والی میشه به api ای که سمت سرور قرار داره وصل شد و اطلاعات رو رد و بدل کرد و درواقع جایگزینی است برای Async Task