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)结果:出现自动滚屏效果,可自行查看。