【达内课程】Service(上)

xiaoxiao2021-02-28  21

文章目录

进程优先级ServiceService生命周期Activity和Service传递数据Service粘性绑定Service

进程优先级

讲解Service之前,先了解一下进程优先级

在Android系统中,当系统资源(内存资源)不足时,系统会自动清理一部分应用程序占用的内存,以释放出更多的可用内存空间,运行当前需要执行的应用程序

当系统自动清理应用程序占用的内存时,会按照进程的优先级,从低到高进行清理,即优先级较低的进程则最优先被清理,而优先级较高的则越不容易被清理

进程的优先级,从高到低依次是: 1、前台进程,表现为进程中存在可见并可控的Activity 2、可见进程,表现为进程中存在局部可见却不可控的Activity 3、服务进程,表现为存在正在运行的Service 4、后台进程,表现为该进程中的所有Activity均已被置于后台,即不可见也不可控 5、空进程,表现为已经退出的进程

如果我正在使用QQ,那么QQ属于前台进程,如果回到桌面,就是后台进程,如果直接按返回键退出,那么QQ就是空进程

Service

Service是Android系统的核心组件之一

Service是没有界面的,后台工作(看不见)的类

Service是运行在主线程的,所以,虽然Service适合做长期的任务,但是,也必须开始子线程来完成相关任务

Service是单例的(实例唯一:在同一时间内只存在一个对象)

启动Service 调用startService(Intent)方法即可启动Service

停止Service 1、在Service类以外,调用stopService(intent)方法即可停止Service 2、在Service类内部,调用stopSelf()方法,即可停止当前Service

Service生命周期

onCreate():当第一次创建Service对象时被调用 onStartCommand():每次激活Service组件时被调用 onDestroy():销毁服务

栗子1

新增 WorkService

import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.support.annotation.Nullable; import android.util.Log; public class WorkService extends Service { @Override public void onCreate() { super.onCreate(); Log.d("Service","WorkService@"+hashCode()+".onCreate()"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d("Service","WorkService@"+hashCode()+".onStartCommand()"); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { Log.d("Service","WorkService@"+hashCode()+".onDestroy()"); super.onDestroy(); } @Nullable @Override public IBinder onBind(Intent intent) { return null; } }

在AndroidManifest中注册

<service android:name=".WorkService"/>

activity_main布局文件

<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" tools:context="com.siliconvalley.xy.sms.MainActivity" android:orientation="vertical"> <Button android:id="@+id/btn_start_service" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="激活Service"/> <Button android:id="@+id/btn_stop_service" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="停止Service"/> </LinearLayout>

MainActivity

public class MainActivity extends Activity implements View.OnClickListener{ private Button btnStart; private Button btnStop; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btnStart = (Button) findViewById(R.id.btn_start_service); btnStart.setOnClickListener(this); btnStop = (Button) findViewById(R.id.btn_stop_service); btnStop.setOnClickListener(this); } @Override public void onClick(View v) { Intent intent = new Intent(this, WorkService.class); switch (v.getId()){ case R.id.btn_start_service: startService(intent); break; case R.id.btn_stop_service: stopService(intent); break; } } }

Log

当点击激活Service按钮时

WorkService@15788440.onCreate() WorkService@15788440.onStartCommand()

再次点击激活Service按钮时

WorkService@15788440.onStartCommand()

点击停止Service时

WorkService@15788440.onDestroy()

Service可以用于在后台执行的操作,例如检查版本更新,长时间的任务

Activity和Service传递数据

开始这里的内容之前,你应该知道Activity和Activity之间是如何传递数据的,Intent在Android系统的作用

下面的栗子是根据,上面课程基础上修改的

栗子

写一个WorkServicce,继承Service

注意 写完Service要先注册

<service android:name=".WorkService"/>

WorkService

public class WorkService extends Service { @Override public void onCreate() { super.onCreate(); Log.d("Service","WorkService@"+hashCode()+".onCreate()"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d("Service","WorkService@"+hashCode()+".onStartCommand()"); String u = intent.getStringExtra("_username"); String g = intent.getStringExtra("_gender"); int a = intent.getIntExtra("_age",0); Log.d("Service","姓名:"+u+" 性别:"+g+" 年龄:"+a); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); Log.d("Service","WorkService@"+hashCode()+".onDestroy()"); } @Nullable @Override public IBinder onBind(Intent intent) { return null; } }

activity_main

<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="com.siliconvalley.xy.sms.MainActivity" android:padding="15dp"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="请输入用户名" /> <EditText android:id="@+id/et_username" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="请选择性别" /> <RadioGroup android:id="@+id/rg_male" android:layout_width="match_parent" android:layout_height="wrap_content"> <RadioButton android:id="@+id/rb_male" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="男" /> <RadioButton android:id="@+id/rb_female" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="女" /> </RadioGroup> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="请输入年龄" /> <EditText android:id="@+id/et_age" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="number"/> <Button android:id="@+id/btn_submit" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="提交"/> </LinearLayout>

MainActivity

public class MainActivity extends Activity implements View.OnClickListener { private EditText etUserName; private RadioButton rbGenderMale; private EditText etAge; private Button btnSubmit; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); etUserName = (EditText) findViewById(R.id.et_username); rbGenderMale = (RadioButton) findViewById(R.id.rb_male); etAge = (EditText) findViewById(R.id.et_age); btnSubmit = (Button) findViewById(R.id.btn_submit); btnSubmit.setOnClickListener(this); } @Override public void onClick(View v) { Toast.makeText(this,"clicked",Toast.LENGTH_SHORT).show(); String username = etUserName.getText().toString().trim(); String gender = rbGenderMale.isChecked()?"男":"女"; int age = Integer.parseInt(etAge.getText().toString()); Intent intent = new Intent(this,WorkService.class); intent.putExtra("_username",username); intent.putExtra("_gender",gender); intent.putExtra("_age",age); startService(intent); } }

