【Android笔记】Service的生命周期

来源:互联网 发布:中国空军 知乎 编辑:程序博客网 时间:2024/04/30 12:06

AndriodService的生命周期

1. Service生命周期

1)  可以通过调用Context.startService()启动一个Service,这可能会触发ServiceonCreate()onStart()操作,具体来说即执行startService()一定会触发onStart(),但如果该Service已经在系统中存在,则onCreate()不会被再次调用,它只在Service第一次启动时触发。

通过Context.startService()启动的Service会一直运行,直到通过Context.stopService()或者stopSelf()停止它。多次通过startService()启动某个服务并不会生成多个实例,但会导致服务的onStart()被多次调用,当然由于只有一个实例,因此无论启动多少次,停止它只需调用一次Context.stopService()stopSelf()就可以了。

 

2)  也可以通过Context.bindService()来获得一个服务的链接,这个链接是一直会保持到通过Context.unbindService()断掉它。如果在连接时系统中还没有该服务,则可能会新创建一个服务,这时ServiceonCreate函数也同样会被调用。连接建立时会ServiceonBinder会被触发,通过onBinder可以返回连接建立后的IBinder接口对象,使用服务的客户端(比如某个Activity)可以通过IBinder对象和Service交互。

     一个Service如果是通过bindService()启动的,那么它会一直存在到没有任何客户端与它保持连接为止,原因是可能有很多客户端与这个服务保持连接,这时如果某个链接被客户端主动断掉只会是Service的链接数减1,当减至0的时候这个Service就会被销毁。

 

3)  一个Service既可以被启动(start)也可以被连接(bind),这时Service的生命周期取决于它被创建的方式,如果是通过Context.startService()创建的则和第一种情况一样,如果是通过Context.bindService()使用参数Context.BIND_AUTO_CREATE创建的,则情况和第二种一样。

     当然,在Service停止,被销毁时,会触发其onDestroy()函数,我们需要在这里完成这个Service相关资源的清理,比如停止其子线程,注销监听器等等。

 

2. 相关的官方描述(Android SDK1.5)如下:

android-sdk文档 /docs/reference/android/app/Service.html

1)  There are two reasons that a service can be run by the system. If someone callsContext.startService()then the system will retrieve the service (creating it and calling its onCreate() method if needed) and then call itsonStart(Intent, int)method with the arguments supplied by the client. The service will at this point continue running untilContext.stopService() or stopSelf() is called. Note that multiple calls to Context.startService() do not nest (though they do result in multiple corresponding calls to onStart()), so no matter how many times it is started a service will be stopped once Context.stopService() or stopSelf() is called.

 

2)  Clients can also use Context.bindService() to obtain a persistent connection to a service. This likewise creates the service if it is not already running (callingonCreate() while doing so), but does not call onStart(). The client will receive the IBinder object that the service returns from itsonBind(Intent) method, allowing the client to then make calls back to the service. The service will remain running as long as the connection is established (whether or not the client retains a reference on the service's IBinder). Usually the IBinder returned is for a complex interface that has been written in aidl.

 

3)  A service can be both started and have connections bound to it. In such a case, the system will keep the service running as long as either it is startedor there are one or more connections to it with the Context.BIND_AUTO_CREATE flag. Once neither of these situations hold, the service's onDestroy() method is called and the service is effectively terminated. All cleanup (stopping threads, unregistering receivers) should be complete upon returning from onDestroy().

 

如下是Service的生命周期时序图:

 

 

 

 

3. 几个需要注意的地方

1)   Service无论以何种方式创建,都是在应用的主线程里创建的,也就是说创建一个Service并不意味着生成了一个新的线程,Service的创建过程是阻塞式的,因此也需要考虑性能,不能影响界面和逻辑上的后续操作。

 

2)   如果Service自己没有生成新的线程,那它也是运行在应用的主线程里的,因此Service本身并不能提高应用的响应速度和其他的性能,而是说通过这个后台服务生成新的线程来处理比较耗时的操作如大数据的读取等来提高响应,Service自己并不能保证这一点。Service相当于提供了一个这些费时操作的平台,由它在后台创建新线程完成这些任务,以及视各种情况管理这些线程,包括销毁。

 

