با حمایت ما%۵
تخفیف بگیرد

logo-samandehi

برنامه نويسي اندرويد 11- همزمانی - AsyncTask ها

مقدمه:

در قسمت قبل، با استفاده از Thread ها برنامه زیر را پیاده سازی کردیم. اما همانطور که دیده می شد، برای آپدیت کردن کنترل های UI ( رابط گرافیک ) نیاز داشتیم که از Main Thread یا همان UI Thread استفاده کنیم، به همین منظور از Handler کمک گرفتیم و با post کردن یک Runnable به آن، قادر بودیم مجموعه دستور العمل های آن Runnable را در Main Thread اجرا کنیم ( مستقل از اینکه در کدام Thread هستیم ).

اینجا موضوع دیگری مطرح می شود که اگر قرار باشد اعمال پیچیده UI با اعمال پیچیده داخل Thread ها ترکیب شوند ممکن است کار آپدیت کردن UI دشوار تر شود. تا حدودی این موضوع درست است، بله دشوار تر خواهد شد. به این منظور در این قسمت روش دیگری برای استفاده از Thread ها گفته می شود که به AsyncTask ها معروفند. به عبارتی در پشت قضیه همان اعمال Thread و Handler اجرا می شود اما ما با آن دسته و پنجه نرم نمی کنیم، از طرفی کمی به تعداد خطوط کد اضافه می شود اما قابلیت مدیریت بیشتری بر روی عملکرد الگوریتم خواهیم داشت.

موضوع بعدی این است که کی از Thread ها استفاده کنیم و کی از AsyncTask ها؟ پاسخ این سئوال را خودتان بعداً بهتر درک خواهید کرد. استفاده از هر دو روش آسان است، فقط نیاز است آنرا خوب درک کنید، پس از یک درک به نسبت کامل تقریباً بدون نیاز به داشتن اطلاعات بیشتر در مورد Thread ها قادر خواهید بود برنامه های بسیار پیشرفته در مورد Thread ها طراحی کنید.

در این آموزش قصد داریم دقیقاً برنامه گذشته را بنویسیم اما این بار با استفاده از AsyncTask ها، نه به طور مستقیم با استفاده از Thread. از این جهت فایلهای XML همان فایلهای جلسه قبل خواهند بود ولی Activity های جدید تر خواهیم ساخت و برنامه دیگری داخل آنها خواهیم نوشت.

 

تصویر متحرک از خروجی این جلسه ( همانند جلسه قبل - اما با روشی دیگر ) :

 

 

آموزش:

» کار را بر روی پروژه ساخته شده در ( همزمانی - Thread ها ) ادامه می دهیم. لذا اگر آنرا ندارید از آموزش مذکور دانلود کرده و طبق آموزشهای قبل تر ، آنرا Import کنید.

» کلاسهای  ThreadSample3Activity.java، ThreadSample2Activity.java، ThreadSample1Activity.java را در com.uncocoder.course.lessons.thread می سازیم و به شکل زیر آنرا برنامه نویسی کنید ( یا کپی کنید ). توجه داریم که form ها را مجدد نساخته ایم و از همان قبلی ها استفاده می کنیم.

 

