因为最近要面试,于是打算整理整理一下Android的基础知识,由于之前本人已经学习过大概的Android基础知识,这里主要讲这四大组件、五大存储、六大布局、网络请求等这些内容,其他一些等有时间再整理,话不多说。

应用组件(官方解释,需科学上网)

应用组件是 Android 应用的基本构建基块。每个组件都是一个不同的点,系统可以通过它进入您的应用。 并非所有组件都是用户的实际入口点,有些组件相互依赖,但每个组件都以独立实体形式存在,并发挥特定作用 — 每个组件都是唯一的构建基块,有助于定义应用的总体行为。

共有四种不同的应用组件类型。每种类型都服务于不同的目的,并且具有定义组件的创建和销毁方式的不同生命周期。

 

一、什么是Service(服务)?

从官方的解释中可以看到:

Service

服务是一种在后台运行的组件,用于执行长时间运行的操作或为远程进程执行作业。 服务不提供用户界面。 例如,当用户位于其他应用中时,服务可能在后台播放音乐或者通过网络获取数据,但不会阻断用户与 Activity 的交互。 诸如 Activity 等其他组件可以启动服务,让其运行或与其绑定以便与其进行交互。

参考网站:https://www.jianshu.com/p/d963c55c3ab9       https://www.jianshu.com/p/95ec2a23f300

       Service是Android系统中的四大组件之一,主要有两个应用场景:后台运行和跨进程访问。Service可以在后台执行长时间运行操作而不提供用户界面,除非系统必须回收内存资源,否则系统不会停止或销毁服务。服务可由其他应用组件启动,而且即使用户切换到其他应用,服务仍然将在后台继承运行。此外,组件还可以绑定到服务,然后与服务进行交互,甚至是执行进程间通信(IPC)。

        注:Service是在主线程里执行操作的,可能会因为执行耗时操作而导致ANR(Application Not Responding),即无响应。

  • 定义:服务是Android四大组件之一,属于计算型组件
  • 作用:提供需在后台长时间运行的服务(如:复杂计算、音乐播放、下载等等)
  • 特点:在后台运行、生命周期长、无用户界面

 

二、Service(服务)的生命周期

2.1 生命周期的常用方法

  • 官方说明图:

在Service的生命周期里,常用的有:

  • 4个手动调用的方法,如下
手动调用方法 作用
startService() 启动服务
stopService() 关闭服务
bindService() 绑定服务
unbindService() 解绑服务
  • 5个自动调用的方法,如下
内部自动调用的方法 作用
onCreate() 创建服务
oStartCommand() 开始服务
onBind() 绑定服务
onUnbind() 解绑服务
onDestroy() 销毁服务

2.2 生命周期方法的具体介绍

2.3 常用的生命周期使用

 

三、Service(服务)的类型

3.1 具体分类

Service可按照地点运行类型功能进行分类,具体如下:

  • 地点

1.本地服务

2.远程服务

  • 运行类型

1.前台服务

2.后台服务

  • 功能

1.可通信服务

2.不可通信服务

示意图如下:

3.2 详细介绍

 

四、Service(服务)各种类型的使用

  • 本地服务(LocalService)

1.介绍

      这是最普通、最常用的后台服务Service。

2.使用步骤

         (1)新建子类继承Service类(需重写父类的onCreate()、onStartCommand()、onDestroy()、onBind()方法)

         (2)构建用来启动Service的Intent对象

         (3)调用startService()启动Service、调用stopService()停止服务

         (4)在AndroidMinifest.xml里注册Service

3.代码示例

         (1)activity_main.xml

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

         (2)MyService类

public class MyService extends Service {    private static final String TAG = "MyService";    public MyService() {    }    @Override    public void onCreate() {        super.onCreate();        Log.d(TAG, "onCreate: ");    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        Log.d(TAG, "onStartCommand: ");        return super.onStartCommand(intent, flags, startId);    }    @Override    public void onDestroy() {        Log.d(TAG, "onDestroy: ");        super.onDestroy();    }    @Override    public IBinder onBind(Intent intent) {        // TODO: Return the communication channel to the service.        throw new UnsupportedOperationException("Not yet implemented");    }}

         (3)MainActivity类

public class MainActivity extends AppCompatActivity implements View.OnClickListener {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Button button1 = findViewById(R.id.button1);        Button button2 = findViewById(R.id.button2);        button1.setOnClickListener(this);        button2.setOnClickListener(this);    }    @Override    public void onClick(View v) {        Intent intent = new Intent(getApplicationContext(), MyService.class);        switch (v.getId()) {            case R.id.button1:                startService(intent);                break;            case R.id.button2:                stopService(intent);                break;        }    }}

