什么是service,为什么要使用service
1.Service是 Android四大组件之一,和Acvtivity的级别相当
2.Service是可以长时间运行在后台的,是不可见的,是没有界面的
3.Service是运行在主线程的
4.Service可以跨进程调用
在真实的商业项自中都有定期在后台执行任务(如:下载、上传等)的需求。当某个功能需要执行很长时间(如:下载、收集数据等),并且在这个执行过程中不需要让用户操作,不需要Activity进行交互的情况下,可以通过Service在后台完成指定任务。
使用startService启动service
1.新建类继承service
2.重写onCreate方法
3.实现onBind抽象方法
4.重写onStartCommand方法
startService代码展示
xml的代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="myapplication.com.example.sq.MyActivity">
<Button
android:id="@+id/start_btn"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="启动service"
android:textSize="30sp" />
<Button
android:id="@+id/stop_btn"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="停止service"
android:textSize="30sp" />
</LinearLayout>
接下来在activity里面添加点击事件,使用switch语句。然后分别用startService和stopService来启动停止service。
package myapplication.com.example.sq;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
public class MyActivity extends AppCompatActivity implements View.OnClickListener {
private Button startBtn;
private Button stopBtn;
private Intent intent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
bindID();
}
private void bindID() {
startBtn = findViewById(R.id.start_btn);
stopBtn = findViewById(R.id.stop_btn);
stopBtn.setOnClickListener(this);
startBtn.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.start_btn:
intent = new Intent(MyActivity.this, MyService.class);
startService(intent);
break;
case R.id.stop_btn:
stopService(intent);
break;
}
}
}
我们要想沉睡一秒,可以在onStartCommand方法里面写一个thread的子线程。可以打印一下。
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
Log.e("SERVICE" + Thread.currentThread().getName(), i + " ***");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
startService的特点和缺点
1.onCreate只会执行一次,只要调用startservice,onStartCommand一定会执行
2.Service运行的线程在主线程中,做耗时操作需要另开子线程
3.通过intent传参,在onStartCommand中接收参数
4.无法获得service对象,直接操作service中的属性和方法
5.调用stopservice,serv会执行service方法后停止。
优点:
使用简单,和activity一样,只要几行代码就行。
缺点:
使用startService方式。无法获得serv对象,不能直接操作service的属性和方法,只能通过intent传递不同的参数,重复调用startService,会触发onStartCommand
使用bindService方式的缺点、优点、特点
优点:可以得到service对象,灵活控制service内部的属性和方法
缺点:使用复杂
特点:
1.oncreate,onBind只执行一次
2.Service运行的线程在主线程中,做耗时操作需要另开子线程
3.可以直接操作service内部的属性和方法
4.调用unbindservice后,service会执行onunbind,ondestory方法会停止
bindservice的使用示例
先创建一个MyService1继承Service,然后再重写其他的方法,这边需要注意的是我们定义一个Guanjia 类来继承Binder,以此来得到service的对象
public class MyService1 extends Service {
private String TAG="MySERVICE1";
private Guanjia guanjia=new Guanjia();
public class Guanjia extends Binder{
//作用:得到当前Service的对象
public MyService1 getServiceObject(){
return MyService1.this;
}
}
public void fly(){
Log.e("TAG","开飞机");
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.e("TAG","onBind...");
return guanjia ;
}
@Override
public boolean onUnbind(Intent intent) {
Log.e("TAG","onUnbind...");
return super.onUnbind(intent);
}
@Override
public void onCreate() {
super.onCreate();
Log.e("TAG","onCreate..");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("TAG","onStartCommand...");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onRebind(Intent intent) {
super.onRebind(intent);
Log.e("TAG","onRebind..");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.e("TAG","onDestroy...");
}
}
然后在创建一个activity,创建三个button控件,分别赋上点击事件。在onclick里面写上switch语句。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="myapplication.com.example.sq.ZhangsanActivity"
android:orientation="vertical">
<Button
android:id="@+id/bindBtn"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="绑定bind"
android:textSize="20sp"
/>
<Button
android:id="@+id/jiechuBtn"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="解除bind"
android:textSize="20sp"
/>
<Button
android:id="@+id/tiao_lisi"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="前往李四页面"
android:textSize="20sp"/>
</LinearLayout>
在这里我们需要写一个ServiceConnection 来拿到拿到myService1对象,打印一下日志,我们可以看到他的执行方法的顺序。记住要manifest里面注册service标签。
public class ZhangsanActivity extends AppCompatActivity implements View.OnClickListener{
private Button bindBtn;
private Button jieBtn;
private Button tiaoBtn;
private String TAG="ZhangsanActivity";
private ServiceConnection serviceConnection=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder service) {
Log.e("TAG","onServiceConnected*************###################");
//通过管家的中介作用,拿到myService1对象
MyService1 myService1 = ((MyService1.Guanjia) service).getServiceObject();
myService1.fly();
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
Log.e("TAG","onServiceConnected*************###################");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_zhangsan);
bindID();
}
private void bindID() {
bindBtn=findViewById(R.id.bindBtn);
jieBtn=findViewById(R.id.jiechuBtn);
tiaoBtn=findViewById(R.id.tiao_lisi);
bindBtn.setOnClickListener(this);
jieBtn.setOnClickListener(this);
tiaoBtn.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.bindBtn:
Intent intent=new Intent(this,MyService1.class);
bindService(intent,serviceConnection,BIND_AUTO_CREATE);
break;
case R.id.jiechuBtn:
unbindService(serviceConnection);
break;
case R.id.tiao_lisi:
Intent intent1=new Intent(ZhangsanActivity.this,LisiActivity.class);
startActivity(intent1);
break;
}
}
}
使用intentservice的特点及优缺点
特点:
1.会创建独立的工作线程来处理所有的intent请求
2.会创建独立的工作线程来处理所有的onHandleIntent
3.多次调用,会按队列的顺序逐一执行
优点:
1.无需处理线程的创建与线程同步问题
2.无需手动关闭service
3.无需另开子线程
缺点:
无法精确线程的执行过程,一旦线程启动,只能等待线程执行完毕
intentservice的使用示例
先写一个MyIntentService继承IntentService,然后在onHandleIntent里面写一个for循环。重写onCreate、onDestroy两个方法。需要在创建一个无参的构造方法,因为那个是系统的。
public class MyIntentService extends IntentService {
public MyIntentService(String name) {
super(name);
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
for (int i=0;i<5;i++){
try {
Log.e("MyIntentService",i+"***");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
然后就是添加button控件,最后需要绑定id,添加点击事件。在switch语句里面跳转。
public class ISActivity extends AppCompatActivity implements View.OnClickListener {
private Button ISbtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_is);
ISbtn = findViewById(R.id.is_btn);
ISbtn.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.is_btn:
Intent intent = new Intent(ISActivity.this, MyIntentService.class);
startService(intent);
break;
}
}
}
intentservice和service的区别
1.intentservice不要另开子线程,他可以按队列的顺序执行,而service不可以,执行耗时操作,需要开子线程
2.intentservice只能用startservice,而service可以有两种方式,但是每次也只能用一种
3.在manifest注册的时候,intentservice需要写一个无参的构造方法,而service不需要