محتویات فایل AsyncSample1Activity :


  1. package com.uncocoder.course.lessons.thread;

    import android.app.Activity;
    import android.content.Intent;
    import android.os.AsyncTask;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.KeyEvent;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.ScrollView;
    import android.widget.TextView;
    import com.uncocoder.course.lessons.R;

    public class AsyncSample1Activity extends Activity {

        /* تعریف اشاره گرهای مورد نیاز جهت اتصال به رابط گرافیک */
        private Button               btn_no_thread        = null;
        private Button               btn_single_thread    = null;
        private Button               btn_parallel_threads = null;
        private Button               btn_clear_log        = null;
        private Button               btn_next             = null;
        private ScrollView           scroll_content       = null;
        private TextView             txt_log              = null;

        /** متغیری برای اینکه تعیین کنیم آیا فقط روی لوگ کت نشان داده شود یا روی رابط گرافیک هم نشان داده شود */
        private final static boolean mCanLogToUi          = true;



        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.form_thread1);

            /* مقدار دهی اشاره گرهای رابط گرافیک و تعیین عملکرد آنها */
            initializeUi();
        }



        /** با استفاده از این می توانیم کنترل صفحه کلید سخت افزاری را در دست بگیریم */
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_BACK) {
                /* به برنامه دستور خروج کامل را خواهیم داد */
                System.exit(0);
                return true;
            }

            /* اگر ما دستوری برای صفحه کلید نداشتیم، کار خودش را بکند */
            return super.onKeyDown(keyCode, event);
        }



        /** مقدار دهی اشاره گرهای رابط گرافیک و عملکرد آنها */
        private void initializeUi() {
            btn_no_thread = (Button) findViewById(R.id.btn_no_thread);
            btn_single_thread = (Button) findViewById(R.id.btn_single_thread);
            btn_parallel_threads = (Button) findViewById(R.id.btn_parallel_threads);
            btn_clear_log = (Button) findViewById(R.id.btn_clear_log);
            btn_next = (Button) findViewById(R.id.btn_next);
            scroll_content = (ScrollView) findViewById(R.id.scroll_content);
            txt_log = (TextView) findViewById(R.id.txt_log);

            btn_no_thread.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    doWithoutThread();
                }
            });

            btn_single_thread.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    doSingleThread();
                }
            });

            btn_parallel_threads.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    doParallelThreads();
                }
            });

            btn_clear_log.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    clearLog();
                }
            });

            btn_next.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    /* اجرای اکتیویتی جدید و بستن کامل اکتیویری فعلی */
                    Intent intent = new Intent(AsyncSample1Activity.this, AsyncSample2Activity.class);
                    startActivity(intent);
                    finish();
                }
            });
        }



        /** صفجه حاول لوگ ها را خالی می کند و فقط یک عبارت لوگ در آن می نویسد */
        private void clearLog() {
            txt_log.setText("Log:");
        }



        /** یک عمل طولانی مدت که برای تست ها بکار می رود */
        private void heavyWeightWork() {
            String str = "";

            for (long i = 0; i < 1500; i++) {
                str += i + "\n";
            }
        }



        /** به پنجره لوگ کت و کنترل داخل برنامه دستور نمایش لوگ جدید را می دهیم */
        private void addLog(final String message) {

            /* همانطور که می بینید دیگر نیازی به استفاده از هندلر ها نیست، علت در متن آموزش قرار داده شده است */
            if (mCanLogToUi) {
                txt_log.setText(txt_log.getText().toString() + "\n" + message);
                scroll_content.fullScroll(View.FOCUS_DOWN);
            }

            /* در هر صورت پیام را در لوگ کت می نویسیم */
            Log.i("LOG", message);
        }



        private void doWithoutThread() {
            addLog("With no thread Started");
            heavyWeightWork();
            addLog("With no thread Finished");
        }

        public class HeavyWeightTask extends AsyncTask {

            /* تعریف فیلدی جهت نگهداری نام ترد مورد نظر */
            public String mTitle;



            @Override
            protected void onPreExecute() {
                /* نمایش  تسک که استارت شده است */
                addLog(mTitle + " Started");

                super.onPreExecute();
            }



            @Override
            protected Void doInBackground(Void... params) {
                /* تصحیح نام ترد بر اساس اطلاعات ورودی */
                Thread.currentThread().setName(mTitle);

                /* انجام عمل سنگین */
                heavyWeightWork();
                return null;
            }



            @Override
            protected void onPostExecute(Void result) {
                /* نمایش  تسک که خاتمه یافته است */
                addLog(mTitle + " Finished");

                super.onPostExecute(result);
            }
        }



        /** تست شماره یک */
        private void doSingleThread() {

            /* ساخت یک نمونه از تسک و اجرای آن */
            HeavyWeightTask task = new HeavyWeightTask();
            task.mTitle = "Thread";
            task.execute();
        }



        private void doParallelThreads() {
            /* ساخت چند نمونه از تسک و اجرای آن */
            HeavyWeightTask task1 = new HeavyWeightTask();
            HeavyWeightTask task2 = new HeavyWeightTask();
            HeavyWeightTask task3 = new HeavyWeightTask();
            HeavyWeightTask task4 = new HeavyWeightTask();
            task1.mTitle = "Thread 1";
            task2.mTitle = "Thread 2";
            task3.mTitle = "Thread 3";
            task4.mTitle = "Thread 4";
            task1.execute();
            task2.execute();
            task3.execute();
            task4.execute();
        }
    }

 

 