         (4)AndroidManifest.xml清单文件

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

Androidmanifest里Service的常见属性说明

属性 说明 备注
android:name Service的类名  
android:label Service的名字 若不设置,默认为Service类名
android:icon Service的图标  
android:permission 申明此Service的权限 有提供了该权限的应用才能控制或连接此服务
android:process 表示该服务是否在另一个进程中运行(远程服务) 不设置默认为本地服务;remote则设置成远程服务
android:enabled 系统默认启动 true:Service 将会默认被系统启动;不设置则默认为false
android:exported 该服务是否能够被其他应用程序所控制或连接 不设置默认此项为 false

4.运行结果

05-01 17:18:00.777 22569-22569/com.peterli.localservicetest D/MyService: onCreate: 05-01 17:18:00.777 22569-22569/com.peterli.localservicetest D/MyService: onStartCommand: 05-01 17:18:11.827 22569-22569/com.peterli.localservicetest D/MyService: onDestroy: 

  • 远程服务(RemoteService)

1.介绍(远程服务与本地服务的区别)

     远程服务与本地服务最大的区别是:远程服务与调用者不再同一个进程里(也就是说远程服务是运行在另外一个进程);                                                                            而本地服务则是与调用者运行在同一个进程里

     示意图如下:

2.使用场景

    多个应用程序共享同一个后台远程服务。(也就是说一个远程服务与多个应用程序的组件(四大组件)进行跨进程通信)

    示意图:

3.具体使用

3.1 前言

    为了让远程Service与多个应用程序的组件(四大组件)进行IPC(跨进程通信),需要使用AIDL(Android接口定义语言)

    (1)IPC:Inter-Process Communication,即跨进程通信。

    (2)AIDL:Android Interface Definition Language,即Android接口定义语言;用于让某个Service与多个应用程序组件之                                      间进行跨进程通信,从而可以实现多个应用程序共享同一个Service的功能。

    在多进程通信中,存在两个进程角色(以最简单的为例):服务器端和客户端

3.2 使用步骤

     服务器端(Service)

          (1)新建定义AIDL文件,并声明该服务需要向客户端提供的接口

          (2)在Service子类中实现AIDL中定义的接口方法,并定义生命周期的方法(onCrate、onBind、onDestroy等等)

          (3)在AndroidManifest.xml中注册服务和声明为远程服务

     客户端(Client)

          (1)拷贝服务器端的AIDL文件到目录下

          (2)使用Stud.asInterface接口获取服务器的Binder,根据需要调用服务提供的接口方法

          (3)通过Intent指定服务端的服务名称和所在包,绑定远程Service

3.3 代码示例

     服务器端(Service)工程项目:

步骤1: 新建一个AIDL文件(懒得截图,使用原网站的图)

步骤2:在新建AIDL文件里定义Service需要与Activity进行通信的内容(方法),并进行编译(Make Project)

// 在新建的AIDL_Service1.aidl里声明需要与Activity进行通信的方法package scut.carson_ho.demo_service;interface AIDL_Service1 {    void AIDL_Service();}//AIDL中支持以下的数据类型//1. 基本数据类型//2. String 和CharSequence//3. List 和 Map ,List和Map 对象的元素必须是AIDL支持的数据类型;//4. AIDL自动生成的接口(需要导入-import)//5. 实现android.os.Parcelable 接口的类(需要导入-import)

步骤3:在Service子类中实现AIDL中定义的接口方法,并定义生命周期的方法(onCreat、onBind()等等)

public class MyService extends Service {    private static final String TAG = "MyService";    private AIDL_Service1.Stub mBinder = new AIDL_Service1.Stub() {        @Override        public void AIDL_Service() throws RemoteException {            Log.d(TAG, "AIDL_Service: 客户端通过AIDL与远程后台成功通信");        }    };    public MyService() {    }    @Override    public void onCreate() {        super.onCreate();        Log.d(TAG, "onCreate: ");    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        Log.d(TAG, "onStartCommand: ");        return super.onStartCommand(intent, flags, startId);    }    @Override    public void onDestroy() {        Log.d(TAG, "onDestroy: ");        super.onDestroy();    }    @Override    public IBinder onBind(Intent intent) {        Log.d(TAG, "onBind: ");        return mBinder;    }    @Override    public boolean onUnbind(Intent intent) {        Log.d(TAG, "onUnbind: ");        return super.onUnbind(intent);    }}

步骤4:在AndroidMainfest.xml中注册服务 & 声明为远程服务

