Service

一、

1、概念:Android的四大组件之一,是一个没有用户界面长期在后台运行执行“耗时操作”的应用组件

2、服务与Activity的区别:

相同点:都是四大组件,需要在清单文件中注册,都运行在主线程,都有生命周期

        <service
            android:name=".service.MyService"
            android:enabled="true"
            android:exported="true" />

不同点:Activity有界面,Service没有界面,Activity运行在前台与用户进行交互,Service运行在后台。

3、服务与线程的区别:

Thread:是程序执行的最小单元,他是分配CPU的基本单位,可以做一些耗时操作(异步任务)

Service更多的时候充当线程管理者的角色。

4、服务的分类

运行的位置:本地服务(Local Service)、远程服务remote

启动方式:startService和BindService

5、启动的特点:

startService:服务一旦被启动就与启动他的组件失去了关系。

bindService:与启动他的组件绑在一起(同进退。共生死)

6、服务只能被解绑一次,多次解绑会抛出异常。

二、服务的生命周期

1、startService

onCreate -->onStartConmmand(可以执行多次) -->onDestroy(stopService,stopSelf)

开启服务startService:onCreate,onStartCommand

返回键:没有变化,在后台运行

多次点击开启服务:onStartCommand

结束服务stopService:onDestroy;还有一种自杀stopSelf

2、bindService

onCreate-->onbind-->onUnbind-->ondestroy

        <service
            android:name=".service.MyService"
            android:enabled="true"
            android:exported="true" />
        //启动一个服务
        btnStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivity.this, MyService.class);
                intent.putExtra("info", "ssssssssssss");
                startService(intent);
            }
        });
        //停止一个服务
        butStop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivity.this, MyService.class);
                stopService(intent);
            }
        });
/**
 * started service:
 * 1.服务同时只会被创建一次,可以通过外部调用stopService或调用stopSelf来终止服务
 * 2.当执行一个已启动的服务,会直接调用onStartCommand方法来执行业务
 * 3.默认情况下服务与主线程在同一个进程中的同一个线程中运行,如果服务执行一个比较耗时的操作,我们必须使子线程来完成工作,避免主线程被阻塞
 * 4.使用started Service启动的一个服务,在没有关闭之前会一直在后台运行
 */
public class MyService extends Service {
    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public void onCreate() {
        super.onCreate();
        System.out.println("!!!my service create");
    }


    //在该方法中实现服务的核心业务
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        System.out.println("!!!!!!" + intent.getStringExtra("info"));


        //这个阻塞主线程
//        for (int i = 0; i < 10; i++) {
//            System.out.println("!!!" + "onStartCommand" +i+Thread.currentThread().getName());
//            try {
//                Thread.sleep(500);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//
////            if (i == 5) {
////                this.stopSelf();//终止服务
////                break;
////            }
//        }

        //使用线程完成长时间的工作
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 40; i++) {
                    System.out.println("!!!" + "onStartCommand" + i + Thread.currentThread().getName());
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    if (i == 10) {
                        MyService.this.stopSelf();//终止服务
                        break;
                    }
                }
            }
        }).start();

        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        System.out.println("!!!my service destroy");
    }
}

三、IntentService

是Service的子类

特点:

1、其他组件调用startService启动IntentService服务时,会依次执行onCreate-->onStartCommand-->onHandleIntent-->onDestroy,说明IntetnService在onHandleIntent方法中处理完成意图对象后会销毁服务

2、IntentService底层采用请求队列对Intent请求意图对象进行管理

        <service
            android:name=".service.MyIntentService"
            android:exported="false" />
//启动一个IntentService服务
        btnStartIntent.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivity.this, MyIntentService.class);
                startService(intent);
            }
        });
/**
 * IntentService:
 * 1.内部有一个工作线程来完成耗时操作,只需实现onHandleIntent方法即可
 * 2.完成工作后会自动停止服务
 * 3.如果同时执行多个任务时,会以队列的方式,依次执行
 * 4.通常使用该类来完成本APP中的耗时工作
 */
public class MyIntentService extends IntentService {

    public MyIntentService() {
        super("MyIntentService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {

        for (int i = 0; i < 30; i++) {
            System.out.println("!!!" + i + Thread.currentThread().getName());
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

}

 绑定一个Service

        //绑定一个服务
        btnBind.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivity.this, MyBindService.class);
                //异步绑定,绑定成功会回调onServiceConnected
                bindService(intent, connection, Context.BIND_AUTO_CREATE);
            }
        });

        //绑定服务的连接回调
        connection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName componentName, IBinder iBinder) {

                //绑定成功后的回调方法
                iCat = ICat.Stub.asInterface(iBinder);
                mBound = true;
            }

            @Override
            public void onServiceDisconnected(ComponentName componentName) {

                //服务异常时回调
                mBound = false;
            }
        };

        //通过IPC调用业务方法
        btnCallClick.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (iCat == null) {
                    return;
                }
                try {
                    iCat.setName("小猫");
                    Toast.makeText(MainActivity.this, iCat.desc().toString(), Toast.LENGTH_SHORT).show();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        //解绑一个服务
        btnUnbind.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (mBound) {
                    unbindService(connection);
                }
            }
        });
