您的位置:首页 > 移动开发 > Android开发

《android开发-从小工到专家》学习记录(六)

2018-02-14 01:14 381 查看
今天主要学习了android中的多线程;

先简单介绍一下android 开发中,一个activity所处的线程为UI线程,也就是我们处理onCreate函数的线程,也可以称为主线程,在这个线程中是不允许进行耗时操作的,也就是说最好不要阻塞这个线程,,而我们平常开发往往会进行一些比如网络请求之类的操作,既然这些操作不能放在UI线程中,那我们自然想到我们可以开启一个子线程完成这些工作,然而问题又来了,子线程中是不能修改UI的。既然这样,那我们该如何实现一个耗时操作的请求并且改变UI呢,一个方法是我在点击打开链接中提到的使用AsyncTask的方法进行异步操作,另一种就是android提供的消息处理手段handler-looper-message机制;

其实这个机制很简单,但是很多书上和资料上都写的太绕了,所以我觉得作为一个程序员,最好的学习方法是看代码而不是看别人提供的解释文字,如下代码:

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
/*代码省略*/
private Thread mThread;
private Handler handler = new Handler(){
public void handleMessage(android.os.Message msg)
{
switch(msg.what)
{
case 100:
/*
处理代码
*/
break;
case 101:

/*
处理代码
*/
break; default: break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); requestPermission(this); //requestReadExternalPermission(); init(); } private void init() { /*处理代码*/ }
//更新界面函数
private void UpdateProgress()
{
if(mThread==null) {
mThread = new Thread() {
public void run() {
while (!interrupted()) {
int currentPosition = binder.getCurrentPositon();
Message message = Message.obtain();
message.obj = currentPosition;
//message.arg1 = binder.getId();
if (flag == 0) {
message.what = 100;
} else {
message.what = 101;
}
handler.sendMessage(message);
}
}

;
};
mThread.start();
}
}
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
/*代码省略*/
private Thread mThread;
private Handler handler = new Handler(){
public void handleMessage(android.os.Message msg)
{
switch(msg.what)
{
case 100:
/*
处理代码
*/
break;
case 101:

/*
处理代码
*/
break; default: break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); requestPermission(this); //requestReadExternalPermission(); init(); } private void init() { /*处理代码*/ }
//更新界面函数
private void UpdateProgress()
{
if(mThread==null) {
mThread = new Thread() {
public void run() {
while (!interrupted()) {
int currentPosition = binder.getCurrentPositon();
Message message = Message.obtain();
message.obj = currentPosition;
//message.arg1 = binder.getId();
if (flag == 0) {
message.what = 100;
} else {
message.what = 101;
}
handler.sendMessage(message);
}
}

;
};
mThread.start();
}
}


上述是我截取的自己项目中的部分代码,删了很多,留下了主要部分,可以看出,当我们想去执行一个耗时操作的时候,我们的做法是开启一个子线程完成耗时操作,这样的思路完全没有问题,注意,耗时操作的完成全是由子线程完成的,跟什么handler,message,looper都没有关系;而在完成耗时操作之后我们想给UI界面进行一些修改,这才用到了上述说的消息传递机制,代码中的做法是,现在UI线程中NEW 了一个handler,重写了handleMessage方法,该方法接受一个message对象,并根据message对象中的某些字段比如.obj中的值,进行相应的处理;而message对象中的值在子线程中进行赋予,并在子线程中使用handler.sendMessage(msg)的方法发送message对象;以上就完成了一个子线程消息发送给UI线程进行处理的过程,其中需要注意的是子线程中发送对象的方法是handler.sendMessage(msg),这个handler对象创建在UI线程中,并且最终就是由这个handler中的handlermessage方法进行处理的,发送和接受是一个handler对象,handler中的操作最终表现为改变了UI界面,这也就说明了handler实际上是与UI线程绑定的,统一的说,handler需要与一个线程进行关联。

写到这里好像发现,还有一个looper完全没有提及,这东西是干什么的呢?这涉及到sendMessage之后,消息会立即被Handler处理吗?如果是这样的话,如果好几个子线程都调用这个sendMessage,handler要怎么处理呢,同时接受很多个message对象?显然是不应该的,为了避免这种情况的发送,在线程中会创建一个messagequeue---消息队列,进行对Message对象的管理,将接收到的message对象放入队列中,以先进先出的模式进行处理message,这时候就引出了我们所说的looper,大家不要刻意去理解一个英文单词,我们只需要把它当成一个单词就好,不然会自找麻烦的,loop的翻译是一个循环,但是它在这里不要当成一个循环者去理解它,我建议大家在没读源代码之前把它当成message管理者去理解即可,它负责的工作是message队列的出入,我们接收到的message对象形成了message队列,而looper就是这个队列的发动机,looper中的loop函数中实现了一个死循环,它的工作是如果message队列中有对象,就对其进行处理,现在理解为什么命名为Looper了吧,因为它当中有一个死循环。

而如果要说这机制中的核心点,我认为是message对象,我们说过,一个消息处理机制需要去对应一个线程,不然就乱套了,这是显而易见的。其实要想知道怎么实现的与线程关联,读源代码会很清晰,这里我没贴出代码,简单进行一些叙述:1.handler中主要是实现了对于message所带信息的处理方法,并且在handler的构造方法中会获取looper对象,实现handler与Looper的关联;2.Looper作为消息队列的管理者,其中自然持有这消息队列;3.JAVA线程中有一个叫sThreadLocal的局部变量,此对象的set()方法实现了为当前线程设置一个Looper的功能;所以综上,消息处理机制与线程的关联实质是looper与线程的关联,looper对消息队列的持有以及handler与Looper的关联三个方面结合实现的。(所以为什么在子线程中如果没有looper对象的时候直接创建handler会报错呢?因为handler的构造方法里需要获取一个Looper对象!)

除此之外再说一点,android是怎么实现message与handler的关联处理的呢?其实message类中有一个Handler成员,内部变量名为target,因为handler、message已经与线程对应了,所以当handler作为message中的一个成员存在的时候,消息队列处理就变得很简单,只需要使用msg.target.dispatchMessage(msg)方法即可,dispatchMessage为一个分发的方法,因为handler有接受callback与直接处理两种消息处理形式。

以上就是android消息处理机制的一些内容,今天还学了很多关于JAVA多线程的知识,然而现在已经很晚了,该休息了,就写到这吧。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: