建议基于下载案例进行思考,将下面的知识点往下载案例上面靠,思考下载案例中运用到的是哪个知识点,哪个原理会非常好的理解。
目录
一、服务简介
服务是Android中的四大组件之一。服务就是运行在后台的,就是说即使用户在使用其它的app,这个服务里面的代码也可以继续执行,同时运行(郭神:服务适合去执行那些不需要和用户交互但是需要长期执行的任务,服务不依赖于任何用户的界面)
按照以上的理解,服务应该就是运行在子线程当中的,是的服务中的一些代码确实是应该允许在子线程当中的,但是并不是自动允许在子线程当中的,是需要我们手动去开启一个线程放入相关代码的!
同时需要注意,服务是依赖于创建这个服务的进程的,如果这个进程关闭了之后,那么这个服务也会随之关闭的!
记住一点定义非常重要,服务也是属于四大组件之一,地位也是非常高的,和activity的地位差不多,但是依赖于activity(在activiy中创建),生命周期也是和activity差不多的,但是启动该service的activity被销毁之后该service也会被销毁。<---- 理解错误
二、Android中的多线程编程
为什么要在服务这一章节学这个多线程编程呢?
因为服务一般是运行在后台的,而当前的app程序是有一个主线程的,然后服务因为经常需要执行耗时操作(比如说联网操作,下载……),如果这些耗时操作放在主线程当中,会阻塞主线程,导致程序崩溃。因此如果服务需要执行这些动作的话就必须要将它们放在一个新的线程里面,我们需要在服务的内部手动创建线程。
2.1 线程的基本用法
线程的基本用法就三种
(1)定义一个类继承Thread,重写run方法。然后new出这个类的实例。
public class MyThread extends Thread {
@Override
public void run() {
//线程执行的相关代码
}
}
//…………
MyThread myThread = new MyThread();
myThread.start();
(2)定义一个类实现runnable接口
public class MyThread implements Runnable {
@Override
public void run() {
//线程代码
}
}
//创建出这个线程并且启动线程
MyThread myThread = new MyThread();
Thread thread = new Thread(myThread);
thread.start();
(3)匿名内部类的形式---最常用
new Thread(new Runnable() {
@Override
public void run() {
//线程执行的代码
}
}).start();
2.2 在子线程中更新ui
此处在抄代码的过程中有疑问?为什么使用LinearLayout布局在分支线程中更新ui是可以的,而在RelativeLayout中却是不行的?
Android中规定更新ui只能在主线程当中,子线程当中是不能更新ui的,因此Android中提供了一套“异步消息处理机制”来执行这种操作。
固定的流程:
(1) 在主线程当中new出Handler实例对象,并且重写里面的HandleMessage方法,编写handlerMessage方法,根据参数Message中携带的数据来执行相关的操作,一般就是在这里执行更新ui的主线程操作,因为这个对象是在主线程当中创建并且方法也是在主线程当中执行的,因此更新ui的操作肯定也是在主线程当中执行的!
(2) 在分支线程创建一个Message对象,这个message对象可以携带一些耗时操作之后的结果(可以携带很多东西的,int,Object……),然后通过Handler对象将这条message发送出去,然后handlerMessage(Message msg)方法进行接收,然后根据这个msg所携带的相关数据(结果)进行相应的判断处理。
代码如下所示:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
public static final int UPDATE_TEXT = 1;
TextView text;
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case UPDATE_TEXT:
text.setText("Nice to meet you");
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button changeText = findViewById(R.id.changeText);
changeText.setOnClickListener(this);
text = findViewById(R.id.text_view);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.changeText:
new Thread(new Runnable() {
@Override
public void run() {
//text.setText("nice to meet you");
Message message = new Message();
message.what = UPDATE_TEXT;
handler.sendMessage(message);
}
}).start();
break;
default:
break;
}
}
}
2.3 子线程中更新ui的原理(异步消息处理机制原理)
明确这套异步消息处理机制有四个组成部分:
(1)Message:线程之间传递的信息,用于不同线程之间传递数据的,可以携带数据。message.what携带数据,message.arg1和message.arg2携带整型数据,message.obj携带一个object对象。
(2)Handler:发送和处理Message的,利用sendMessage()发送消息,handlerMessage()处理消息;
(3)MessageQueue:存放所有Handler发送过来的消息,这里面的消息会一直被等待处理ÿ