محتویات فایل AsyncSample2Activity :


  1. package com.uncocoder.course.lessons.thread;

    import android.app.Activity;
    import android.content.Intent;
    import android.os.AsyncTask;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.KeyEvent;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.ProgressBar;
    import android.widget.ScrollView;
    import android.widget.TextView;
    import com.uncocoder.course.lessons.R;

    public class AsyncSample2Activity extends Activity {

        /* تعریف اشاره گرهای مورد نیاز جهت اتصال به رابط گرافیک */
        private Button               btn_set_and_start = null;
        private Button               btn_stop          = null;
        private Button               btn_clear_log     = null;
        private Button               btn_prev          = null;
        private Button               btn_next          = null;
        private ScrollView           scroll_content    = null;
        private TextView             txt_log           = null;
        private ProgressBar          prg_percent       = null;
        private EditText             edt_interval      = null;

        /** متغیری برای اینکه تعیین کنیم آیا فقط روی لوگ کت نشان داده شود یا روی رابط گرافیک هم نشان داده شود */
        private final static boolean mCanLogToUi       = true;



        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.form_thread2);

            /* مقدار دهی اشاره گرهای رابط گرافیک و تعیین عملکرد آنها */
            initializeUi();
        }



        /** با استفاده از این می توانیم کنترل صفحه کلید سخت افزاری را در دست بگیریم */
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_BACK) {
                /* به برنامه دستور خروج کامل را خواهیم داد */
                System.exit(0);
                return true;
            }

            /* اگر ما دستوری برای صفحه کلید نداشتیم، کار خودش را بکند */
            return super.onKeyDown(keyCode, event);
        }



        /** در صورتیکه صفحه قرار بود از دید خارج شود عمل استاپ تسک را انجام دهد */
        @Override
        public void onPause() {
            super.onPause();
            doStop();
        }



        /** مقدار دهی اشاره گرهای رابط گرافیک و عملکرد آنها */
        private void initializeUi() {
            btn_set_and_start = (Button) findViewById(R.id.btn_set_and_start);
            btn_stop = (Button) findViewById(R.id.btn_stop);
            btn_clear_log = (Button) findViewById(R.id.btn_clear_log);
            btn_next = (Button) findViewById(R.id.btn_next);
            btn_prev = (Button) findViewById(R.id.btn_prev);
            scroll_content = (ScrollView) findViewById(R.id.scroll_content);
            txt_log = (TextView) findViewById(R.id.txt_log);
            prg_percent = (ProgressBar) findViewById(R.id.prg_percent);
            edt_interval = (EditText) findViewById(R.id.edt_interval);

            btn_set_and_start.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    doStart();
                }
            });

            btn_stop.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    doStop();
                }
            });

            btn_clear_log.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    clearLog();
                }
            });

            btn_prev.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    /* اجرای اکتیویتی جدید و بستن کامل اکتیویری فعلی */
                    Intent intent = new Intent(AsyncSample2Activity.this, AsyncSample1Activity.class);
                    startActivity(intent);
                    finish();
                }
            });

            btn_next.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    /* اجرای اکتیویتی جدید و بستن کامل اکتیویری فعلی */
                    Intent intent = new Intent(AsyncSample2Activity.this, AsyncSample3Activity.class);
                    startActivity(intent);
                    finish();
                }
            });
        }



        /** صفجه حاول لوگ ها را خالی می کند و فقط یک عبارت لوگ در آن می نویسد */
        private void clearLog() {
            txt_log.setText("Log:");
        }



        /** به پنجره لوگ کت و کنترل داخل برنامه دستور نمایش لوگ جدید را می دهیم */
        private void addLog(final String message) {

            /* همانطور که می بینید دیگر نیازی به استفاده از هندلر ها نیست، علت در متن آموزش قرار داده شده است */
            if (mCanLogToUi) {

                /* نمایش محتویات گذشته، رفتن به خط بعد و نمایش پیام جدید */
                txt_log.setText(txt_log.getText().toString() + "\n" + message);

                /* محاسبه و نمایش مقدار پروگرس بار */
                int percent = mLoopCount % 100;
                prg_percent.setProgress(percent);

                /* رفتن به انتهای لیست اسکرول */
                scroll_content.fullScroll(View.FOCUS_DOWN);
            }

            /* در هر صورت پیام را در لوگ کت می نویسیم */
            Log.i("LOG", message);
        }

        /** تعیین اینکه آیا تسک می تواند حلقه خود را ادامه دهد */
        private boolean         mCanContinue = false;

        /** نگهداری اینکه چندمین حلقه اجرا هستیم */
        private int             mLoopCount   = 0;

        /** تعریف به عنوان فیلد با دید زیاد که بتوانیم در هر متدی به آن دسترسی داشته باشیم */
        private HeavyWeightTask mTask;



        private void doStart() {
            /* اگر تسک نال نبود یعنی در حال اجرا است پس نمایش مناسب می دهیم و بیرون می آییم */
            if (mTask != null) {
                addLog("Thread already Started! Stop it First and Start Again!");
                return;
            }

            /* با رسیدن به این خط یعنی تسکی وجود نداشته پس ادامه می دهیم */

            /* می گوییم که تسک می توان حلقه خود را ادامه دهد، البته فعلاً ذخیره می کنیم، با چک شرط تست می کنیم */
            mCanContinue = true;

            /* ریست کردن شماره حلقه فعلی، چرا که تسک از ابتدا شروع به کار خواهد کرد */
            mLoopCount = 0;

            mTask = new HeavyWeightTask();
            mTask.mTitle = "Thread";
            mTask.execute();
        }



        /** متوقف نمودن تسک */
        private void doStop() {
            /* با فالس کردن این متغیر می گوییم که حلقه وایل دیگر لوپ نزند */
            mCanContinue = false;

            /* اگر تسک وجود داشت آنرا متوقف کند */
            if (mTask != null) {
                mTask.cancel(true);
            }

            /* تسک را از حافظه پاک می کنیم و می گوییم که دیگر وجود نداشته باشد و نخواهد داشت */
            mTask = null;
        }

        public class HeavyWeightTask extends AsyncTask {

            /* تعریف فیلدی جهت نگهداری نام ترد مربوط به تسک مورد نظر */
            public String mTitle;

            /* تعریف فیلدی جهت ذخیره کردن پیام خروجی */
            public String mMessage;



            @Override
            protected void onPreExecute() {
                /* نمایش  تسک که استارت شده است */
                addLog(mTitle + " Started");

                super.onPreExecute();
            }



            @Override
            protected Void doInBackground(Void... params) {
                /* تصحیح نام ترد مربوط به تسک بر اساس اطلاعات ورودی */
                Thread.currentThread().setName(mTitle);

                /* گرفتن مقدار عددی زمان انتظار بین حلقه ها از داخل ادیت باکس در رابط گرافیک */
                final int interval = Integer.parseInt(edt_interval.getText().toString());

                /* تا زمانیکه ما می گوییم تسک می تواند داخل این حلقه را مدام اجرا کند */
                while (mCanContinue) {
                    /* فعلا به این دستور ( ترای ) کاری ندارم */
                    try {
                        /* به ترد مربوط به تسک فعلی دستور می دهیم عمل خود را تا زمان معین متوقف کند و هیچ پردازشی انجام ندهد */
                        Thread.sleep(interval);

                        /* پس از صرف زمان معین ادامه می دهیم و یکی به شماره حلقه اضافه می کنیم */
                        mLoopCount++;

                        /* خروجی مناسب را در لوگ کت و احتمالاً رابط گرافیک نمایش می دهیم */
                        mMessage = "Loop #" + mLoopCount;
                        publishProgress();
                    }
                    /* در صورتیکه با استفاده از متد اینتراپت در پایین، ترد  مربوط به تسک را متوقف کنیم داخل این دستورات می شویم */
                    catch (InterruptedException e) {
                        /* ترد متوقف شده */
                        mMessage = "Interrupted by Code, Stopped Clicked";
                        publishProgress();
                    }
                }

                return null;
            }



            @Override
            protected void onProgressUpdate(Void... values) {
                addLog(mMessage);
                super.onProgressUpdate(values);
            }



            @Override
            protected void onPostExecute(Void result) {
                /* نمایش  تسک که خاتمه یافته است */
                addLog(mTitle + " Finished");

                super.onPostExecute(result);
            }
        }
    }

 

 

