zoukankan      html  css  js  c++  java
  • 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()方法中

  • 相关阅读:
    在vue项目中stylus的安装及使用
    如何在vue中全局引入stylus文件的公共变量
    d3.js在vue项目中的安装及案例
    cytoscape.js在vue项目中的安装及案例
    vue路由router的三种传参方式
    vue项目警告There are multiple modules with names that only differ in casing
    vue+iview实现一行平均五列布局
    JVM 内存对象管理
    JVM 垃圾回收机制
    面试随笔-01
  • 原文地址:https://www.cnblogs.com/chhom/p/4717832.html
Copyright © 2011-2022 走看看