            //该Service可以响应带有scut.carson_ho.service_server.AIDL_Service1这个action的Intent。            //此处Intent的action必须写成“服务器端包名.aidl文件名”                                                

     客户端(Client)工程项目:

              

步骤1:将服务端的AIDL文件所在的包复制到客户端目录下(Project/app/src/main),并进行编译。(懒得截图,使用原网站的图)

PS:记得要原封不动地复制!!什么都不要改!

步骤2:在主布局文件定义按钮

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

步骤3:在MainActivity.java里

  • 使用Stub.asInterface接口获取服务器的Binder;
  • 通过Intent指定服务端的服务名称和所在包,进行Service绑定;
  • 根据需要调用服务提供的接口方法。
public class MainActivity extends AppCompatActivity {    //定义aidl接口变量    private AIDL_Service1 mAIDL_service;    //创建ServiceConnection的匿名类    private ServiceConnection mServiceConnection = new ServiceConnection() {        //在Activity与Service建立关联时调用        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            //使用AIDLService1.Stub.asInterface()方法获取服务器端返回的IBinder对象            //将IBinder对象传换成了mAIDL_Service接口对象            mAIDL_service = AIDL_Service1.Stub.asInterface(service);            try {                //通过该对象调用在MyAIDLService.aidl文件中定义的接口方法,从而实现跨进程通信                mAIDL_service.AIDL_Service();            } catch (RemoteException e) {                e.printStackTrace();            }        }        //重写onServiceConnected()方法和onServiceDisconnected()方法        //在Activity与Service建立关联和解除关联的时候调用        @Override        public void onServiceDisconnected(ComponentName name) {        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Button button1 = findViewById(R.id.button1);        Button button2 = findViewById(R.id.button2);        Button button3 = findViewById(R.id.button3);        Button button4 = findViewById(R.id.button4);        button1.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                //通过Intent指定服务端的服务名称和所在包,与远程Service进行绑定                //参数与服务器端的action要一致,即"服务器包名.aidl接口文件名"                Intent intent = new Intent("com.peterli.remoteserviceserver.AIDL_Service1");                //Android5.0后无法只通过隐式Intent绑定远程Service                //需要通过setPackage()方法指定包名                intent.setPackage("com.peterli.remoteserviceserver");                //绑定服务,传入intent和ServiceConnection对象                bindService(intent, mServiceConnection, BIND_AUTO_CREATE);            }        });        button2.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                unbindService(mServiceConnection);            }        });        button3.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Intent intent = new Intent("com.peterli.remoteserviceserver.AIDL_Service1");                intent.setPackage("com.peterli.remoteserviceserver");                startService(intent);            }        });        button4.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Intent intent = new Intent("com.peterli.remoteserviceserver.AIDL_Service1");                intent.setPackage("com.peterli.remoteserviceserver");                stopService(intent);            }        });    }}

3.4 运行结果(按的顺序:开启服务-->绑定服务-->解绑服务-->停止服务)

05-01 20:51:10.329 29345-29345/com.peterli.remoteserviceserver:remote D/MyService: onCreate: 05-01 20:51:10.329 29345-29345/com.peterli.remoteserviceserver:remote D/MyService: onStartCommand: 05-01 20:51:12.879 29345-29345/com.peterli.remoteserviceserver:remote D/MyService: onBind: 05-01 20:51:12.879 29345-29357/com.peterli.remoteserviceserver:remote D/MyService: AIDL_Service: 客户端通过AIDL与远程后台成功通信05-01 20:51:17.239 29345-29345/com.peterli.remoteserviceserver:remote D/MyService: onUnbind: 05-01 20:51:19.269 29345-29345/com.peterli.remoteserviceserver:remote D/MyService: onDestroy: 

从上面测试结果可以看出:

  • 打印的语句分别运行在不同进程(看语句前面的包名);
  • 客户端调用了服务端Service的方法

    (即客户端和服务端进行了跨进程通信)


  • 后台服务

几乎服务都是在后台运行的,以本地后台为例,那个就是普通的后台服务。


  • 前台服务

1. 介绍