3)   stopServiceunbindService都可以把Service停掉,但是如果希望明确立刻停掉Service,则使用stopService更安全,因为unbindService实质上是将与Service的连接数减一,当减为0的时候才会销毁该服务实例,stopService的效果相当于将连接数立即减为0,从而关闭该服务,所以在选择关闭方式上要视不同情况而定。




Service简介:

Service 是Android的四大组件之一,一般用于没有UI界面,长期执行的后台任务,即使程序退出时,后台任务还在执行。比如:音乐播放。

Service的误区:

1.service在UI线程中执行。 2.不可以在service中执行耗时任务,因为service是在UI线程中运行的。 3.如果需要执行后台的耗时任务,必须在Service中开启一个线程来执行。

Service的生命周期:

\



启动和停止Service的两种方式 1.context.startService();context.stopService(). 2.context.bindService();context.unbindService().
\



Service使用实例1:

客户端代码如下:
package com.xjp.broadcast;import android.app.Activity;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.TextView;public class MainActivity extends Activity {    private final static String action = "com.xjp.MainActivity";    private TextView result;    private Button startService;    private Button stopService;    private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {        @Override        public void onReceive(Context context, Intent intent) {            int i = intent.getIntExtra("key", 0);            result.setText(i + "");        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        result = (TextView) findViewById(R.id.result);        startService = (Button) findViewById(R.id.startService);        startService.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Intent service = new Intent(MainActivity.this, CalculationService.class);                startService(service);            }        });        stopService = (Button) findViewById(R.id.stopService);        stopService.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Intent service = new Intent(MainActivity.this, CalculationService.class);                stopService(service);            }        });    }    @Override    protected void onResume() {        super.onResume();        initFilter();    }    @Override    protected void onDestroy() {        super.onDestroy();        unregisterReceiver(broadcastReceiver);    }    private void initFilter() {        IntentFilter filter = new IntentFilter();        filter.addAction(action);        registerReceiver(broadcastReceiver, filter);    }}

1.依次点击“启动服务” 和“停止服务” ,生命周期 打印结果如下:
\

2.点击两次 “启动服务” 打印结果如下: \


这种方式可以多次启动同一个Service,并且 只有第一次才执行 onCreate。第二次之后 就只执行 onStartCommand,并且当且仅当该应用退出之后,该服务依然存在后台运行着。退出之后,在设置里面查看正在运行的应用:
\




服务端代码如下:
package com.xjp.broadcast;import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.util.Log;/** * Description: * User: xjp * Date: 2015/5/4 * Time: 14:14 */public class CalculationService extends Service {    private final static String TAG = "CalculationService";    private final static String action = "com.xjp.MainActivity";    private boolean quit = false;    @Override    public IBinder onBind(Intent intent) {        Log.e(TAG, "====onBind=====");        return null;    }    @Override    public boolean onUnbind(Intent intent) {        Log.e(TAG, "====onUnbind=====");        return super.onUnbind(intent);    }    @Override    public void onCreate() {        Log.e(TAG, "====onCreate=====");        super.onCreate();    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        Log.e(TAG, "====onStartCommand=====");        startThread();        return super.onStartCommand(intent, flags, startId);    }    @Override    public void onDestroy() {        Log.e(TAG, "====onDestroy=====");        quit = true;        super.onDestroy();    }    /**     * 开启线程模拟耗时任务     */    public void startThread() {        new Thread(new Runnable() {            int i = 0;            @Override            public void run() {                while (i < 200 && !quit) {                    try {                        Thread.sleep(1000);                        i++;                        Intent intent = new Intent(action);                        intent.putExtra("key", i);                        sendBroadcast(intent);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            }        }).start();    }}



Service使用实例2:

客户端代码如下:
package com.xjp.broadcast;import android.app.Activity;import android.content.BroadcastReceiver;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.content.ServiceConnection;import android.os.Bundle;import android.os.IBinder;import android.view.View;import android.widget.Button;import android.widget.TextView;public class MainActivity extends Activity {    private final static String action = "com.xjp.MainActivity";    private TextView result;    private Button startService;    private Button stopService;    private CalculationService calculationService;    private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {        @Override        public void onReceive(Context context, Intent intent) {            int i = intent.getIntExtra("key", 0);            result.setText(i + "");        }    };    private ServiceConnection serviceConnection = new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            calculationService = ((CalculationService.CalulationBinder) service).getService();            calculationService.startThread();        }        @Override        public void onServiceDisconnected(ComponentName name) {            calculationService = null;        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        result = (TextView) findViewById(R.id.result);        startService = (Button) findViewById(R.id.startService);        startService.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Intent service = new Intent(MainActivity.this, CalculationService.class);                bindService(service, serviceConnection, Context.BIND_AUTO_CREATE);            }        });        stopService = (Button) findViewById(R.id.stopService);        stopService.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                unbindService(serviceConnection);            }        });    }    @Override    protected void onResume() {        super.onResume();        initFilter();    }    @Override    protected void onDestroy() {        super.onDestroy();        unregisterReceiver(broadcastReceiver);    }    private void initFilter() {        IntentFilter filter = new IntentFilter();        filter.addAction(action);        registerReceiver(broadcastReceiver, filter);    }}

