首先,说一下怎么用android的多线程机制。
最最重要的,要先普及一下下,一个操作系统,运行起来,都是以进程 process 进行管理的,一般,一个操作系统下的应用,会开一个进程,无论这个进程是怎么开,他肯定会开一个,这个就聊这么多吧。然而一个应用程序,往往在运行的过程中,在于用户的交互过程中,不可避免的,需要有一些异步处理,这个就不用解释了。
这个异步处理,就是多开一个线程 Thread ,在我们进行应用层开发的时候,thread,就像我们程序的手下,帮助处理老大的许多事情。
这里,我必须说一个东西。Android 4.0 之后不能在主线程中请求HTTP请求。
什么是主线程,简单的说,就是画出界面的线程,具体的解释,可以自己去查资料。
CPU在高速的运转的过程中,就像是一条高速公路,而高速公路上的一个个车道,就像是一个又一个进程,在一个车道上,不可能只有一个车,一个进程的很多车就像是一个有一个线程,线程同样按照结构化顺序行走,但是会有他的寿命,一个车道,就是为了把一个又一个车送到自己的位置上。线程怎么管理呢??这就是消息的循环机制了。线程的运行顺序,就是按照消息队列中,消息的顺序进行的。消息的队列有自己的管理器。
1,例如要改变TextView的text,代码如下:
myTextView.post(new Runnable(){
@Override
public void run() {
myTextView.setText("new text");
}
});
android的线程,要么存在后方,要么自己解释显示出来。。谁不会闲着没事,得到一些数据,自己处理着玩,既不保存,也不显示,只是作为CPU的过客,那肯定是不存在的。使用控件的 post 方法,可以很简单令开一个道路。但是,这只是多开一个消息,并不会多一个thread,这个要晓得。
2,Handler
Message message = new Message();
message.what = 0x01010101;
mHandler.sendMessage(message);
//主线程:
mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
if(msg.what == 0x01010101){
myTextView.setText("new text");
}
}
};
一个Handler,就是启动,,操作消息的器具。。可以称之为消息处理去。
不光如此,Handler同样可以 post 或者 postdelay 一个runnable,这个时候,就不需要产生一个消息了。
Handle mhandle = new Handler();
mhandler.post(new Runnable(){
public void run(){
}
});
//或者
mhandler.postDelayed(.....);
和上面的一样,Handler并不会开启一个新的线程,而只是,多开一个消息处理。所以,当我们在Handler 里面进行 Thread.sleep() 的时候,你就会知道,什么叫屏幕假死。
很多视频,书籍上,都说,这种机制是可以处理异步的,,都给我吹牛逼,还得浪费我的学习时间。
3,AsyncTask
AsyncTask定义了三种泛型类型 Params,Progress和Result。
Params 启动任务执行的输入参数,比如HTTP请求的URL。
Progress 后台任务执行的百分比。
Result 后台执行任务最终返回的结果,比如String。
class MyTask extends AsyncTask<Object, Object, Object> {
@Override
//这个方法可以理解为线程的run方法
protected Object doInBackground(Object... params) {
this.publishProgress(null, null, null);
}
@Override
//在doInBackground方法里如果有调用publishProgress方法的话就会运行这个方法
//这个方法就是在线程运行时改变控件属性的方法
protected void onProgressUpdate(Object... values) {
myTextView.setText("new text");
}
}
这里要说的是,Async,是安卓android 提倡的多线程异步处理类。同志们如果感兴趣的话,可以单独查一下,这个类封装的处理比较全面。唯一不太好的是,一个,就是我们敲的代码有点多,嘿嘿,,还有一个,就是这个类在实现的过程中,消耗是比较大的。
4,StrictMode
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
5,下面这一个,就比较高级了。。就是,新建一个线程,在线程中进行消息的处理。
new Thread(runnable).start();
Handler handler = new Handler(){
public void handleMessage(Message msg) {
super.handleMessage(msg);
Bundle data = msg.getData();
String val = data.getString("value");
Log.i(TAG,"请求结果:" + val);
}
}
Runnable runnable = new Runnable(){
public void run() {
// TODO: http request.
Message msg = new Message();
Bundle data = new Bundle();
data.putString("value","请求结果");
msg.setData(data);
handler.sendMessage(msg);
}
}
这个例子,我觉着,要练熟练。你自己看着办吧。
6,这一个,在我们当代的android 开发中,非常重要。。我说的这个当代,是我的现在这个当代。网上很多材料,都是搜索引擎,爬出来几百年前的文章,很多都不能用了。
也许很多年一个,我的这个文章被爬出来,千万别骂我,可能,那个时候 android 已经变成另外一个样子。
下面,是一个多线程情况下,进行通讯的例子。
class myThread extends Thread<span style="white-space:pre"> </span>//可以在是使用的时候,new 出来,然后start 就可以运行了。
{
private EHandler mHandler;
public void run()
{
Looper myLooper, mainLooper;<span style="white-space:pre"> </span><strong><span style="font-size:14px;">//Looper,这是一个非常有用,并且可爱的对象,平时默默无闻,用的时候,都是解决大问题</span></strong>
myLooper = Looper.myLooper();//得到当前线程的Looper
mainLooper = Looper.getMainLooper();//得到UI线程的Looper
String obj;
if(myLooper == null)//判断当前线程是否有消息循环Looper
{
mHandler = new EHandler(mainLooper);
obj = "current thread has no looper!";//当前Looper为空,EHandler用mainLooper对象构造
}
else
{
mHandler = new EHandler(myLooper);//当前Looper不为空,EHandler用当前线程的Looper对象构造
obj = "This is from current thread.";
}
mHandler.removeMessages(0);//清空消息队列里的内容
Message m = mHandler.obtainMessage(1, 1, 1, obj);//这里,用实例化的handler对象,来打包一个消息对象。
mHandler.sendMessage(m);//发送消息
}
}
//看到没有,用Looper来初始化构造一个Handler 。可以得到在某一个线程上的Handler 。
class EHandler extends Handler
{
public EHandler(Looper looper)
{
super(looper);
}
public void handleMessage(Message msg) //消息处理函数
{
tv.setText((String)msg.obj);//设置TextView内容
}
}
}
太java 的多线程机制中,很多类和借口,都非常值得我们细细斟酌使用。。就奔着用着舒服,也值得我们这样做。