      服务几乎都是在后台运行的,但后台服务的系统优先级还是比较低的,但系统出现内存不足的情况时,就有可能会回收掉正在后台运行的服务。如果想要服务一直保持运行状态,不被系统回收,就可以考虑使用前台服务。前台服务和后台服务最大的区别就在于,它会有一个正在运行的图标在系统状态栏显示,下拉状态栏后可以看到更加详细的信息,非常类似于通知的效果。或者说可能你并不是希望服务不被系统回收,而是有其他特殊的需求(比如天气APP数据的服务)。

2. 代码示例

      用法很简单,只需要在原有的Service类对onCreate()方法进行稍微修改即可,本人亲测与是否可通信服务无关,如下:

8.0以下:

@Override    public void onCreate() {        super.onCreate();        System.out.println("执行了onCreat()");        //添加下列代码将后台Service变成前台Service        //构建"点击通知后打开MainActivity"的Intent对象        Intent notificationIntent = new Intent(this,MainActivity.class);        PendingIntent pendingIntent = PendingIntent.getActivity(this,0,notificationIntent,0);        //新建Builer对象        Notification.Builder builer = new Notification.Builder(this);        builer.setContentTitle("前台服务通知的标题");//设置通知的标题        builer.setContentText("前台服务通知的内容");//设置通知的内容        builer.setSmallIcon(R.mipmap.ic_launcher);//设置通知的图标        builer.setContentIntent(pendingIntent);//设置点击通知后的操作        Notification notification = builer.getNotification();//将Builder对象转变成普通的notification        startForeground(1, notification);//让Service变成前台Service,并在系统的状态栏显示出来    }

8.0以上:

 @Override    public void onCreate() {        super.onCreate();        Log.d(TAG, "onCreate: ");        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);        String channelId = getString(R.string.app_name);        NotificationChannel notificationChannel = new NotificationChannel(channelId, channelId, NotificationManager.IMPORTANCE_DEFAULT);        notificationChannel.setDescription(channelId);        notificationChannel.setSound(null, null);        notificationManager.createNotificationChannel(notificationChannel);        Intent intent = new Intent(getApplicationContext(), MainActivity.class);        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);        Notification.Builder builder = new Notification.Builder(this, channelId);        builder.setContentTitle("这是一个标题");        builder.setContentText("这是一个内容");        builder.setSmallIcon(R.mipmap.ic_launcher);        builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher));        builder.setContentIntent(pendingIntent);        Notification notification = builder.build();        startForeground(1, notification);    }

3. 测试结果(本人还是懒得截图,贴上原网站的图片)

     运行后,当点击Start Service或Bind Service按钮,Service就会以前台Service的模式启动(通知栏上有通知),如下图


  • 可通信的后台服务

1. 介绍

      普通的本地后台服务是最基础的,但只能单机使用,即无法与Activity通接下来将在上面的基础用法上,增设“与Activity通                    信”的功能,即使用绑定Service服务(Binder类、bindService()、onBind()、unbindService()、onUnbind())

           2. 使用步骤

                (1)在新建子类继承Service类,并新建一个子类继承自Binder类、写入与Activity关联需要的方法、创建实例。

                (2)在主布局文件再设置两个Button分别用于绑定和解绑Service。

                (3)在Activity通过调用MyBinder类中的public方法来实现Activity与Service的联系。

                               (即实现了Activity指挥Service干什么Service就去干什么的功能)

           3. 代码示例

MyService类

public class MyService extends Service {    private static final String TAG = "MyService";    private MyBinder mBinder = new MyBinder();    public MyService() {    }    class MyBinder extends Binder{        public void serviceConnectActivity(){            Log.d(TAG, "Service关联了Activity,并在Activity执行了Service的方法");        }    }    @Override    public void onCreate() {        super.onCreate();        Log.d(TAG, "onCreate: ");    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        Log.d(TAG, "onStartCommand: ");        return super.onStartCommand(intent, flags, startId);    }    @Override    public void onDestroy() {        Log.d(TAG, "onDestroy: ");        super.onDestroy();    }    @Override    public IBinder onBind(Intent intent) {        Log.d(TAG, "onBind: ");        return mBinder;    }    @Override    public boolean onUnbind(Intent intent) {        Log.d(TAG, "onUnbind: ");        return super.onUnbind(intent);    }}

 activity_main.xml

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

MainActivity类

