Android中規定:
java
(1)不能阻礙UI主線程,達到5秒以上會自動報錯(ANR應用程序沒法響應)
android
(2)不要讓UI主線程以外的線程去更新主UI,不然繪世界報錯
ide
例:post
public class MainActivity extends Activity { private TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv = (TextView) findViewById(R.id.textView1); findViewById(R.id.strat).setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { thread.start();//單擊按鈕啓動一個子線程 } }); } Thread thread = new Thread(){ public void run() { tv.setText("hello");//在子線程中更新UI }; }; } |
那麼如何解決上面出現的問題呢?能夠用咱們的Handler
spa
一:Handler
線程
Handler對象的使用和線程相關,也就是說,他會綁定一個線程,讓這個耗時的操做在新建的線程上完成,而達到不阻礙主UI線程的操做,從而達到線程之間的通訊。
對象
二:用途
blog
(1)發送消息
資源
可使用post(runnable對象)、postDelay(runnable對象,int時間間隔)等方法發送Runnable對象,從而與主UI線程進行通訊。
可使用sendMessage(Message對象)、sendMessage(Message對象,int時間間隔)等方法發送Message對象,從而與主UI線程進行通訊。
(2)接收消息
可使用handleMessage(Message對象)方法處理接收穫得的Message
三:經常使用的Handler方法
(1)post(runnable對象):啓動線程,在線程中處理耗時操做
(2)postDelay(runnable對象,int時間間隔): 每隔多長時間執行一次線程
(3)sendMessage(Message對象):發送消息給主線程
(4)handleMessage(Message對象):接收消息,並更新UI
四:發送Runnable對象,從而與主UI線程進行通訊
◆功能:在新建的線程中,完成計數操做,並更新主UI上的控件。
(1)建立Handler對象,並實例化
// 建立Handler對象 private Handler handler = new Handler(); |
(2)建立線程,完成計數操做,並更新主UI
// 建立線程 Runnable runnable = new Runnable() { int count = 0; @Override public void run() { count++; tv.setText(count + "");// 更新UI // System.out.println("我是子線程"); handler.postDelayed(runnable, 1000);// 每隔一秒執行一次線程 } }; |
(3)主界面添加按鈕。啓動按鈕: 經過handler啓動子線程;中止按鈕:移除線程對象
private Button startBtn, stopBtn;// 聲明按鈕 private TextView tv;// 聲明文本框 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 查找資源 startBtn = (Button) findViewById(R.id.start); stopBtn = (Button) findViewById(R.id.stop); tv = (TextView) findViewById(R.id.textView1); // 爲按鈕添加監聽 startBtn.setOnClickListener(this); stopBtn.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.start: handler.post(runnable);// 經過Handler啓動線程 break; case R.id.stop: // 移除子線程 handler.removeCallbacks(runnable); break; } } |
◆結果:單擊start按鈕,主UI開始更新,單擊stop時候中止更新。
五:使用sendMessage(Message對象)和handleMessage(Message對象)實現Message對象的接受與發送
功能:這裏利用的sendMessage發送消息,用handleMessage方法去更新UI。讓ProgressBar自動更新,在TextView中實時顯示進度條中的值。
◆具體實現:
(1)建立handler對象和子線程,用Message封裝消息,經過handler的sendMessage方法發送消息。
Runnable runnable = new Runnable() { @Override public void run() { count += 10; // Message message = new Message();// 建立消息的承載對象這樣會建立不少個Message對象 //建立Message對象承載信息 Message message = handler.obtainMessage();//這樣建立的Message只會有一個 //Message存儲消息 message.arg1 = count;// 承載數據 handler.sendMessage(message);// 發送消息 handler.postDelayed(runnable, 1000);// 每隔一秒執行一次線程 } }; |
(2)實例化handler對象,實現其中的handleMessage方法,接收消息,更新UI
private Handler handler = new Handler() { public void handleMessage(Message msg) {// 接受消息 pgbar.setProgress(msg.arg1);// 更新主界面的UI tv.setText(msg.arg1+""); if (msg.arg1 ==100) {// 作判斷 count=0; tv.setText("到頭了。。"); handler.removeCallbacks(runnable);// 移除UI } }; }; |
(3)在主界面中給按鈕添加監聽,經過Handler對象以啓動和移除線程
private ProgressBar pgbar; private TextView tv; private int count = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); pgbar = (ProgressBar) findViewById(R.id.progressBar1); tv = (TextView) findViewById(R.id.textView1); findViewById(R.id.start).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { handler.post(runnable);// 啓動線程 } }); findViewById(R.id.stop).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { handler.removeCallbacks(runnable);// 移除線程 } }); } |
結果:單擊開始按鈕,滾動條與TextView同時更新,且同步,任意位置單擊按鈕時,都可以中止。
六:運用Handler實現屏幕的自動滾屏
(1)在主界面上添加一個ScrollView,在其中的的LinearLayout下添加一個TextView,裏面添加足夠多的文字
(2)在主界面上實例化Handler對象,在其中的handleMessage方法中實現滾屏效果,具體以下
handler = new Handler() {//實例化Handler對象 public void handleMessage(android.os.Message msg) { if (msg.what == 1) {//判斷消息的標示 int startPosition = sv.getScrollY();//獲得當前的Y值 if (startPosition == 0 || startPosition != lastPosition) {//判斷條件,看看是否是到達底部或者是否是開始位置 lastPosition = sv.getScrollY();//如果,則得到Y值 sv.scrollBy(0, 2);//X座標不變,Y值每次加2 實現豎屏滾動 handler.sendEmptyMessageDelayed(1, 100);//發送消息 } } }; }; handler.sendEmptyMessageDelayed(1, 100);//發送消息標識爲1 的消息,每一個0.1秒發送一個消息 |
(3)結果:出現自動滾屏效果,可自行查看。