2024年最全Android四大组件之 Service,15个经典面试问题及答案精简版

最后

分享一份NDK基础开发资料

详解:Linux网络虚拟化技术

分享内容包括不限于高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter等全方面的Android进阶实践技术;希望能帮助到大家,也节省大家在网上搜索资料的时间来学习,也可以分享动态给身边好友一起学习!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

1 通过startService()

Service会经历 onCreate --> onStartCommand()

stopService的时候直接onDestroy

如果是 调用者 直接退出而没有调用stopService的话,Service会一直在后台运行。

下次调用者再起来仍然可以stopService。

2 通过bindService()

Service只会运行onCreate()–>onBind()

这个时候 调用者和Service绑定在一起

unbindService的时候  onUnbind()–>onDestroyed()

调用者退出了,Srevice就会调用onUnbind()–>onDestroyed()

所谓绑定在一起就共存亡了。

注意:Service的onCreate的方法只会被调用一次,

就是你无论多少次的startService又 bindService,Service只被创建一次。

如果先是bind了,那么start的时候就直接运行Service的onStart方法,

如果先是start,那么bind的时候就直接运行onBind方法。如果你先bind上了,就stop不掉了,

只能先UnbindService, 再StopService,所以是先start还是先bind行为是有区别的。

Android中的服务和windows中的服务是类似的东西,服务一般没有用户操作界面,它运行于系统中不容易被用户发觉,可以使用它开发如监控之类的程序。

服务不能自己运行,需要通过调用Context.startService()或Context.bindService()方法启动服务。

这两个方法都可以启动Service,但是它们的使用场合有所不同。使用startService()方法启用服务,调用者与服务之间没有关连,

即使调用者退出了,服务仍然运行。使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止,大有“不求同时生,必须同时死”的特点。

如果打算采用Context.startService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,

接着调用onStart()方法。如果调用startService()方法前服务已经被创建,多次调用startService()方法并不会导致多次创建服务,

但会导致多次调用onStart()方法。采用startService()方法启动的服务,只能调用Context.stopService()方法结束服务,服务结束时会调用onDestroy()方法。

如果打算采用Context.bindService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,

接着调用onBind()方法。这个时候调用者和服务绑定在一起,调用者退出了,系统就会先调用服务的onUnbind()方法,

接着调用onDestroy()方法。如果调用bindService()方法前服务已经被绑定,

多次调用bindService()方法并不会导致多次创建服务及绑定(也就是说onCreate()和onBind()方法并不会被多次调用)。

如果调用者希望与正在绑定的服务解除绑定,可以调用unbindService()方法,调用该方法也会导致系统调用服务的onUnbind()–>onDestroy()方法.

三    代码实例

编写不需和Activity交互的本地服务示例

本地服务编写比较简单。首先,要创建一个Service类,该类继承android的Service类。这里写了一个计数服务的类,每秒钟为计数器加一。在服务类的内部,还创建了一个线程,用于实现后台执行上述业务逻辑。

package com.easymorse;import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.util.Log;public class CountService extends Service {    private  boolean threadDisable;    privateint count;

@Override    public IBinder onBind(Intent intent) {        returnnull;

}

@Override    public void onCreate() {        super.onCreate();        new Thread(new Runnable() {

@Override            publicvoid run() {                while (!threadDisable) {                    try {

Thread.sleep(1000);

} catch (InterruptedException e) {

}

count++;

Log.v(“CountService”,"Count is " + count);

}

}

}).start();

}

@Override    public void onDestroy() {        super.onDestroy();        this.threadDisable= true;

Log.v(“CountService”,“on destroy”);

}    public int getCount() {        return count;

}

}

需要将该服务注册到配置文件AndroidManifest.xml中,否则无法找到:

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android=“http://schemas.android.com/apk/res/android”    package=“com.easymorse” android:versionCode=“1” android:versionName=“1.0”>    <applicationandroid:icon=“@drawable/icon” android:label=“@string/app_name”>        <activityandroid:name=“.LocalServiceDemoActivity”            android:label=“@string/app_name”>            <intent-filter>                actionandroid:name\=“android.intent.action.MAIN”/                categoryandroid:name\=“android.intent.category.LAUNCHER”/            </intent-filter>        </activity>        serviceandroid:name\=“CountService”/    </application>    uses-sdkandroid:minSdkVersion\=“3”/

</manifest/>

在Activity中启动和关闭本地服务。

package com.easymorse;import android.app.Activity;import android.content.Intent;import android.os.Bundle;public class LocalServiceDemoActivityextends Activity {    /** Called when the activity is first created.*/    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);

setContentView(R.layout.main);        this.startService(new Intent(this, CountService.class));

}

@Override    protectedvoid onDestroy() {        super.onDestroy();        this.stopService(new Intent(this, CountService.class));

}

}