محتویات فایل AsyncSample3Activity :


  1. package com.uncocoder.course.lessons.thread;

    import android.app.Activity;
    import android.content.Intent;
    import android.os.Bundle;
    import android.view.KeyEvent;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import com.uncocoder.course.lessons.R;

    public class AsyncSample3Activity extends Activity {

        /* تعریف اشاره گرهای مورد نیاز جهت اتصال به رابط گرافیک */
        private Button btn_prev = null;



        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.form_thread3);

            /* مقدار دهی اشاره گرهای رابط گرافیک و تعیین عملکرد آنها */
            btn_prev = (Button) findViewById(R.id.btn_prev);
            btn_prev.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    /* اجرای اکتیویتی جدید و بستن کامل اکتیویری فعلی */
                    Intent intent = new Intent(AsyncSample3Activity.this, AsyncSample2Activity.class);
                    startActivity(intent);
                    finish();
                }
            });
        }



        /** با استفاده از این می توانیم کنترل صفجه کلید سخت افزاری را در دست بگیریم */
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_BACK) {
                System.exit(0);
                return true;
            }

            return super.onKeyDown(keyCode, event);
        }

    }

 

 

محتویات فایل AndroidManifest.xml:



  1.     package="com.uncocoder.course.lessons"
        android:versionCode="1"
        android:versionName="1.0" >

       

                android:icon="@drawable/ic_launcher"
            android:label="@string/app_name" >
                        android:name=".AndroidCourseActivity"
                android:label="@string/app_name" >
           
                        android:name="com.uncocoder.course.lessons.thread.ThreadSample1Activity"
                android:label="@string/app_name"
                android:theme="@android:style/Theme.NoTitleBar" >
           
                        android:name="com.uncocoder.course.lessons.thread.ThreadSample2Activity"
                android:label="@string/app_name"
                android:theme="@android:style/Theme.NoTitleBar" >
           
                        android:name="com.uncocoder.course.lessons.thread.ThreadSample3Activity"
                android:label="@string/app_name"
                android:theme="@android:style/Theme.NoTitleBar" >
           
                        android:name="com.uncocoder.course.lessons.thread.AsyncSample1Activity"
                android:label="@string/app_name"
                android:theme="@android:style/Theme.NoTitleBar" >
               
                   

                   
               

           
                        android:name="com.uncocoder.course.lessons.thread.AsyncSample2Activity"
                android:label="@string/app_name"
                android:theme="@android:style/Theme.NoTitleBar" >
           
                        android:name="com.uncocoder.course.lessons.thread.AsyncSample3Activity"
                android:label="@string/app_name"
                android:theme="@android:style/Theme.NoTitleBar" >
           
       

 

 