public class MainActivity extends AppCompatActivity implements View.OnClickListener {    private MyService.MyBinder mMyBinder;    private ServiceConnection mServiceConnection = new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            mMyBinder = (MyService.MyBinder) service;            mMyBinder.serviceConnectActivity();        }        @Override        public void onServiceDisconnected(ComponentName name) {        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Button button1 = findViewById(R.id.button1);        Button button2 = findViewById(R.id.button2);        Button button3 = findViewById(R.id.button3);        Button button4 = findViewById(R.id.button4);        button1.setOnClickListener(this);        button2.setOnClickListener(this);        button3.setOnClickListener(this);        button4.setOnClickListener(this);    }    @Override    public void onClick(View v) {        Intent intent = new Intent(getApplicationContext(), MyService.class);        switch (v.getId()) {            case R.id.button1:                startService(intent);                break;            case R.id.button2:                stopService(intent);                break;            case R.id.button3:                bindService(intent, mServiceConnection, BIND_AUTO_CREATE);                break;            case R.id.button4:                unbindService(mServiceConnection);                break;        }    }}

           3.4 运行结果(按的顺序:开启服务-->绑定服务-->解绑服务-->停止服务)

05-01 23:29:07.025 2373-2373/com.peterli.communicationservice D/MyService: onCreate: 05-01 23:29:07.025 2373-2373/com.peterli.communicationservice D/MyService: onStartCommand: 05-01 23:29:10.075 2373-2373/com.peterli.communicationservice D/MyService: onBind: 05-01 23:29:10.105 2373-2373/com.peterli.communicationservice D/MyService: Service关联了Activity,并在Activity执行了Service的方法05-01 23:29:13.845 2373-2373/com.peterli.communicationservice D/MyService: onUnbind: 05-01 23:29:14.875 2373-2373/com.peterli.communicationservice D/MyService: onDestroy: 

  • 不可通信的后台服务

以本地后台为例,那个就是普通的不可通信后台服务,它并没有与其他组件进行通信。


 

五、Service(服务)各种类型的使用场景

  • 各种Service的使用场景请看下图:

 

六、IntentService的使用及其工作原理

1.定义

IntentServiceAndroid里的一个封装类,继承四大组件之一的Service

2.作用

处理异步请求和实现多线程,它可以简单地创建一个异步的、会自动停止的服务。

3.使用场景

线程任务需按顺序在后台执行

1.最常见的场景:离线下载

2.不符合多个数据同时请求的场景:所有的任务都在同一个Thread looper里执行

4.工作原理

4.1 流程示意图

     IntentService的工作原理和源码工作流程如下:

4.2 特别注意

       如果启动IntentsService多次,那么每个耗时操作则是以队列的方式在IntentsServiceonHandleIntent回调方法中依                      次执行,执行完自动结束。

5.源码分析

问题1:IntentService如何单独开启1个新的工作线程(主要从源码中的onCreate方法入手)

