一、一般我们都会在子线程完成一些耗时的操作。
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),可以通过传递上下文实现调用;
效果图片: