什么是服务?


服务(service)是Android中实现程序后台运行的解决方案,它非常适合去执行那些不需要和用户交互而且还要求长期运行的任务。服务的运行不依赖任何的用户界面,即使应用被切换到后台或者用户重新启动了另一个程序,服务还是能够保持正常运行的。

不过需要注意的是,服务并不是运行在一个独立的进程里面,而是依赖于创建服务时所在的程序的进程,当某个程序的进程被杀掉的时候,所有依赖于这个进程的服务就都会被停掉!

当然也不能被服务的后台概念所迷惑,实际上所有的服务并不会自动开启线程,所有的代码都是默认运行在主线程当中的,也就是说我们需要在服务的内部手动的床架子线程,并在这里执行具体的任务,否则就有可能出现主线程被阻塞的情况。

Android多线程得先知道


在探究服务这点上我们首先要明白的是安卓的多线程,我们这里学习的也只是安卓多线程最基本以及简单的东西,虽然自己的水平也只是学习入门的水平,但是按照我对多线程这该耐心的理解,要仔细研究的话多线程里面的东西是不会少的,比如说线程之间的通信,由线程安全牵扯出的线程的各种锁等等,看最简单的,Android线程的基本用法:

// 线程的第一种写法,直接继承自Thread自定义我们的MyThread类
class MyThread extends Thread{ @Override
public void run() {
super.run();
// 具体的逻辑处理 }
}
/*
*
* 那我们改如何使用这个多线程呢?
* 其实也很简单,我们直接new 一个 MyThread类
* 然后调用它的start()方法,这样run方法里面的具体的操作就在子线程中执行了
* */

我们还有更好的方式来写多线程,这种继承的方式耦合度有点低,更多的时候我们是选择实现Runnable()接口的方式来定义一个线程,要是我们使用了这个方法来实现多线程之后我们调用的方式也就要发生改变

大概的思路还是: 我们初始化一个MyThread类,这个类实现一下 Runnable() 接口

我们再初始化一个Thread对象,但是在初始化的时候需要我们把New出来的MyThread类对象传入,在之后直接调用start()方法

那有没有更简单的方式来写呢?当然是有,也会说我们最常见的,要是你不想再去定义一个类,我们就使用下面匿名类的方式来写,代码如下:

// 使用匿名类的方式使用多线程
new Thread(new Runnable() {
@Override
public void run() { Log.d("ServiceMainActivity","我是在其他线程执行的任务")
}
}).start();

不安全的线程


Android的线程和我们iOS的线程是一样的也是不安全的,所以想要在子线程中更新UI是办不到的,这一点和我们iOS的一样,这时候就涉及到主线程和子线程之间的通信,该如何处理呢?

下面是我们在异步线程里面做的操作,在完成我们发送消息,在主线程接收到消息只有处理任务:

   // 线程的第一种写法,直接继承自Thread自定义我们的MyThread类
class MyThread extends Thread{ @Override
public void run() {
super.run(); // 具体的逻辑处理
Message message = new Message();
message.what = UPDATE_TEXT;
handler.sendMessage(message);
}
}

下面是我们在主线程做的操纵:

    public  static final int UPDATE_TEXT = 1;

    private  Handler handler = new Handler(){
// 线程的第一种写法,直接继承自Thread自定义我们的MyThread类
class MyThread extends Thread{ @Override
public void run() {
super.run(); // 具体的逻辑处理
Message message = new Message();
message.what = UPDATE_TEXT;
handler.sendMessage(message);
}
}
};

这样我们在异步和主线程之间建立起了通讯,其实在主线程和异步线程之间建立通讯的方式还有其他的方式,我们在接着看异步消息处理机制。

异步消息处理机制


在Android中的异步消息处理主要有四个部分组成: Message   Handler   MessageQueue    Looper

在上一节中,前面的Message和Handler在上一节中我们已经接触过了,而MessageQueue和Looper我们暂时还没有接触到,下面我们就对着四部分一点点的剖析一下。

1、Message

Message是在线程之间传递的消息,他可以在内部携带少量的信息,用于在不同的线程之间交换数据,前面的时候我们用到的只是简单的what字段,除此之外可以使用arg1和arg2字段类携带一些整形数据,使用obj字段可以携带一个object对象。

2、Handler

Handler 顾明思议也就是处理者的意思,它也主要是用于发送和处理消息的,发送消息一般都是使用Handler的sendMessage()方法,而发出的消息经过一系列的辗转处理后,最终会传递到Handler的handleMessage()方法。

3、MessageQueue

MessageQueue 是消息队列的意思,它主要用于存放所有通过Handler发送的消息,这部分消息会一直存放在消息队列里面,等待被处理,每个线程中只会有一个MessageQueue对象。

4、Looper

Looper是每个线程中的MessageQueue的管家,调用Looper的loop()方法,就会进入到一个无限循环当中,然后每当发现MessageQueue中存放在一条消息,就会将它取出,并传递到Handler的handlerMessage()方法中,每一个线程中也只会有一个Looper对象。

我们了解了他们的基本概念之后我们也就可以看看下面的这张图了,Android异步消息处理流程图,通过这张流程图我们乐意更好的理解一下这个Android异步消息的处理流程,理解他们四个之间的关系,更好的裂解一下他们的概念:

