zoukankan      html  css  js  c++  java
  • [Android]Android四大组件之Service总结

    一、Service介绍

    Service是Android中实现程序后台运行的解决方案,它非常适合用于去执行那些不需要和用户交互而且还要长期运行的task。Service的运行不需要依赖于任何用户界面,即使当程序被切换到后台,霍州用户打开了另外一个app。Service仍然能够保持正常的运行。
    不过需要注意的是,Service不是运行在一个独立的进程当中的,而是依赖于创建服务时所在的app进程。当app进程被杀死,Service也会被杀死。

    二、Service生命周期

    . 通过startService方法 2. 通过bindService方法 这两种启动方式下的生命周期如下图所示:

    Service的生命周期比起Activity要简单不少,只有onCreate()、onStartCommand()、onBind()、onDestory()。
    一旦项目内任何位置调用了Context的startService(),相应的Service就会启动,并且回调onStartCommand()。如果这个Service之前还没有创建过,onCreate()会优先于onStartCommand()执行。Service启动了之后会一直保持running状态,知道stopService()或stopSelf()被调用。tips:所有Service都只会存在一个实例,所以不管调用多少次startService(),最后只需要调用一次stopService()或stopSelf()就会停下来。

    另外还可以调用了Context的bindService()来获取一个Service的持久连接,这时候就会回调onBind()。如果这个Service之前还没有创建过,onCreate()会优先于onBind()执行。

    三、Service的基本用法

    新建一个ServiceTest项目,并新建一个MyService文件

    public class MyService extends Service {  
    
        public static final String TAG = "MyService";  
    
        @Override  
        public void onCreate() {  
            super.onCreate();  
            Log.d(TAG, "onCreate() executed");  
        }  
    
        @Override  
        public int onStartCommand(Intent intent, int flags, int startId) {  
            Log.d(TAG, "onStartCommand() executed");  
            return super.onStartCommand(intent, flags, startId);  
        }  
    
        @Override  
        public void onDestroy() {  
            super.onDestroy();  
            Log.d(TAG, "onDestroy() executed");  
        }  
    
        @Override  
        public IBinder onBind(Intent intent) {  
            return null;  
        }  
    
    }  

    在main_activity.xml文件中写入

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
        android:layout_width="match_parent"  
        android:layout_height="match_parent"  
        android:orientation="vertical" >  
    
        <Button  
            android:id="@+id/start_service"  
            android:layout_width="match_parent"  
            android:layout_height="wrap_content"  
            android:text="Start Service" />  
    
        <Button  
            android:id="@+id/stop_service"  
            android:layout_width="match_parent"  
            android:layout_height="wrap_content"  
            android:text="Stop Service" />  
    
    </LinearLayout>  

    另外还有MainActivity

    public class MainActivity extends Activity implements OnClickListener {  
    
        private Button startService;  
    
        private Button stopService;  
    
        @Override  
        protected void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.activity_main);  
            startService = (Button) findViewById(R.id.start_service);  
            stopService = (Button) findViewById(R.id.stop_service);  
            startService.setOnClickListener(this);  
            stopService.setOnClickListener(this);  
        }  
    
        @Override  
        public void onClick(View v) {  
            switch (v.getId()) {  
            case R.id.start_service:  
                Intent startIntent = new Intent(this, MyService.class);  
                startService(startIntent);  
                break;  
            case R.id.stop_service:  
                Intent stopIntent = new Intent(this, MyService.class);  
                stopService(stopIntent);  
                break;  
            default:  
                break;  
            }  
        }  
    
    }  

    最后还要在AndroidManifest.xml中进行注册,加入下面这句话

    <service android:name="com.example.servicetest.MyService" >  

    然后run一下,看看logcat
    这里写图片描述

    四、Service和Activity之间的通信

    在上一节的代码中,onbind()这个方法并没有使用,其实它就是用与Service和Activity之间通信的。

    我们首先在main_activity.xml中加入两个button,并修改MainActivity和MyService

    public class MainActivity extends Activity implements OnClickListener {  
    
        private Button startService;  
    
        private Button stopService;  
    
        private Button bindService;  
    
        private Button unbindService;  
    
        private MyService.MyBinder myBinder;  
    
        private ServiceConnection connection = new ServiceConnection() {  
    
            @Override  
            public void onServiceDisconnected(ComponentName name) {  
            }  
    
            @Override  
            public void onServiceConnected(ComponentName name, IBinder service) {  
                myBinder = (MyService.MyBinder) service;  
                myBinder.startDownload();  
            }  
        };  
    
        @Override  
        protected void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.activity_main);  
            startService = (Button) findViewById(R.id.start_service);  
            stopService = (Button) findViewById(R.id.stop_service);  
            bindService = (Button) findViewById(R.id.bind_service);  
            unbindService = (Button) findViewById(R.id.unbind_service);  
            startService.setOnClickListener(this);  
            stopService.setOnClickListener(this);  
            bindService.setOnClickListener(this);  
            unbindService.setOnClickListener(this);  
        }  
    
        @Override  
        public void onClick(View v) {  
            switch (v.getId()) {  
            case R.id.start_service:  
                Intent startIntent = new Intent(this, MyService.class);  
                startService(startIntent);  
                break;  
            case R.id.stop_service:  
                Intent stopIntent = new Intent(this, MyService.class);  
                stopService(stopIntent);  
                break;  
            case R.id.bind_service:  
                Intent bindIntent = new Intent(this, MyService.class);  
                bindService(bindIntent, connection, BIND_AUTO_CREATE);  
                break;  
            case R.id.unbind_service:  
                unbindService(connection);  
                break;  
            default:  
                break;  
            }  
        }  
    
    }  
    public class MyService extends Service {  
    
        public static final String TAG = "MyService";  
    
        private MyBinder mBinder = new MyBinder();  
    
        @Override  
        public void onCreate() {  
            super.onCreate();  
            Log.d(TAG, "onCreate() executed");  
        }  
    
        @Override  
        public int onStartCommand(Intent intent, int flags, int startId) {  
            Log.d(TAG, "onStartCommand() executed");  
            return super.onStartCommand(intent, flags, startId);  
        }  
    
        @Override  
        public void onDestroy() {  
            super.onDestroy();  
            Log.d(TAG, "onDestroy() executed");  
        }  
    
        @Override  
        public IBinder onBind(Intent intent) {  
            return mBinder;  
        }  
    
        class MyBinder extends Binder {  
    
            public void startDownload() {  
                Log.d("TAG", "startDownload() executed");  
                // 执行具体的下载任务  
            }  
    
        }  
    
    }  

    Service和Thread的关系

    首先声明Service和Thread之间没有任何关系!
    之所以有不少人会把它们联系起来,主要就是因为Service的后台概念。Thread我们大家都知道,是用于开启一个子线程,在这里去执行一些耗时操作就不会阻塞主线程的运行。而Service我们最初理解的时候,总会觉得它是用来处理一些后台任务的,一些比较耗时的操作也可以放在这里运行,这就会让人产生混淆了。但是,如果Service其实是运行在主线程里的,所以Service和Thread并没有什么关系
    在MainActivity的onCreate()方法里加入一行打印当前线程id的语句:

    Log.d("MyService", "MainActivity thread id is " + Thread.currentThread().getId());  

    然后在MyService的onCreate()方法里也加入一行打印当前线程id的语句:

    Log.d("MyService", "MyService thread id is " + Thread.currentThread().getId());  

    现在重新运行一下程序,并点击Start Service按钮,可以看到,它们的线程id完全是一样的,由此证实了Service确实是运行在主线程里的,也就是说如果你在Service里编写了非常耗时的代码,程序必定会出现ANR的。
    Android的后台就是指,它的运行是完全不依赖UI的。即使Activity被销毁,或者程序被关闭,只要进程还在,Service就可以继续运行。为了避免Service导致主线程阻塞,我们可以在Service中再创建一个子线程,然后在这里去处理耗时逻辑就没问题了。这就是Thread。
    至于为什么Thread不建立在Activity中。因为Activity很难对Thread进行控制,当Activity被销毁之后,就没有任何其它的办法可以再重新获取到之前创建的子线程的实例。而且在一个Activity中创建的子线程,另一个Activity无法对其进行操作。但是Service就不同了,所有的Activity都可以与Service进行关联,然后可以很方便地操作其中的方法,即使Activity被销毁了,之后只要重新与Service建立关联,就又能够获取到原有的Service中Binder的实例。因此,使用Service来处理后台任务,Activity就可以放心地finish,完全不需要担心无法对后台任务进行控制的情况。

  • 相关阅读:
    NFS 规格严格
    Spring 规格严格
    如何做好软件功能测试 规格严格
    51CTO上不错的文章 规格严格
    一个好网站 规格严格
    系统小贴士 规格严格
    编译Zabbix 规格严格
    JS学习 规格严格
    杂项 规格严格
    MySQL 自增ID 规格严格
  • 原文地址:https://www.cnblogs.com/zhousysu/p/5483615.html
Copyright © 2011-2022 走看看