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)結果