一、
1、概念:Android的四大组件之一,是一个没有用户界面长期在后台运行执行“耗时操作”的应用组件
2、服务与Activity的区别:
相同点:都是四大组件,需要在清单文件中注册,都运行在主线程,都有生命周期
<service
android:name=".service.MyService"
android:enabled="true"
android:exported="true" />
不同点:Activity有界面,Service没有界面,Activity运行在前台与用户进行交互,Service运行在后台。
3、服务与线程的区别:
Thread:是程序执行的最小单元,他是分配CPU的基本单位,可以做一些耗时操作(异步任务)
Service更多的时候充当线程管理者的角色。
4、服务的分类
运行的位置:本地服务(Local Service)、远程服务remote
启动方式:startService和BindService
5、启动的特点:
startService:服务一旦被启动就与启动他的组件失去了关系。
bindService:与启动他的组件绑在一起(同进退。共生死)
6、服务只能被解绑一次,多次解绑会抛出异常。
二、服务的生命周期
1、startService
onCreate -->onStartConmmand(可以执行多次) -->onDestroy(stopService,stopSelf)
开启服务startService:onCreate,onStartCommand
返回键:没有变化,在后台运行
多次点击开启服务:onStartCommand
结束服务stopService:onDestroy;还有一种自杀stopSelf
2、bindService
onCreate-->onbind-->onUnbind-->ondestroy
<service
android:name=".service.MyService"
android:enabled="true"
android:exported="true" />
//启动一个服务 btnStart.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(MainActivity.this, MyService.class); intent.putExtra("info", "ssssssssssss"); startService(intent); } }); //停止一个服务 butStop.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(MainActivity.this, MyService.class); stopService(intent); } });
/** * started service: * 1.服务同时只会被创建一次,可以通过外部调用stopService或调用stopSelf来终止服务 * 2.当执行一个已启动的服务,会直接调用onStartCommand方法来执行业务 * 3.默认情况下服务与主线程在同一个进程中的同一个线程中运行,如果服务执行一个比较耗时的操作,我们必须使子线程来完成工作,避免主线程被阻塞 * 4.使用started Service启动的一个服务,在没有关闭之前会一直在后台运行 */ public class MyService extends Service { public MyService() { } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. throw new UnsupportedOperationException("Not yet implemented"); } @Override public void onCreate() { super.onCreate(); System.out.println("!!!my service create"); } //在该方法中实现服务的核心业务 @Override public int onStartCommand(Intent intent, int flags, int startId) { System.out.println("!!!!!!" + intent.getStringExtra("info")); //这个阻塞主线程 // for (int i = 0; i < 10; i++) { // System.out.println("!!!" + "onStartCommand" +i+Thread.currentThread().getName()); // try { // Thread.sleep(500); // } catch (InterruptedException e) { // e.printStackTrace(); // } // //// if (i == 5) { //// this.stopSelf();//终止服务 //// break; //// } // } //使用线程完成长时间的工作 new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 40; i++) { System.out.println("!!!" + "onStartCommand" + i + Thread.currentThread().getName()); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } if (i == 10) { MyService.this.stopSelf();//终止服务 break; } } } }).start(); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); System.out.println("!!!my service destroy"); } }
三、IntentService
是Service的子类
特点:
1、其他组件调用startService启动IntentService服务时,会依次执行onCreate-->onStartCommand-->onHandleIntent-->onDestroy,说明IntetnService在onHandleIntent方法中处理完成意图对象后会销毁服务
2、IntentService底层采用请求队列对Intent请求意图对象进行管理
<service
android:name=".service.MyIntentService"
android:exported="false" />
//启动一个IntentService服务 btnStartIntent.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(MainActivity.this, MyIntentService.class); startService(intent); } });
/** * IntentService: * 1.内部有一个工作线程来完成耗时操作,只需实现onHandleIntent方法即可 * 2.完成工作后会自动停止服务 * 3.如果同时执行多个任务时,会以队列的方式,依次执行 * 4.通常使用该类来完成本APP中的耗时工作 */ public class MyIntentService extends IntentService { public MyIntentService() { super("MyIntentService"); } @Override protected void onHandleIntent(Intent intent) { for (int i = 0; i < 30; i++) { System.out.println("!!!" + i + Thread.currentThread().getName()); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } } }
绑定一个Service
//绑定一个服务 btnBind.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(MainActivity.this, MyBindService.class); //异步绑定,绑定成功会回调onServiceConnected bindService(intent, connection, Context.BIND_AUTO_CREATE); } }); //绑定服务的连接回调 connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { //绑定成功后的回调方法 iCat = ICat.Stub.asInterface(iBinder); mBound = true; } @Override public void onServiceDisconnected(ComponentName componentName) { //服务异常时回调 mBound = false; } }; //通过IPC调用业务方法 btnCallClick.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (iCat == null) { return; } try { iCat.setName("小猫"); Toast.makeText(MainActivity.this, iCat.desc().toString(), Toast.LENGTH_SHORT).show(); } catch (Exception e) { e.printStackTrace(); } } }); //解绑一个服务 btnUnbind.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (mBound) { unbindService(connection); } } });
/** *绑定服务: * 通过绑定服务实现功能的步骤: * 1、客户端通过bindService方法来绑定一个服务对象,如果绑定成功,会回调ServiceConnection接口方法onServiceConnected * 2、通过Service组件来暴露业务接口 * 3、服务端通过创建一个*.aidl文件来定义一个可以被客户端调用的业务接口 * 一个aidl文件: * (1)不能有修饰符,类似接口写法 * (2)支持类型有:8中基本数据类型,String,CharSequeue,List<String> map,自定义类型 * 4、服务端需要提供一个业务接口的实现类,通过我么会继承Stub类 * 5、通过Service的onBind方法返回被绑定的业务对象 * 6、客户端如果绑定成功,就可以像调用自己的方法一样调用远程的方法 */ public class MyBindService extends Service{ public MyBindService() { super(); } @Override public void onCreate() { super.onCreate(); } @Override public IBinder onBind(Intent intent) { return new CatImpl(); } @Override public boolean onUnbind(Intent intent) { return super.onUnbind(intent); } @Override public void onDestroy() { super.onDestroy(); } }
interface ICat {
void setName(String name);
String desc();
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
}
public class CatImpl extends ICat.Stub {
private String name;
@Override
public void setName(String name) throws RemoteException {
this.name = name;
}
@Override
public String desc() throws RemoteException {
return "hello ,my name is " + name;
}
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
}
2.Android多线程编程
2.1.线程的基本用法:
匿名类的方式定义和实现一个线程:
new Thread(new Runnable(){ @Override public void run(){ //处理具体逻辑 } }).start();
2.2在子线程中更新UI
public class MainActivity extends Activity implements OnClickListener{ public static final int UPDATE_TEXT=1 //先定义一个UPDATE_TEXT,用于表示更新TextView这个动作 private TextView text; private Buuton changeText; private Handler handler=new Handler(){ //新增一个handler对象,并重写父类的handleMessage方法,在这里对具体的Message进行处理 public void handleMessage(Message msg){ switch(msg.what){ case UPDATE_TEXT: //在这里进行UI操作 //如果发现Message的what字段值等于UPDATE_TEXT,就将TextView显示的内容改成nice text.setText("nice"); break; } } }; @Override public void onClick(View v){ switch(v.getId){ case R.id.change_text: new Thread(new Runnable(){ @Override public void run(){ Message message=new Message(); message.what=UPDATE_TEXT; handler.sendMessage(message);//将Message对象发送出去 } }); break; default: break; } } }
2.3解析异步消息处理机制
Android中的异步消息处理主要由四个部分组成,Message、Handler、MessageQueue和Looper
2.3.1Message
Message是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间交换数据,有Message的what字段,,除此之外还可以用arg1和arg2字段来携带一些整型数据,使用obj字段携带一个Object对象
2.3.2Handler
Handler顾名思义也就是处理者的意思,它主要是用于发送和处理消息的。发送消息一般是使用Handler的sendMessage()方法,而发出的消息经过一系列的辗转处理后,最终会传递到Handler的handleMessage()方法中。
2.3.3MessageQueue
是消息列队的意思,它主要是用于存放所有通过Handler发送的消息,这部分消息会一直存在于消息的队列中,等待被处理。每个线程中只会有一个MessageQueue()对象
2.3.4Looper
Looper是每个线程中的MessageQueue的管家,调用Looper的loop()方法后,就会进入到一个无限循环当中,然后每当发现MessageQueue中存在一条消息,就会将他取出,并传递到Handler的handleMessage()方法中,每个线程也只有一个Looper对象
异步消息处理的流程:
首先需要在主线程中创建一个Handler对象,并重写handleMessage()方法
然后当子线程中需要进行UI操作时,就创建一个Message对象,并通过Handler将这条消息发送出去,之后这条消息会被添加到MessageQueue的队列中等待被处理,而Looper则会一直尝试从MessageQueue中去除待处理的消息
最后分发回Handler的handleMessage()方法中