@Overridepublic void onCreate() {    super.onCreate();        // 1. 通过实例化HandlerThread新建线程 & 启动;故 使用IntentService时,不需额外新建线程    // HandlerThread继承自Thread,内部封装了 Looper    HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");    thread.start();      // 2. 获得工作线程的 Looper & 维护自己的工作队列    mServiceLooper = thread.getLooper();    // 3. 新建mServiceHandler & 绑定上述获得Looper    // 新建的Handler 属于工作线程 ->>分析1    mServiceHandler = new ServiceHandler(mServiceLooper); }   /**      * 分析1:ServiceHandler源码分析     **/      private final class ServiceHandler extends Handler {         // 构造函数         public ServiceHandler(Looper looper) {         super(looper);       }        // IntentService的handleMessage()把接收的消息交给onHandleIntent()处理        @Override         public void handleMessage(Message msg) {            // onHandleIntent 方法在工作线程中执行          // onHandleIntent() = 抽象方法,使用时需重写 ->>分析2          onHandleIntent((Intent)msg.obj);          // 执行完调用 stopSelf() 结束服务          stopSelf(msg.arg1);    }}   /**      * 分析2: onHandleIntent()源码分析     * onHandleIntent() = 抽象方法,使用时需重写     **/       @WorkerThread      protected abstract void onHandleIntent(Intent intent);

问题2:IntentService如何通过onStartCommand() 将Intent传递给服务还有依次插入到工作队列中

/**   * onStartCommand()源码分析  * onHandleIntent() = 抽象方法,使用时需重写  **/   public int onStartCommand(Intent intent, int flags, int startId) {    // 调用onStart()->>分析1    onStart(intent, startId);    return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;}/**   * 分析1:onStart(intent, startId)  **/   public void onStart(Intent intent, int startId) {    // 1. 获得ServiceHandler消息的引用    Message msg = mServiceHandler.obtainMessage();    msg.arg1 = startId;    // 2. 把 Intent参数 包装到 message 的 obj 发送消息中,    //这里的Intent  = 启动服务时startService(Intent) 里传入的 Intent    msg.obj = intent;    // 3. 发送消息,即 添加到消息队列里    mServiceHandler.sendMessage(msg);}

6.源码总结

从上面源码可以看出:IntentService本质 = Handler + HandlerThread

1. 通过HandlerThread单独开启1个工作线程(子线程):IntentService

2. 创建1个内部HandlerServiceHandler

3. 绑定ServiceHandlerIntentService

4. 通过onStartCommand()传递服务intentServiceHandler、依次插入Intent到工作队列中并且逐个发送给                                         onHandleIntent()

5. 通过onHandleIntent()依次处理所有Intent对象所对应的任务 

  (因此我们通过重写onHandleIntent()在里面根据Intent的不同进行不同线程操作即可)

7.注意事项

此处,有两个注意事项需要关注的:

     1. 工作任务队列 = 顺序执行

     2. 不建议通过bindService()启动IntentService

注意事项1:工作任务队列 = 顺序执行

解释:

即如果一个任务正在IntentService中执行,此时你再发送1个新的任务请求,这个新的任务会一直等待直到前面一个任务执行完毕后才开始执行。

原因:

1. 由于onCreate()只会调用一次,所以它只会创建1个工作线程(子线程);

2. 当多次调用startService()时(即onStartCommand()也会调用多次),其实不会创建新的工作线程,只是把消息加入消                     息队列中等待执行;

3. 所以,多次启动IntentService会按照顺序执行事件(若服务停止,则会清除消息队列中的消息,后续的事件不再执行)

注意事项2:不建议通过bindService()启动IntentService

原因:

// 在IntentService中,onBind()默认返回null    @Override    @Nullable    public IBinder onBind(Intent intent) {        return null;    }
  • 采用bindService()启动IntentService的生命周期如下:

onCreate() -->onBind() --> onUnbind() --> onDestory()

  • 由上面生命周期可以得知不会调用onStart()onStartCommand(),故不会将消息发送到消息队列,那么也就是说onHandleIntent()也将不会回调,即无法实现多线程的操作(所以,此时你应该使用Service,而不是IntentService

 

七、IntentService与Service(服务)、Thread(普通线程)的区别

此处主要讲解IntentServiceService(服务)Thread(普通线程)的区别。

1.  IntentService与Service(服务)的区别

2.  IntentService与Thread(普通线程)的区别

 

八、Service(服务)与Thread(线程)的区别

  • 结论:Service与Thread无任何关系!!!
  • 之所以会有不少人把他们联系起来,主要是因为Service的后台概念(后台:后台任务运行完全不依赖UI,即时活动被销毁或者说程序被关闭,只要进程还在,后台任务就可以继续运行)
  • 关于二者的异同,具体如下图:

  • 注:一般会将Service和Thread联合着用,即在Service中再创建一个子线程(工作线程)去处理耗时操作逻辑,如下代码:
@Override  public int onStartCommand(Intent intent, int flags, int startId) {  //新建工作线程    new Thread(new Runnable() {          @Override          public void run() {              // 开始执行后台任务          }      }).start();      return super.onStartCommand(intent, flags, startId);  }    class MyBinder extends Binder {      public void service_connect_Activity() {    //新建工作线程        new Thread(new Runnable() {              @Override              public void run() {                  // 执行具体的下载任务              }          }).start();      }    }  

 

更多相关文章

  1. 如何解决本地大批量数据的更新,和后台的同步,讲解socket的IPC和soc
  2. [置顶] 解决android某些应用开发某些类无法解析/找到的问题--使
  3. Android面试真题,了解一下?
  4. 实现两次按返回键退出的五种方法
  5. ListView的两次测量(源码分析)
  6. android解析xml和json区别
  7. android推送服务overview
  8. 向android 的状态栏中加入快捷按钮(home,back,menu等等)的方法(续)
  9. android 前后台保活 实现定位数据定时上传并展示轨迹 (上)

随机推荐

  1. 客觀評 Android、iOS、WP7
  2. Android系统触摸屏的校正——http://carv
  3. Android Studio com.android.dex.DexExce
  4. 【Android休眠】之Android休眠机制
  5. Android面试经验二:
  6. 个人认为安卓开发前景
  7. android Uid 与 Pid 的区别与用法
  8. Android工程 引用另外一个Android工程(zz
  9. Android 里的Intent是什么意思
  10. Android:增强目录选择器对话框