什么是服务?


服务(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. gdb调试命令的使用及总结

    gdb调试命令的使用及总结 gdb是一个在UNIX环境下的命令行调试工具.如果需要使用gdb调试程序,请在gcc时加上-g选项.下面的命令部分是简化版,比如使用l代替list等等. 1.基本命令 命令 ...

  2. ZJOI2018 Day2 滚粗记 + 流水账

    一脸懵逼地就被直接拉过来浙江省选了,一年参加两次省选成就达成-- 讲课啥的都没听,过去休息了一天就进行比赛了.考试之前感冒没好透,精神不是 \(100\%\) 的状态,但是并无大碍(反正最后都很凉). ...

  3. 周记【距gdoi:91天】

    这星期挺没状态的.听蔡大神讲组合游戏,然后欢乐得以为自己懂了,然后看到题目就懵了,然后就各种乱各种走神……但是某大神们(kpm和child)疯狂地切题.然后又颓废了两个晚上后决定滚回去文化课(oi没状 ...

  4. BZOJ1093 [ZJOI2007]最大半连通子图 【tarjan缩点 + DAG最长路计数】

    题目 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意 两点u,v,存在一条u到v的有向路径或者从v到u的有向路径.若G ...

  5. HDU 多校对抗赛 J Time Zone

    Time Zone Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total S ...

  6. sls语法:创建file,创建文件夹

    http://blog.kukafei520.net/html/2014/942.html /tmp/aaa.txt: file.managed /tmp/salt_test: file.direct ...

  7. i=i+1与i+=1的区别及效率(Java)

    原博客地址 在做个java优化的PPT时,看到了i=i+1与i+=1的区别,在这之前还真没想到那么细. 1.x=x+1,x+=1及x++的效率哪个最高?为什么? x=x+1最低,因为它的执行如下. ( ...

  8. koala 编译scss不支持中文解决方案

    方法一: 在scss文件第一行加上代码:@charset "utf-8"; 方法二: 进入到Koala 安装目录 C:\Koala\rubygems\gems\sass-3.4.9 ...

  9. 使用FindBugs-IDEA插件找到代码中潜在的问题

    另一篇使用文档,参照:https://www.cnblogs.com/huaxingtianxia/p/6703315.html 我们通常都会在APP上线之后,发现各种错误,尤其是空指针异常,这些错误 ...

  10. 解决tomcat不支持中文路径的问题

    问题描述: 开发文件下载功能时,因为需求比较简单,要求下载一个说明文件.于是,直接给出了文件所在服务器的地址,通过链接直接下载此文件(因需求简单,未考虑安全方面的问题-_-||). 在这个过程中,文件 ...