服务端代码如下:
package com.xjp.broadcast; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.util.Log; /** * Description: * User: xjp * Date: 2015/5/4 * Time: 14:14 */ public class CalculationService extends Service { private final static String TAG = "CalculationService"; private final static String action = "com.xjp.MainActivity"; private boolean quit = false; private IBinder binder = new CalulationBinder(); public class CalulationBinder extends Binder { public CalculationService getService() { return CalculationService.this; } } @Override public IBinder onBind(Intent intent) { Log.e(TAG, "====onBind====="); return binder; } @Override public boolean onUnbind(Intent intent) { Log.e(TAG, "====onUnbind====="); return super.onUnbind(intent); } @Override public void onCreate() { Log.e(TAG, "====onCreate====="); super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.e(TAG, "====onStartCommand====="); startThread(); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { Log.e(TAG, "====onDestroy====="); quit = true; super.onDestroy(); } /** * 开启线程模拟耗时任务 */ public void startThread() { new Thread(new Runnable() { int i = 0; @Override public void run() { while (i < 200 && !quit) { try { Thread.sleep(1000); i++; Intent intent = new Intent(action); intent.putExtra("key", i); sendBroadcast(intent); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); } } 


一次点击“启动服务”按钮和 “停止服务” 按钮,生命周期 打印结果如下:\

绑定服务,如果退出的时候没有解除绑定 ,也就是没有调用 context.unbindService().的话,会报错误。所以,一般都在客户端的 onDestory()中调用 context.unbindService(). 所以这种服务不太适合后台长时间的任务。 这种服务绑定和解除绑定是成对出现的。

两种Service总结:


第一种,非绑定的Service,应用退出时可以不停止服务退出。可以让服务一直在后台运行。缺点:启动服务即 启动后台任务,不能很好的在客户端随时控制 服务的后台任务执行时间。 第二种,绑定的Service,应用退出时必须解除绑定Service,否则程序报错。优点:不过绑定的Service可获得 Service 的Binder,可以灵活控制 Service里的各种方法的调用。



(android实战)Service 生命周期和使用注意项

一.基础知识

服务一般分为两种:

1:本地服务, Local Service 用于应用程序内部。在Service可以调用Context.startService()启动,调用Context.stopService()结束。 在内部可以调用Service.stopSelf() 或 Service.stopSelfResult()来自己停止。无论调用了多少次startService(),都只需调用一次 stopService()来停止。

2:远程服务, Remote Service 用于android系统内部的应用程序之间。可以定义接口并把接口暴露出来,以便其他应用进行操作。客户端建立到服务对象的连接,并通过那个连接来调用服 务。调用Context.bindService()方法建立连接,并启动,以调用 Context.unbindService()关闭连接。多个客户端可以绑定至同一个服务。如果服务此时还没有加载,bindService()会先加 载它。
提供给可被其他应用复用,比如定义一个天气预报服务,提供与其他应用调用即可。

那么先来看Service的生命周期吧:如图:

 

context.startService() ->onCreate()- >onStartCommand()->Service running--调用context.stopService() ->onDestroy()

context.bindService()->onCreate()->onBind()->Service running--调用>onUnbind() ->onDestroy()从上诉可以知道分别对应本地的,,以及远程的,也对应不同的方式启动这个服务。

 

 

二.注意事项

2.1  同一服务,多次启动,服务实际执行的过程

第一次 启动服务时,运行 onCreate -->onStartCommand

后面在启动服务时,服务只执行onStartCommand

在实际使用过程中,通过Intent 传递数据,在OnStartCommand中执行。


0 0
原创粉丝点击