首页 > 代码库 > 子线程更新UI界面的2种方法
子线程更新UI界面的2种方法
一、一般我们都会在子线程完成一些耗时的操作。
1、Android中消息机制:
2、知识点:
Message:消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理。
Handler:处理者,负责Message的发送及处理。使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理,例如更新UI等。
MessageQueue:消息队列,用来存放Handler发送过来的消息,并按照FIFO规则执行。当然,存放Message并非实际意义的保存,而是将Message以链表的方式串联起来的,等待Looper的抽取。
Looper:消息泵,不断地从MessageQueue中抽取Message执行。因此,一个MessageQueue需要一个Looper。
Thread:线程,负责调度整个消息循环,即消息循环的执行场所。
子线程更新uI界面方法一:用Handler
1、我们将在上张AsyncTask的案例中进行操作,我们将之前点击调用事件中的调用方法注释。
public class MainActivity extends Activity { private SimpleAdapter sa; private Button btn; private TextView tv; private List<Userinfos> list=new ArrayList<Userinfos>(); private BaseAdapter adapter; private ListView lv; private Runnable doInBackground1; private Runnable doInBackground2; private Runnable doInBackground3; private Handler handler; private Thread th; private Thread th2; @Override protected void onCreate(Bundle savedInstanceState) { //这里是UI主线程 super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); for (int i = 0; i < 5; i++) { Userinfos u = new Userinfos(); u.setName("小明"+i); u.setSex("男"+i); list.add(u); } lv=(ListView)this.findViewById(R.id.listView1); tv=(TextView)findViewById(R.id.textView1); btn=(Button)findViewById(R.id.button1); btn.setOnClickListener(new OnClickListener(){ //模拟数据访问产生数据 @Override public void onClick(View v) { // TODO Auto-generated method stub /*Take tk=new Take(MainActivity.this);//同步任务 tk.execute(list,adapter);//参数是传给doInBackground*/ Thread t1=new Thread(doInBackground1); t1.start(); Thread t2=new Thread(doInBackground2); t2.start(); Thread t3=new Thread( doInBackground3); t3.start(); }});
handler=new Handler() { public void handleMessage(android.os.Message msg) { int what=msg.what; Log.i("handler","已经收到消息,消息what:"+what+",id:"+Thread.currentThread().getId()); if(what==1) { Log.i("handler已接受到消息",""+what); tv.setText("子线程一"); } if(what==2) { Log.i("handler已接受到消息",""+what); adapter.notifyDataSetChanged(); } if(what==3) { Log.i("handler已接受到消息",""+what); adapter.notifyDataSetChanged(); btn.setText("子线程三"); } }; }; //子线程一 doInBackground1=new Runnable(){ @Override public void run() { // TODO Auto-generated method stub try { Thread.sleep(3000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } //1.访问数据库或者互联网,不在UI进程,所以不卡 Message msg=new Message(); //对消息一个识别号,便于handler能够识别 msg.what=1; handler.sendMessage(msg); Log.i("dd","子线程一已发送消息给handler"); }}; //子线程二 doInBackground2=new Runnable(){ @Override public void run() { // TODO Auto-generated method stub try { Thread.sleep(5000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } Message mge=new Message(); mge.what=2; handler.sendMessageDelayed(mge,200); for(Userinfos us:list) { us.setName("李丽"); } Log.i("dd","子线程二已发送消息给handler"); }}; //子线程三 doInBackground3=new Runnable() { @Override public void run() { // TODO Auto-generated method stub try { Thread.sleep(9000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } Message mge=new Message(); mge.what=3; handler.sendMessageDelayed(mge,200); for(Userinfos us:list) { us.setSex("女"); } Log.i("dd","子线程三已发送消息给handler"); }};
1、子线程发消息,通知Handler完成UI更新:
2、Handler的handleMessage方法进行消息处理,接收到消息进行UI界面更新。
注:方法一的Handler对象必须定义在主线程中,如果是多个类直接互相调用,就不是很方便,需要传递content对象或通过接口调用。
效果图:
子线程更新uI界面方法二:用用Activity对象的runOnUiThread方法更新
通过runOnUiThread方法进行UI界面更新
public void onClick(View v) { // TODO Auto-generated method stub /*Take tk=new Take(MainActivity.this);//同步任务 tk.execute(list,adapter);//参数是传给doInBackground*/ /*Thread t1=new Thread(doInBackground1); t1.start(); Thread t2=new Thread(doInBackground2); t2.start(); Thread t3=new Thread( doInBackground3); t3.start();*/ th.start(); th2.start(); }});
th= new Thread() { @Override public void run() { //这儿是耗时操作,完成之后更新UI; runOnUiThread(new Runnable() { //更新UI @Override public void run() { // TODO Auto-generated method stub btn.setText("runOnUiThread子线程一"); } }); super.run(); } }; th2=new Thread() { public void run() { runOnUiThread(new Runnable() { @Override public void run() { try { Thread.sleep(3000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } // TODO Auto-generated method stub tv.setText("runOnUiThread子线程二"); } }); }; };
1、通过runOnUiThread方法New 一个Runnable实现run方法进行UI界面更新。
如果在非上下文类中(Activity),可以通过传递上下文实现调用;
效果图片:
子线程更新UI界面的2种方法