LOG

姓名:Lily 性别:女 年龄:11

其中WorkService的onStartCommand()方法的第一个参数就是Intent直接取值即可

Service粘性

在第一个栗子中,我们点击激活Service按钮,查看Log日志

WorkService@68964290.onCreate() WorkService@68964290.onStartCommand()

当我们在DDMS中停掉当前进程

过一会儿之后,发现日志中又多了

WorkService@68964290.onCreate() WorkService@68964290.onStartCommand()

Service又回来了

Service的粘性表现为当Service意外终止后,在一定时间后会自动重新启动,根本停不下来…

Service是否粘性,由onStartCommand()方法的返回值决定,取值可以是

Service.START_STICKY–>粘性Service.START_NOT_STICKY–>非粘性Service.START_STICKY_COMPATIBILITY–>兼容模式粘性Service.START_REDELIVER_INTENT–>粘性的,且重启时还拥有此前的Intent数据(重新传递Intent)

【小结】 如果希望Service是非粘性的,取值为Service.START_NOT_STICKY 如果希望Service是粘性的,则使用父类方法返回值

如果Service是粘性的,默认情况下,每次自动重启时,并不会携带Intent对象,即自动重启时,第一个参数Intent,为null

例如,第一次启动时

WorkService@76449015.onCreate() WorkService@76449015.onStartCommand(),intent->Intent { cmp=com.siliconvalley.xy.sms/.WorkService }

当我们强制关掉进程,当Service重启时,intent变为了null

WorkService@68964290.onCreate() WorkService@68964290.onStartCommand(),intent->null

如果希望Service是粘性的,且自动重启时还拥有此前的Intent数据,则取值为Service.START_REDELIVER_INTENT

栗子,我们修改栗子1的代码

激活Service时,我们传递一个值

Intent intent = new Intent(this, WorkService.class); intent.putExtra("date","2018-2-12");

WorkService的onStartCommand()方法修改为

@Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d("Service", "WorkService@" + hashCode() + ".onStartCommand(),intent->" + intent); if (intent != null) { Log.d("Service", "date->" + intent.getStringExtra("date")); } else { Log.d("Service", "null"); } return super.onStartCommand(intent, flags, startId); }

第一次激活Service的Log

WorkService@76449015.onCreate() WorkService@76449015.onStartCommand(),intent->Intent { cmp=com.siliconvalley.xy.sms/.WorkService (has extras) } date->2018-2-12

强制停掉,然后Servce自动重启时

WorkService@68964290.onCreate() WorkService@68964290.onStartCommand(),intent->null null

现在把onStartCommand()方法的返回值修改为

return START_REDELIVER_INTENT;

第一次激活时Log

WorkService@76449015.onCreate() WorkService@76449015.onStartCommand(),intent->Intent { cmp=com.siliconvalley.xy.sms/.WorkService (has extras) } date->2018-2-12

强制停掉,然后Servce自动重启时

WorkService@68964290.onCreate() WorkService@68964290.onStartCommand(),intent->Intent { cmp=com.siliconvalley.xy.sms/.WorkService (has extras) } date->2018-2-12

绑定Service

绑定Service是激活Service的一种方式,称之为“绑定模式”

而上面说到的startService是启动Service,是激活Service的一种方式,称之为“启动模式”

绑定模式激活的Service组件,可以用于实现组件间通信

组件->Activity、Service、BroadcastReceiver、ContentProvider 控件->TextView、ImageView 等可操控的view

栗子

1、首先创建WorkService继承Service

public class WorkService extends Service { @Override public void onCreate() { super.onCreate(); Log.d("Service", "WorkService@" + hashCode() + ".onCreate()"); } @Nullable @Override public IBinder onBind(Intent intent) { InnerIBinder binder = new InnerIBinder(); Log.d("Service", "WorkService@" + hashCode() + ".onBind()"); return binder; } private class InnerIBinder extends Binder { } }

2、注册Service

<service android:name=".WorkService"/>

对代码的一些解释

要想绑定成功,在WorkService中的onBind()方法需要返回一个非null的值 其中IBinder是接口(从名字上也很容易看出来Interface),所以我们写一个内部InnerIBinder来实现这个接口 然而,我们查看IBinder的注释,发现它告诉我们不要直接实现这个接口,而是要extends Binder

activity_main

<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" tools:context="com.siliconvalley.xy.sms.MainActivity" android:orientation="vertical"> <Button android:id="@+id/btn_bind_service" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="绑定Service"/> </LinearLayout>

MainActivity

public class MainActivity extends Activity implements View.OnClickListener { private Button btnBindService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btnBindService = (Button) findViewById(R.id.btn_bind_service); btnBindService.setOnClickListener(this); } @Override public void onClick(View v) { //绑定Service Intent service = new Intent(this,WorkService.class); ServiceConnection conn = new InnerServiceConnection(); int flags = BIND_AUTO_CREATE;//该取值表示:绑定Service时自动创建Service对象 bindService(service, conn, flags); Log.d("Service","MainActivity.onClick()->使用bindService激活了Service组件"); } private class InnerServiceConnection implements ServiceConnection{ @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.d("Service","MainActivity.onServiceConnected()->当Activity和Service连接好后执行这个方法"); } @Override public void onServiceDisconnected(ComponentName name) { } } }

LOG

MainActivity.onClick()->使用bindService激活了Service组件 WorkService@205845759.onCreate() WorkService@205845759.onBind() MainActivity.onServiceConnected()->当Activity和Service连接好后执行这个方法

【小结】

转载请注明原文地址: https://www.6miu.com/read-2499973.html

最新回复(0)