/**
 *绑定服务:
 * 通过绑定服务实现功能的步骤:
 * 1、客户端通过bindService方法来绑定一个服务对象,如果绑定成功,会回调ServiceConnection接口方法onServiceConnected
 * 2、通过Service组件来暴露业务接口
 * 3、服务端通过创建一个*.aidl文件来定义一个可以被客户端调用的业务接口
 *   一个aidl文件:
 *   (1)不能有修饰符,类似接口写法
 *   (2)支持类型有:8中基本数据类型,String,CharSequeue,List<String> map,自定义类型
 * 4、服务端需要提供一个业务接口的实现类,通过我么会继承Stub类
 * 5、通过Service的onBind方法返回被绑定的业务对象
 * 6、客户端如果绑定成功,就可以像调用自己的方法一样调用远程的方法
 */

public class MyBindService extends Service{

    public MyBindService() {
        super();
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return new CatImpl();
    }

    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}
interface ICat {

    void setName(String name);
    String desc();
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);
}
public class CatImpl extends ICat.Stub {
    private String name;

    @Override
    public void setName(String name) throws RemoteException {
        this.name = name;
    }

    @Override
    public String desc() throws RemoteException {
        return "hello ,my name is " + name;
    }

    @Override
    public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

    }
}

2.Android多线程编程

2.1.线程的基本用法:

匿名类的方式定义和实现一个线程:

new Thread(new Runnable(){

@Override

public void run(){

//处理具体逻辑

}

}).start();

2.2在子线程中更新UI

public class MainActivity extends Activity implements OnClickListener{
    public static final int UPDATE_TEXT=1
    //先定义一个UPDATE_TEXT,用于表示更新TextView这个动作
    private TextView text;
    private Buuton changeText;
    private Handler handler=new Handler(){

        //新增一个handler对象,并重写父类的handleMessage方法,在这里对具体的Message进行处理
        public void handleMessage(Message msg){
            switch(msg.what){
                case UPDATE_TEXT:
                //在这里进行UI操作
                //如果发现Message的what字段值等于UPDATE_TEXT,就将TextView显示的内容改成nice
                text.setText("nice");
                break;
            }
        }
    };

    @Override

    public void onClick(View v){
        switch(v.getId){
            case R.id.change_text:
            new Thread(new Runnable(){
                @Override
                public void run(){
                    Message message=new Message();
                    message.what=UPDATE_TEXT;
                    handler.sendMessage(message);//将Message对象发送出去
                }
            });
            break;
        default:
            break;
        }
    }
}

2.3解析异步消息处理机制

Android中的异步消息处理主要由四个部分组成,Message、Handler、MessageQueue和Looper

2.3.1Message

Message是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间交换数据,有Message的what字段,,除此之外还可以用arg1和arg2字段来携带一些整型数据,使用obj字段携带一个Object对象

2.3.2Handler

Handler顾名思义也就是处理者的意思,它主要是用于发送和处理消息的。发送消息一般是使用Handler的sendMessage()方法,而发出的消息经过一系列的辗转处理后,最终会传递到Handler的handleMessage()方法中。

2.3.3MessageQueue

是消息列队的意思,它主要是用于存放所有通过Handler发送的消息,这部分消息会一直存在于消息的队列中,等待被处理。每个线程中只会有一个MessageQueue()对象

2.3.4Looper

Looper是每个线程中的MessageQueue的管家,调用Looper的loop()方法后,就会进入到一个无限循环当中,然后每当发现MessageQueue中存在一条消息,就会将他取出,并传递到Handler的handleMessage()方法中,每个线程也只有一个Looper对象

异步消息处理的流程:

首先需要在主线程中创建一个Handler对象,并重写handleMessage()方法

然后当子线程中需要进行UI操作时,就创建一个Message对象,并通过Handler将这条消息发送出去,之后这条消息会被添加到MessageQueue的队列中等待被处理,而Looper则会一直尝试从MessageQueue中去除待处理的消息

最后分发回Handler的handleMessage()方法中

原文地址:https://www.cnblogs.com/chhom/p/4717832.html