線程通訊-----AsynTask

   AsynTask是Handler的輕量級形式,他能夠用做專門的處理耗時操做。有時咱們會發現,在主線程睡眠的時候,你執行別的操做的時候會出現「卡屏」狀態,這樣的效果極爲很差。可是咱們能夠經過AsynTask去解決這個問題。java

「卡屏」現象異步

   (1)建立自定義類對象 模擬耗時操做   ide

public class Mythread {//自定義類
    public static void sleepy(){
        try {
            Thread.sleep(5000);//模擬耗時操做
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

   (2)在主線程中單擊start按鈕時調用,單擊print按鈕時輸出hello到控制檯this

public class MainActivity extends Activity implements OnClickListener{
    private Button startBtn,printbtn;//聲明按鈕
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //查找資源
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
        startBtn = (Button) findViewById(R.id.start);
        printbtn  =(Button) findViewById(R.id.printBtn);
        //爲按鈕添加監聽
        startBtn.setOnClickListener(this);
        printbtn.setOnClickListener(this);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
    }
    @Override
    public void onClick(View arg0) {
        switch (arg0.getId()) {
        case R.id.start:
            //自定義線程類睡眠方法的調用
            Mythread.sleepy();//這樣使用的話會出現卡屏的狀態
            break;
        case R.id.printBtn:
            System.out.println("hello");
            break;
        }
    }
}

(3)結果:spa

若直接單擊print方法沒問題,後臺輸出正常
線程

◆但若先單擊start按鈕,在單擊任意次數的print按鈕,都不會立刻看見效果,而是等待睡眠5秒以後一併輸出。對象

   如何解決「卡屏」現象?先來看看AsynTast吧。
blog

   一:原理
繼承

    其實啓動AsynTask,就至關於又開闢了一個線程,在這個線程中專門處理耗時操做,從而不會耽誤用戶主UI的其餘操做,提升用戶體驗。資源

   二:建立及經常使用方法

   1:建立

   繼承自AsynTask類,但有三個泛型,這裏要注意一下,泛型用的全是包裝類。

class MyAsynTask extends AsyncTask<泛型1, 泛型2, 泛型3>

   2:經常使用方法及參數

(1)泛型3 doInBackground(泛型1):核心的處理耗時工做。方法的返回值類型:泛型3;參數類型:泛型1。參數的值來自於主界面啓動AsynTask時傳遞的值。

   (2)onPostExecute(泛型3):異步結束時執行的方法。參數的值來自於doInBackground的返回值,所以參數的類型爲:泛型3.

   (3)onPreExecute():在異步開始時就會執行的方法,也就是會在doInBackground方法執行以前執行。

   (4)onProgressUpdate(泛型2):與主線程UI的交互。參數類型:泛型2。參數的值來源於在doInBackground方法中經過publishProgress傳遞過來的值。

   三:如何解決「卡屏現象」?

   (1)建立繼承自AsynTask的類,重寫其中的doInBackground方法

   (2)在doInBackground方法中調用耗時操做

public class MyAsynTask extends AsyncTask<Void, Void, String>{
    @Override
    protected String doInVoid...  params) {
        Mythread.sleepy();//專門處理耗時 的操做
        return null;
    }
}

   (3)在主線程start按鈕的監聽中,再也不是直接調用耗時操做,而是建立AsynTask對象,經過execute啓動線程

case R.id.start:
                                                                                                                                                                                                                                                                                                                                                                                      
            //MyAsynTask myAsynTask = new MyAsynTask();
            //myAsynTask.execute();//啓動AsynTask,這樣就不會出現卡屏的狀態了
            break;

   (4)結果:這是不管怎樣單擊,什麼順序單擊均不會出現「卡屏」現象。

    四:AsynTask的應用

   實現的功能:仍然是上一篇博文中進度條與TextView控件的同步使用。

   (1)建立類繼承自AsynTask,注意泛型類型的添加

   (2)提供成員屬性(主界面上要同步的控件),添加構造方法

private TextView tv;//成員變量
    private ProgressBar bar;//成員變量
    public MyAsynTask(TextView tv, ProgressBar bar) {
        super();
        this.tv = tv;
        this.bar = bar;
    }

   (3)重寫onPreExecute()方法:讓他給出提示「異步開始了」

// 在異步開始時就會執行的方法,也就是會在doInBackground方法執行以前執行
    @Override
    protected void onPreExecute() {
        tv.setText("異步開始了");
        super.onPreExecute();
    }

   (4)重寫doInBackground()方法:完成值的更新

/**
     *  核心處理方法,它的參數有主界面的啓動時傳遞進來
     *  返回類型:泛型3
     *  參數類型:泛型1
     */
    @Override
    protected String doInString...  params) {
        int count = 0;//初始化變量
        for (count = 0; count <= 100; count++) {
            try {
                Thread.sleep(100);//每一個一秒count加1
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 傳給了onProgressUpdate方法
            publishProgress(count);//這個count將會傳給onProgressUpdate中參數
        }
        return count+"";//返回值給onPostExecute方法,以便於結束的判斷
    }

   (5)重寫onPostExecute()方法:結束時給出提示信息

// 異步結束時執行的方法,參數來自於doInBackground的返回值,也就是這裏的vcount;
@Override
protected void onPostExecute(String result) {
    if (result != null) {
        tv.setText("異步結束了,當前的I值爲:" + result+"");
    }
    super.onPostExecute(result);
}

   (6)重寫onProgressUpdate()方法:更新主UI

// 與主線程UI的交互,參數來自於doInBackground方法中的publishProgress的參數值
@Override
protected void onProgressUpdate(Integer... values) {
    bar.setProgress(values[0]);//更新主Ui中的進度條
    tv.setText(values[0] + "");//更新主UI中的文本框
    super.onProgressUpdate(values);
}

   (7)主UI中爲按鈕添加監聽,啓動AsynTask

btn.setOnClickListener(new OnClickListener() {
                                                
            @Override
            public void onClick(View v) {
                //實例化AsynTask對象
            MyAsynTask myAsynTask = new MyAsynTask(tv, bar);
            //啓動AsynTask
            myAsynTask.execute();
                                                    
            }

   (8)結果


   其中AsynTask的幾個方法的返回值與參數類型還得本身繼續的研究研究啊。。有點蒙。。

相關文章
相關標籤/搜索