توضیحات تکمیلی:

نکاتی که در مورد کلاس AsyncTask مهم است را به قرار زیر است:

♦ این کلاس می تواند سه پارامتر ( Generic ) برای خود بگیرد، ما هر سه این پارامتر ها را همیشه و همیشه Void قرار می دهیم، توجه کنید که Void با void متفاوت است. قرار دادن این پارامترها برابر Void نه تنها در آینده برای ما مشکلی ایجاد نخواهد کرد بلکه به خوانایی برنامه بسیار کمک می کند و به عبارتی استفاده از آنها بی مورد و زائد است.

♦ سه متد استفاده شده در کلاس HeavyWeightTask که درون AsyncSample1Activity ساخته ایم که هر سه Override شده اند. نکته کلیدی و بسیار مهم AsyncTask ها این است که همه متدهای آن ( در اینجا Callback هم نامیده می شوند ) به غیر از doInBackground بطور اتوماتیک و بدون دخالت ما در UI Thread اجرا خواهند شد پس بدون نیاز به Handler می توانیم در آن کدهای مربوط به UI را بنویسیم. دستورات نوشته شده در doInBackground در یک Thread که بطور اتوماتیک و بدون دخالت ما در AsyncTask ساخته می شود اجرا خواهند شد، پس در اینجا هم نیاز به ساخت یک Thread بصورت دستی و start کردن آن نخواهیم داشت.

