Android里面的界面的修改,不能直接用一个Thread的方法体来修改。每个Activity都有一个系统主线程一直在循环监听该界面数据是否有什么变化。如果直接新建一个线程来修改界面就会造成多个线程不同步的现象,因此Android引入了Handler来处理多线程对界面进行的操作,个人理解Handler就相当于一个消息池,一旦有界面改变的消息就发送给系统界面主线程让其进行处理。
Handler对界面修改的消息处理大概有这么两种方式:
1、新建一个Runnable对象,但是Runnable()对象里面不要死循环,而是在主线程体里面用死循环来不断的监视界面变化,并用Handler对象来发送该消息
Runnable rb=new Runnable() { public void run() { position=(position++)%16+1; System.out.println("===position: "+(position-1)); if(position!=1) { vcbutton.elementAt(position-2).setImageResource(R.drawable.a22_02); } else vcbutton.elementAt(15).setImageResource(R.drawable.a22_02); vcbutton.elementAt(position-1).setImageResource(R.drawable.a22); } };
在主线程体里面循环监听:
buttonstart.setOnClickListener(new OnClickListener() { public void onClick(View arg0) { if(count>0) { // TODO Auto-generated method stub //每次重新开始的时候把中间的图片显示为问好 centerbutton.setBackgroundResource(R.drawable.a21); //点击开始的时候把当前位置的前景图片修改一下 vcbutton.elementAt(position-1).setImageResource(R.drawable.a22_02); new Thread() { public void run() { isstop=false; for(;;) { //这里必须延迟发送,不染的话屏幕的刷新速度没有那么快就会出现延迟卡屏 handler.postDelayed(rb,250); handler.post(rb2); System.out.println("=====================position: "+position); try { Thread.sleep(sleeptime); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } //这里遇到了一个问题,handler发送消息有延迟,屏幕刷新不够快 sleeptime+=addtime; addtime+=5; if(sleeptime>=500) { isstop=true; isjieshu=true; handler.post(rb2); sleeptime=50; addtime=1; break; } } } }.start(); }}});
这里还遇到了一个很有趣的问题,那就是屏幕刷新的问题。如果有消息就发送给主线程的话可能会由于界面屏幕刷新速度跟不上而出现延迟。因此最好在发送消息的时候给赋予足够的延迟时间
2、重写Handler的处理消息的方法,在该方法中对界面个元素进行修改
class MyHandler extends Handler { @Override public void handleMessage(Message msg) { super.handleMessage(msg); {// 444 第三种方法的消息处理 number++; tv1.setText(number + "");// 修改TextView内容 }
在主线程里面循环监听,将消息添加到消息池中:
Message msg = myHandler.obtainMessage(); // // 吧Message对象添加进Handler的Message容器 myHandler.sendMessage(msg);
为了让我们的程序更加严谨:确保在Activity生命周期结束的时候我们自己写的界面更新线程能正确退出,通常在Activity的ondestroy函数里面添加消息移除函数
handler.removeCallbacks(runnable);