 AsyncTask


为了更加方便的我们在子线程中对UI进行操作,Android还提供了拧一个好用的工具,比如AsyncTask,借助它既是你对异步消息的处理机制完全不了解,也可以十分简单的从子线程切换到主线程,当然他背后的实现原理还是使用了异步消息的处理机制的,只是Android帮我们分装好了而已。

AsyncTask首先是一个抽象类,所以我们想要使用它就必须创建一个子类去继承它,在继承的时候我们可以为AsyncTask类指定三个泛型参数:

* params  可用于在后台任务中使用

* Progress 后台执行任务的时候,界面要是要显示进度,可以使用这里指定的泛型作为进度单位

* Result  如果需要对结果进行参会,则使用这里指定的泛型作为返回值类型

除了上面的这三个参数,还有四个方法使我们在继承之后需要重写的:

1、onPreExecute()                  后台任务开始执行之前调用,用于进行一些界面上的初始化操作

2、doInBackground()              耗时操作

3、onProgressUpdate()           UI的操作

4、onPostExecute()                任务执行完毕并通过return语句进行返回时,这个方法很快被调用,返回的参数会违参数传递到此方法中,处理任务的收尾工作

当然想要启动个DownLoadTask任务,也只需要我们执行 new DownLoadTask().execute()方法即可。

Android学习--探究服务(一)的更多相关文章

  1. Android学习--探究服务(二)

    服务的基本用法 定义服务: 我们需要先创建服务,我们要使用就的利用一个类去继承它,然后重写它的几个方法,具体的我们看下面的代码: 我们重写了下面三个方法: * onCreate()           ...

  2. Android学习笔记--服务(Service)

    1.服务概述 1.服务是Android四大组件之一,在使用上可以分为本地服务和远程服务,本地服务是指在不影响用户操作的情况下在后台默默的执行一个耗时操作,例如下载,音频播放等.远程服务是指可以供其他应 ...

  3. Android学习之服务初体验

    •概念 Service(服务)是一个长期运行在后台,没有用户界面的应用组件,即使切换到另一个应用程序或者后台,服务也可以正常运行: 因此,服务适合执行一些不需要显示界面的后台耗时操作,比如下载网络数据 ...

  4. Android学习_服务

    一.           服务1.         Android多线程 每一个Android应用程序都会分别运行在一个独立的Dalvik(或ART?)虚拟机中,而每个虚拟机在启动时会运行一个UI主线 ...

  5. 【转】 Pro Android学习笔记(八十):服务(5):访问远程服务

    目录(?)[-] Client的AIDL文件 Client的代码 建立连接 请求服务 断开连接 文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://bl ...

  6. 【转】 Pro Android学习笔记(八一):服务(6):复杂数据Parcel

    目录(?)[-] 自定义的Parcelable类 AIDL文件 服务的实现 Client的实现 同步和异步     文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处 ...

  7. 【转】 Pro Android学习笔记(七八):服务(3):远程服务:AIDL文件

    目录(?)[-] 在AIDL中定义服务接口 根据AIDL文件自动生成接口代码 文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.n ...

  8. 【转】 Pro Android学习笔记(七九):服务(4):远程服务的实现

    目录(?)[-] 远程服务的实现小例子 对外开放远程服务的接口 文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.net/flow ...

  9. 【转】 Pro Android学习笔记(七六):服务(1):local和remote

    文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.net/flowingflying/ Android提供服务,服务是运行在后台的 ...

随机推荐

  1. [洛谷P4949]最短距离

    题目大意:给一棵基环树,两种操作: $1\;x\;y:$把第$x$条边长度改成$y$ $2\;x\;y:$查询$x$到$y$的最短距离 题解:发现最短距离只有两种可能,第一个是树上的距离,第二种是经过 ...

  2. mysql_存储过程和函数

    存储过程和函数 1.什么是存储过程和函数 存储过程和函数是事先经过编译并存储在数据库中的一段SQL语句集合,调用存储过程和函数可以简化应用开发人员的很多工作,减少数据在数据库和应用服务器之间的传输,对 ...

  3. 在WPF中应用弱事件模式

    http://www.cnblogs.com/rickiedu/archive/2007/03/15/676021.html 在wpf中应用弱事件模式        感谢VS 的Intellisens ...

  4. php spl库的使用(PHP标准库)【摘抄引用】

    文章来源与推荐阅读:阮一峰--PHP SPL笔记  &&  PHP SPL使用方法和他的威力 1.SPL 是什么? SPL:standard php library php标准库,此 ...

  5. AngularJs学习——何时应该使用Directive、Controller、Service?

    翻译:大漠穷秋 原文链接:http://kirkbushell.me/when-to-use-directives-controllers-or-services-in-angular/ 一.简述 A ...

  6. bzoj 4999: This Problem Is Too Simple!

    Description 给您一颗树,每个节点有个初始值. 现在支持以下两种操作: 1. C i x(0<=x<2^31) 表示将i节点的值改为x. 2. Q i j x(0<=x&l ...

  7. [POJ2187][BZOJ1069]旋转卡壳

    旋转卡壳 到现在依然不确定要怎么读... 以最远点对问题为例,枚举凸包上的两个点是最简单的想法,时间复杂度O(n2) 我们想象用两条平行线卡着这个凸包,当其中一个向某个方向旋转的时候另一个显然也是朝同 ...

  8. 【洛谷 P1645】 序列 (差分约束)

    题目链接 差分约束. 设\(s[i]\)表示前\(i\)个位置有多少个数,那么对于一个限制条件\((L,R,C)\),显然有 \[s[R]-s[L-1]>=C\] 于是连一条\(L-1\)到\( ...

  9. bzoj 1301 后缀数组

    比较裸的后缀数组. /************************************************************** Problem: User: BLADEVIL La ...

  10. 如何完全禁用或卸载Windows 10中的OneDrive

    该功能占用很大的内存与CPU 详见http://os.51cto.com/art/201508/489371.htm