♦ برای استفاده از این کلاس ابتدا یک نمونه از آنرا می سازیم، سپس آن نمونه را execute می کنیم. پس از execute کردن، زندگی این Task آغاز شده و به شکل زیر یک ( دوره زندگی - Life Cycle * ) خواهد داشت. Life Cycle به فرآیندی اتلاق می شود که یک Object در آن متولد شده، زندگی می کند، به محیط پاسخ می گوید و سرانجام می میرد. معمولاً Life Cycle را با استفاده از Diagram هایی به شکل زیر نشان می دهند. شکل زیر Life Cycle یک نمونه از AsyncTask ها است.

♦ همانطور که در این نمودار مشخص است، پس از اجرای execute ، متد onPreExecute اجرا خواهد شد، سپس doInBackground اجرا می شود، در این فاصله می توان از doInBackground به onProgressUpdate رفت و برگشت. در نهایت پس از اتمام doInBackground به متد onPostExecute خواهیم رسید و پس از اتمام دستورات نوشته شده در این متد Task خواهد مرد.

 

 

♦ متد onProgress را در AsyncSample2Activity خواهید دید و  در AsyncSample1Activity از آن استفاده ای نکرده ایم. برای صدا زدن متد onProgressUpdate از دستور publishProgress استفاده می کنیم. از آنجاییکه در doInBackground ( که در غیر UI Thread اجرا می شود ) بتوانیم متدی را اجرا کنیم که در UI Thread قرار است اجرا شود پس نیاز به یک Handler داریم. با صدا زدن publishProgress این هندلر به طور اتوماتیک ساخته شده و دستورات داخل onProgressUpdate را اجرا می کند. همانطور که در کد دیدید ما پیام را مستقیماً نمی توانیم به publishProgress و در نتیجه onProgressUpdate انتقال دهیم به همین منظور آنرا در فیلدی ذخیره کرده و توسط onProgressUpdate مورد استفاده قرار می گیرد.

♦ در متد doStop که در AsyncSample2Activity بکار رفته است روش لغو عملیات یک AsyncTask با استفاده از cancel نمایش داده شده است.