可通过日志查看到后台线程打印的计数内容。

编写本地服务和Activity交互的示例

上面的示例是通过startService和stopService启动关闭服务的。适用于服务和activity之间没有调用交互的情况。如果之间需要传递参数或者方法调用。需要使用bind和unbind方法。

具体做法是,服务类需要增加接口,比如ICountService,另外,服务类需要有一个内部类,这样可以方便访问外部类的封装数据,这个内部类需要继承Binder类并实现ICountService接口。还有,就是要实现Service的onBind方法,不能只传回一个null了。

这是新建立的接口代码:

package com.easymorse;public interface ICountService {    public abstract int getCount();

}

修改后的CountService代码:

package com.easymorse;import android.app.Service;import android.content.Intent;import android.os.Binder;import android.os.IBinder;import android.util.Log;public class CountServiceextends Serviceimplements ICountService {    privateboolean threadDisable;    privateint count;    private ServiceBinder serviceBinder=new ServiceBinder();    public class ServiceBinderextends Binderimplements ICountService{

@Override        publicint getCount() {            return count;

}

}

@Override

public IBinder onBind(Intent intent) {        return serviceBinder;

}

@Override    public void onCreate() {        super.onCreate();        new Thread(new Runnable() {

@Override            publicvoid run() {                while (!threadDisable) {                    try {

Thread.sleep(1000);

} catch (InterruptedException e) {

}

count++;

Log.v(“CountService”,"Count is " + count);

}

}

}).start();

}

@Override    public void onDestroy() {        super.onDestroy();        this.threadDisable= true;

Log.v(“CountService”,“on destroy”);

}    /* (non-Javadoc)

* @see com.easymorse.ICountService#getCount()     */    public int getCount() {        return count;

}

}

服务的注册也要做改动,AndroidManifest.xml文件:

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android=“http://schemas.android.com/apk/res/android”    package=“com.easymorse” android:versionCode=“1” android:versionName=“1.0”>    <applicationandroid:icon=“@drawable/icon” android:label=“@string/app_name”>        <activityandroid:name=“.LocalServiceDemoActivity”            android:label=“@string/app_name”>            <intent-filter>                actionandroid:name\=“android.intent.action.MAIN”/                categoryandroid:name\=“android.intent.category.LAUNCHER”/            </intent-filter>        </activity>        serviceandroid:name\=“CountService”\            <intent-filter>                actionandroid:name\=“com.easymorse.CountService”/            </intent-filter>        </service>    </application>    uses-sdkandroid:minSdkVersion\=“3”/

</manifest>

Acitity代码不再通过startSerivce和stopService启动关闭服务,另外,需要通过ServiceConnection的内部类实现来连接Service和Activity。

package com.easymorse;import android.app.Activity;import android.content.ComponentName;import android.content.Intent;import android.content.ServiceConnection;import android.os.Bundle;import android.os.IBinder;import android.util.Log;public class LocalServiceDemoActivity extends Activity {    private ServiceConnection serviceConnection= new ServiceConnection() {

@Override        publicvoid onServiceConnected(ComponentName name, IBinder service) {

countService = (ICountService) service;

Log.v(“CountService”,“on serivce connected, count is”                    + countService.getCount());

}

@Override        publicvoid onServiceDisconnected(ComponentName name) {

countService =null;

}

};    private ICountService countService;    /** Called when the activity is first created.*/    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);

setContentView(R.layout.main);        this.bindService(new Intent(“com.easymorse.CountService”),                this.serviceConnection, BIND_AUTO_CREATE);

}

@Override    protectedvoid onDestroy() {

this.unbindService(serviceConnection);

super.onDestroy();      //注意先后    }

}

编写传递基本型数据的远程服务

上面的示例,可以扩展为,让其他应用程序复用该服务。这样的服务叫远程(remote)服务,实际上是进程间通信(RPC)。

这时需要使用android接口描述语言(AIDL)来定义远程服务的接口,而不是上述那样简单的java接口。扩展名为aidl而不是java。可用上面的ICountService改动而成ICountSerivde.aidl,eclipse会自动生成相关的java文件。

package com.easymorse;

interface ICountService {    int getCount();

}

编写服务(Service)类,稍有差别,主要在binder是通过远程获得的,需要通过桩(Stub)来获取。桩对象是远程对象的本地代理。

package com.easymorse;import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.os.RemoteException;import android.util.Log;public class CountService extends Service {    privateboolean threadDisable;    privateint count;    private ICountService.Stub serviceBinder= new ICountService.Stub() {

最后

下面是辛苦给大家整理的学习路线

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

t;    private ICountService.Stub serviceBinder= new ICountService.Stub() {

最后

下面是辛苦给大家整理的学习路线

[外链图片转存中…(img-W7LoiswM-1715850287149)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值