一堆东西,AsyncTask、Handler、Looper、MessageQueue。容我一个一个看过来,该翻译的翻译,该写demo的写demo。当然可能不会写的太过深入,因为每个都展开来的话都可以写一篇博客了,这里以了解为主。
一、Handler
Handler在程序中用的还是比较多的,通常会使用Handler在UI线程和后台线程之间传递消息(Message)。UI线程(通常就是主线程)可以根据得到的消息来更新UI组件。下面是本人对API中Handler文档的翻译,英语水平有限,高手勿喷哈
<译>你可以使用一个Handler对象通过发送或处理Message及Runnable对象来实现和某一线程的MessageQueue交互的功能。每个Handler对象只和某一个线程以及该线程的消息队列交互。当你创建一个线程时,它会被绑定到那个创建它的线程或消息队列上,从那是起,它就可以向那个消息队列发送Message或runnable对象,并在这些对象出队列时处理它们。
Handler主要有两个用处:(1)安排一些计划在未来某个时间点处理的Message或Runnable对象。(2)为其他线程安排一个动作(Message或Runnable)。
安排消息是通过post(Runnable)、postAtTime(Runnable,long)、postDelayed(Runnable,long)、sendEmptyMessage(int)、sendMessage(Message)、sendMessageAtTime(Message,long)、sendMessageDelayed(Message,long)这些方法实现的。其中post系列方法使你能够添加消息队列中添加Runnable,这些Runnable对象将在被接收到时执行。send系列方法使你能够像消息队列中添加包含bundle数据的Message对象,这些Message对象会在Handler的handlerMessage(Message)方法中被处理。</译>
OK,Handler这一块关于什么想队列中添加Message或Runnable都是很简单的,这里就不扯了。上边的红字"为其他线程安排一个动作(Message或Runnable)“,一起到没注意到,下面就写个demo。
新建一个Android工程,在主界面MainActivity中包含一个按钮,单击按钮将启动一个新的线程,在线程中有一个Handler的消息处理,可以在单击事件时从主线程向自定义线程MyThread的消息队列中添加一个动作,详细代码如下:
<span style="font-size:18px;">package com.wly.tasktest;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
public class MainActivity extends Activity implements OnClickListener{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.Enqueue_Action_In_Other_Thread).setOnClickListener(this);
System.out.println(Thread.currentThread().getName()); //syso:main
}
@Override
public void onClick(View v) {
switch(v.getId()) {
case R.id.Enqueue_Action_In_Other_Thread:
MyThread myThread = new MyThread();
myThread.start();
//为另外的线程添加动作
Message msg = new Message();
msg.obj = "来自主线程的一个Message";
myThread.getHandler().sendMessage(msg);
break;
}
}
class MyThread extends Thread {
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
System.out.println("received msg with obj:" + msg.obj.toString()); //syso:Thread-1764
}
};
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
int i = 0;
System.out.println(Thread.currentThread().getName());
while(i < 10) {
Message msg = new Message();
msg.obj = i + "";
handler.sendMessageDelayed(msg, 1000);
i ++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public Handler getHandler() {
return handler;
}
}
}
</span>
单击按钮后的运行结果如下:
二、Looper
Looper从字面意义上是"循环者","循环器",它是一个MessageQueue的管理者,除了主线程有一个默认的Looper对象,而创建Looper对象时会自动创建一个Message Queue对象。 即主线程会默认有一个Looper和Messge Queue对象,而其他非主线程则是没有的。要为非主线程关联Looper对象的话,需要调用prepare方法实现,然后再调用loop方法开始消息的循环处理。下面是Android API中Looper的翻译。
<译>用来为一个线程执行一个消息循环的类。默认情况线程是没有与之交互的消息队列的;想要创建一个这样的消息队列,可以在希望运行消息循环的线程上调用prepare方法,然后调用loop方法来开始消息循环的处理。</译>
三、MessageQueue
从MessageQueue的方法就可以看出MessageQueue其实就是一个队列的数据结构,不过里面放的是Message类型的数据对象。
<译>一个低层次的用来存储Looper所分发的Message的类。Message不是直接被添加到MessageQueue中去的,而是通过和Looper交互MessageQueue.IdleHandler来实现的。你可以通过调用Looper.myQueue()来得到当前线程的MessageQueue。</译>
四、AsyncTask
<译>AsyncTask对UI线程来说是易用、方便的。这个类可以在不手动操作线程或Handler的情况下,将后台操作的结果反馈给UI线程。
AsyncTask的设计目的是作为一个Thread和Handler的帮助类,而不是通常意义上的线程框架。AsyncTask对于短时操作(最多几秒)来说是十分合适的。假如你需要一个耗时很长的线程,那么我们极力推荐你使用java.util.concurrent报下的其他API,如Executor,ThreadPoolExecutror以及FutureTask。</译>
下面是一个AsyncTask的简单Demo,注意AsyncTas是一个抽象类,不能直接实例化,但是可以使用匿名对象,为什么呢?这个我会在本文的最后加以解释。最后代码变成这样了
<span style="font-size:18px;">package com.wly.tasktest;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
public class MainActivity extends Activity implements OnClickListener{
TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.Enqueue_Action_In_Other_Thread).setOnClickListener(this);
System.out.println(Thread.currentThread().getName()); //syso:main
findViewById(R.id.testAsyncTask).setOnClickListener(this);
tv = (TextView)findViewById(R.id.textView1);
}
@Override
public void onClick(View v) {
switch(v.getId()) {
case R.id.Enqueue_Action_In_Other_Thread:
MyThread myThread = new MyThread();
myThread.start();
//为另外的线程添加动作
Message msg = new Message();
msg.obj = "来自主线程的一个Message";
myThread.getHandler().sendMessage(msg);
break;
case R.id.testAsyncTask:
new AsyncTask<Void, String, String>() {
@Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
}
//做一些准备动作
@Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
}
//更新进度
@Override
protected void onProgressUpdate(String... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
tv.setText(values[0].toString());
}
@Override
protected String doInBackground(Void... params) {
int i = 0;
while(i < 10) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
i++;
publishProgress(i + "");
}
return null;
}
}.execute(null);
break;
}
}
/**
* 自定义线程类,用于测试"Handler为其他线程添加Message"
*/
class MyThread extends Thread {
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
System.out.println("received msg with obj:" + msg.obj.toString()); //syso:Thread-1764
}
};
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
int i = 0;
System.out.println(Thread.currentThread().getName());
while(i < 10) {
Message msg = new Message();
msg.obj = i + "";
handler.sendMessageDelayed(msg, 1000);
i ++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public Handler getHandler() {
return handler;
}
}
}
</span>
继续抽象类的匿名对象实例化问题,现在加入有一个抽象类A,包含一个抽象方法void methodA。那么采用new A();这种方法实例化A肯定是不行的,Eclipse也会提示我们实现抽象方法的,但是平时我们可能只是按照Eclipse的提示做而已,没有想为什么,我也是这样。只是今天又多想了一下,为什么呢?
如果我们按照Eclipse的提示采用这样的方法new A() {public void methodA(){ ... } }的方法实例化A的对象。是可以的,因为这种创建对象其实是创建了一个匿名子类的的实例对象,而且该匿名子类又实现了抽象类A中所有的抽象方法,也就是说这个匿名子类不再是一个抽象类,那么当然就可以实例化啦。同样的使用new A();得到的也是匿名子类,不过这个匿名子类没有实现A中的抽象方法,即new A();仍然是一个抽象类,当然不能实例化了。
O啦~~~
转帖请保留出处:http://blog.csdn.net/u011638883/article/details/14123755
谢谢!