♦ شما می توانید دو کد را پرینت کرده در کنار یکدیگر قرار دهید و با چشم تفاوت ها را بررسی کنید. همینطور می توانید با استفاده از نرم افزار هایی مانند BeyondCompare این کار را انجام دهید. مقایسه دو کد به شما کمک می کند که محاسن و معایب دو روش را بهتر شناسایی و درک کنید.

♦ بطور کلی زمانیکه نیاز به Update های UI و Progress های لحظه ای داریم و از طرفی نمی خواهیم بر روی Thread اعمال سطح پایینتری نظیر Join، Wait و ... را انجام دهیم استفاده از AsyncTask ها توصیه می شود. در باقی موارد استفاده مستقیم از Thread ها و کنترل برنامه توسط Handler بهتر خواهد بود. بطور مثال:

- برای نوشتن برنامه ای که همزمان صدای را از میکروفون ضبط و پخش می کند مستقیماً از Thread استفاده خواهیم کرد،
- برای نوشتن برنامه که از وب سرویس اطلاعات را خوانده و گزارش دهد از AsyncTask ها استفاده خواهیم کرد.
- برای نوشتن یک Downloader از AsyncTask ها استفاده خواهیم کرد.
- برای نوشتن یک عملیات کپی از فایل به فایل از Thread ها به طور مستقیم استفاده خواهیم کرد.

لزومی در مثالهای بالا نیست و ممکن است برنامه نویسی برعکس آنرا نیز بخوبی انجام دهد.

 

Callback - Event * : این یکی از کلیدیترین واژه های برنامه نویسی است اما مفهوم ساده ای در بر دارد. یک متد را تصور کنید که وقتی مثلاً کپی شدن یک فایل به اتمام می رسد آنرا صدا می زنیم و در آن می گوییم چاپ کند « کپی فایل به اتمام رسید ». در این شرایط به آن متد که صدا زده ایم Event خواهیم گفت. حالا اگر این Event در جواب اجرای یک متد باشد ( مثلاً دستور Copy ) به آن Callback خواهیم گفت. اما در کل تفاوتی بین Callback و Event نیست و می توانید هر دو را یک معنی تلقی کنید.

به همین ترتیب ممکن است Callback ها را شما ننوشته باشید و فقط استفاده کننده باشید. بطور مثال بارها از onClickListener استفاده کرده ایم. این همان Callback ـی است که در پاسخ به کلیک روی یک دکمه صادر می شود. در مورد onProgressUpdate، onPreExecute, onPostExecute هم قضیه به همین شکل است. متد های فوق توسط AsyncTask در زمان خاصی صدا زده می شوند، حالا اگر شما درون آنرا پر کرده باشید، کدهای شما اجرا خواهند شد.

 

سورس برنامه:

می توانید سورس این قسمت و قسمت قبل را از آدرس زیر دانلود کنید:

http://dl1.uncocoder.com/free/source/AndroidCourse_v9.zip

 

توصیه ها:

- بسیار بسیار بسیار روی Thread ها و AsyncTask ها تمرین کنید چون به کرات در پروژه استفاده خواهند شد. سعی کنید با مثالهای مختلف خود را بیازمایید.

- سعی کنید هر مثالی که با Thread انجام می دهید با AsyncTask هم انجام دهید و بالعکس.

 

مطالب مرتبط

آخرین شرکتهای طرف قرارداد

دارولند

طراحی فروشگاه اینترنتی

آف مکس

طراحی سایت تخفیف گروهی

نمایندگان بیمه ما

طراحی وب سایت و پورتال نمایندگان

پژند الکترونیک

طراحی وب سایت و پرتال

نمایندگی بوش

طراحی وب سایت شرکتی

ایران بزرگ

طراحی وب سایت، اتوماسیون اداری و خدمات شبکه پایگاه خبری ایران بزرگ

ستون فقرات تهران

طراحی پورتال تخصصی پزشکی ستون فقرات تهران

آخرین توییت ها

آخرین مقالات آموزشی

استفاده از تکنولوژی روز دنیا در شرکت فناوران راتا رایان