Android中四大组件详解Activity、Service、ContentProvider、broadcastReceiver

四大组件分别为Activity、Service、ContentProvider、BroadcastReceiver。
1、Activity
(1)一个activity通常就是一个界面。
(2)Activty的生命周期的也就是它所在进程的生命周期。
一个Activity的启动顺序:
onCreate() → onStart() → onResume()
当另一个Activity启动时:
第一个Activity onPause() → 第二个Activity onCreate() → onStart() → onResume() → 第一个Activity onStop()
当返回到第一个Activity时:
第二个Activity onPause() → 第一个Activity onRestart() → onStart() → onResume() → 第二个Activity onStop() → onDestroy()
一个Activity的销毁顺序:
(情况一)onPause() → <Process Killed>
(情况二)onPause() → onStop() → <Process Killed>
(情况三)onPause() → onStop() → onDestroy()
(3)在实现 Activity 类的时候,通过覆盖( override )这些方法即可在你需要处理的时候来调用。
onCreate:当活动第一次启动的时候,触发该方法,可以在此时完成活动的初始化工作。
onStart:该方法的触发表示所属活动将被展现给用户。
onResume:当一个活动和用户发生交互的时候,触发该方法
onPause:当一个正在前台运行的活动因为其他的活动需要前台运行而转入后台运行的时候,触发该方法。这时候需要将活动的状态持久化,比如正在编辑的数据库记录等。
onStop:当一个活动不再需要展示给用户的时候,触发该方法。如果内存紧张,系统会直接结束这个活动,而不会触发 onStop 方法。 所以保存状态信息是应该在onPause时做,而不是onStop时做。活动如果没有在前台运行,都将被停止或者Linux管理进程为了给新的活动预留足够的存储空间而随时结束这些活动。因此对于开发者来说,在设计应用程序的时候,必须时刻牢记这一原则。在一些情况下,onPause方法或许是活动触发的最后的方法,因此开发者需要在这个时候保存需要保存的信息。
onRestart:当处于停止状态的活动需要再次展现给用户的时候,触发该方法。
onDestroy:当活动销毁的时候,触发该方法。和 onStop 方法一样,如果内存紧张,系统会直接结束这个活动而不会触发该方法。
(4)Activity栈
每个Activity的状态是由它在Activity栈(是一个后进先出)中的位置决定的。
如果用户使用后退按钮返回的话,或者前台的Activity结束,活动的Activity就会被移出栈消亡,而在栈上的上一个活动的Activity将会移上来并变为活动状态。
(5)Activity一般认为Activity有以下四种状态:
活动状态:当一个Activity在栈顶,它是可视的、有焦点、可接受用户输入的。Android试图尽最大可能保持它活动状态,杀死其它Activity来确保当前活动Activity有足够的资源可使用。当另外一个Activity被激活,这个将会被暂停。
暂停状态:在很多情况下,你的Activity可视但是它没有焦点,换句话说它被暂停了。有可能原因是一个透明或者非全屏的Activity被激活。当被暂停,一个Activity仍会当成活动状态,只不过是不可以接受用户输入。在极特殊的情况下,Android将会杀死一个暂停的Activity来为活动的Activity提供充足的资源。当一个Activity变为完全隐藏,它将会变成停止。
停止状态:当一个Activity不是可视的,它“停止”了。这个Activity将仍然在内存中保存它所有的状态和会员信息。尽管如此,当其它地方需要内存时,它将是最有可能被释放资源的。当一个Activity停止后,一个很重要的步骤是要保存数据和当前UI状态。一旦一个Activity退出或关闭了,它将变为待用状态。
待用状态:在一个Activity被杀死后和被装在前,它是待用状态的。待用Acitivity被移除Activity栈,并且需要在显示和可用之前重新启动它。
(6)activity的四种加载模式,在android的多activity开发中,activity之间的跳转可能需要有多种方式,有时是普通的生成一个新实例,有时希望跳转到原来某个activity实例,而不是生成大量的重复的activity。加载模式便是决定以哪种方式启动一个跳转到原来某个Activity实例。
standard:标准模式,一调用startActivity()方法就会产生一个新的实例。
singleTop:如果已经有一个实例位于Activity栈的顶部时,就不产生新的实例,而只是调用Activity中的newInstance()方法。如果不位于栈顶,会产生一个新的实例。
singleTask:只有一个实例。在同一个应用程序中启动他的时候,若Activity不存在,则会在当前task创建一个新的实例,若存在,则会把task中在其之上的其它Activity destory掉并调用它的onNewIntent方法。
如果是在别的应用程序中启动它,则会新建一个task,并在该task中启动这个Activity,singleTask允许别的Activity与其在一个task中共存,也就是说,如果我在这个singleTask的实例中再打开新的Activity,这个新的Activity还是会在singleTask的实例的task中。
singleInstance:只有一个实例,并且这个实例独立运行在一个task中,这个task只有这个实例,不允许有别的Activity存在。
这些启动模式可以在功能清单文件AndroidManifest.xml中进行设置,中的launchMode属性。
(7)activity之间通过Intent进行通信。
(8)android应用中每一个activity都必须在AndroidManifest.xml配置文件中声明,否则系统不识别也不执行该activity。


2、Service
(1)Service用于在后台完成用户指定的操作。
(2)Service分为两种:
started:当应用程序组件调用startService()方法启动服务时,服务处于启动状态。
bound:当应用程序组件调用bindService()方法绑定服务时,服务处于绑定状态。
(3)startService()和bindService()方法的区别
started Service是由其他组件调用startService()方法启动的,这导致服务的onStartCommand()方法被调用,当服务是start状态时,其生命周期与启动它的组件无关。并且可以在后台无期限运行。因此服务在完成任务后调用stopSelf()方法停止,或者由其他组件调用stopService()方法停止。
使用bindService()方法启动服务时,调用者与服务绑定在一起,调用者一旦退出,服务也就终止。
(4)开发人员需要在应用程序配置文件中声明全部的service,使用<service></service>标签。
(5)Service通常在后台运行,它一般不需要与用户交互,因此Service组件没有图形用户界面。Service组件通常需要继承Service基类,Service组件通常用于为其他组件提供后台服务或监听其他组件运行状态。
(6)本地服务和远程服务
Service其实是运行在主线程里的,如果直接在Service中处理一些耗时的逻辑,就会导致程序ANR。

    public class MyService extends Service {  
      
        ......  
      
        @Override  
        public void onCreate() {  
            super.onCreate();  
            Log.d(TAG, "onCreate() executed");  
            try {  
                Thread.sleep(60000);  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
        }  
          
        ......  
      
    }  

将一个普通的Service转换成远程Service其实非常简单,只需要在注册Service的时候将它的android:process属性指定成:remote就可以了
为什么将MyService转换成远程Service后就不会导致程序ANR了呢?这是由于,使用了远程Service后,MyService已经在另外一个进程当中运行了,所以只会阻塞该进程中的主线程,并不会影响到当前的应用程序。
首先将MyService的onCreate()方法中让线程睡眠的代码去除掉,然后重新运行程序,并点击一下Bind Service按钮,你会发现程序崩溃了!为什么点击Start Service按钮程序就不会崩溃,而点击Bind Service按钮就会崩溃呢?这是由于在Bind Service按钮的点击事件里面我们会让MainActivity和MyService建立关联,但是目前MyService已经是一个远程Service了,Activity和Service运行在两个不同的进程当中,这时就不能再使用传统的建立关联的方式,程序也就崩溃了。
那么如何才能让Activity与一个远程Service建立关联呢?这就要使用AIDL来进行跨进程通信了(IPC)。
AIDL(Android Interface Definition Language)是Android接口定义语言的意思,它可以用于让某个Service与多个应用程序组件之间进行跨进程通信,从而可以实现多个应用程序共享同一个Service的功能。
解析:AIDL的用法
首先需要新建一个AIDL文件,在这个文件中定义好Activity需要与Service进行通信的方法。新建MyAIDLService.aidl文件,代码如下所示

interface MyAIDLService {  
    int plus(int a, int b);  
    String toUpperCase(String str);  
}  

然后修改MyService中的代码,在里面实现我们刚刚定义好的MyAIDLService接口,如下所示

    public class MyService extends Service {  
      
        ......  
      
        @Override  
        public IBinder onBind(Intent intent) {  
            return mBinder;  
        }  
      
        MyAIDLService.Stub mBinder = new Stub() {  
      
            @Override  
            public String toUpperCase(String str) throws RemoteException {  
                if (str != null) {  
                    return str.toUpperCase();  
                }  
                return null;  
            }  
      
            @Override  
            public int plus(int a, int b) throws RemoteException {  
                return a + b;  
            }  
        };  
      
    }  

这里先是对MyAIDLService.Stub进行了实现,重写里了toUpperCase()和plus()这两个方法。这两个方法的作用分别是将一个字符串全部转换成大写格式,以及将两个传入的整数进行相加。然后在onBind()方法中将MyAIDLService.Stub的实现返回。这里为什么可以这样写呢?因为Stub其实就是Binder的子类,所以在onBind()方法中可以直接返回Stub的实现。

    public class MainActivity extends Activity implements OnClickListener {  
      
        private Button startService;  
      
        private Button stopService;  
      
        private Button bindService;  
      
        private Button unbindService;  
          
        private MyAIDLService myAIDLService;  
      
        private ServiceConnection connection = new ServiceConnection() {  
      
            @Override  
            public void onServiceDisconnected(ComponentName name) {  
            }  
      
            @Override  
            public void onServiceConnected(ComponentName name, IBinder service) {  
                myAIDLService = MyAIDLService.Stub.asInterface(service);  
                try {  
                    int result = myAIDLService.plus(3, 5);  
                    String upperStr = myAIDLService.toUpperCase("hello world");  
                    Log.d("TAG", "result is " + result);  
                    Log.d("TAG", "upperStr is " + upperStr);  
                } catch (RemoteException e) {  
                    e.printStackTrace();  
                }  
            }  
        };  
      
        ......  
      
    }  

我们只是修改了ServiceConnection中的代码。可以看到,这里首先使用了MyAIDLService.Stub.asInterface()方法将传入的IBinder对象传换成了MyAIDLService对象,接下来就可以调用在MyAIDLService.aidl文件中定义的所有接口了。这里我们先是调用了plus()方法,并传入了3和5作为参数,然后又调用了toUpperCase()方法,并传入hello world字符串作为参数,最后将调用方法的返回结果打印出来。
那么下面我们自然要学习一下,如何才能在其它的应用程序中调用到MyService里的方法。
另一个应用程序中去绑定Service的时候并没有MyService这个类,这时就必须使用到隐式Intent了。现在修改AndroidManifest.xml中的代码,给MyService加上一个action,如下所示:

<service  
        android:name="com.example.servicetest.MyService"  
        android:process=":remote" >  
        <intent-filter>  
            <action android:name="com.example.servicetest.MyAIDLService"/>  
        </intent-filter>  
    </service>  

这就说明,MyService可以响应带有com.example.servicetest.MyAIDLService这个action的Intent。
如果想要和MyService建立关联其实也不难,首先需要将MyAIDLService.aidl文件从ServiceTest项目中拷贝过来,注意要将原有的包路径一起拷贝过来
接下来打开或新建MainActivity,在其中加入和MyService建立关联的代码,如下所示

    public class MainActivity extends Activity {  
      
        private MyAIDLService myAIDLService;  
      
        private ServiceConnection connection = new ServiceConnection() {  
      
            @Override  
            public void onServiceDisconnected(ComponentName name) {  
            }  
      
            @Override  
            public void onServiceConnected(ComponentName name, IBinder service) {  
                myAIDLService = MyAIDLService.Stub.asInterface(service);  
                try {  
                    int result = myAIDLService.plus(50, 50);  
                    String upperStr = myAIDLService.toUpperCase("comes from ClientTest");  
                    Log.d("TAG", "result is " + result);  
                    Log.d("TAG", "upperStr is " + upperStr);  
                } catch (RemoteException e) {  
                    e.printStackTrace();  
                }  
            }  
        };  
      
        @Override  
        protected void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.activity_main);  
            Button bindService = (Button) findViewById(R.id.bind_service);  
            bindService.setOnClickListener(new OnClickListener() {  
                @Override  
                public void onClick(View v) {  
                    Intent intent = new Intent("com.example.servicetest.MyAIDLService");  
                    bindService(intent, connection, BIND_AUTO_CREATE);  
                }  
            });  
        }  
      
    }  

这和在ServiceTest的MainActivity中的代码几乎是完全相同的,只是在让Activity和Service建立关联的时候我们使用了隐式Intent,将Intent的action指定成了com.example.servicetest.MyAIDLService。
在当前Activity和MyService建立关联之后,我们仍然是调用了plus()和toUpperCase()这两个方法,远程的MyService会对传入的参数进行处理并返回结果,然后将结果打印出来。
(7)Service基本用法
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;  
        }  
    }  

启动和终止服务Activity代码

    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;  
            }  
        }  
    }  

注意:项目中的每一个Service都必须在AndroidManifest.xml中注册才行

<service android:name=".service.MyService"/>

onCreate()方法只会在Service第一次被创建的时候调用,如果当前Service已经被创建过了,不管怎样调用startService()方法,onCreate()方法都不会再执行。
(8)Service和Activity通信
观察MyService中的代码,你会发现一直有一个onBind()方法我们都没有使用到,这个方法其实就是用于和Activity建立关联的,修改MyService中的代码,如下所示:

扫描二维码关注公众号,回复: 5213403 查看本文章
    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;  
        }  
      
        public class MyBinder extends Binder {  
      
            public void startDownload() {  
                Log.d("TAG", "startDownload() executed");  
                // 执行具体的下载任务  
            }  
      
        }  
      
    }  

接下来再修改MainActivity中的代码,让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;  
            }  
        }   
    }  

可以看到,这里我们首先创建了一个ServiceConnection的匿名类,在里面重写了onServiceConnected()方法和onServiceDisconnected()方法,这两个方法分别会在Activity与Service建立关联和解除关联的时候调用。在onServiceConnected()方法中,我们又通过向下转型得到了MyBinder的实例,有了这个实例,Activity和Service之间的关系就变得非常紧密了。现在我们可以在Activity中根据具体的场景来调用MyBinder中的任何public方法,即实现了Activity指挥Service干什么Service就去干什么的功能。
当然,现在Activity和Service其实还没关联起来了呢,这个功能是在Bind Service按钮的点击事件里完成的。可以看到,这里我们仍然是构建出了一个Intent对象,然后调用bindService()方法将Activity和Service进行绑定。bindService()方法接收三个参数,第一个参数就是刚刚构建出的Intent对象,第二个参数是前面创建出的ServiceConnection的实例,第三个参数是一个标志位,这里传入BIND_AUTO_CREATE表示在Activity和Service建立关联后自动创建Service,这会使得MyService中的onCreate()方法得到执行,但onStartCommand()方法不会执行。
(9)如何销毁Service
在Service的基本用法这一部分,我们介绍了销毁Service最简单的一种情况,点击Start Service按钮启动Service,再点击Stop Service按钮停止Service,这样MyService就被销毁了
如果我们是点击的Bind Service按钮呢?由于在绑定Service的时候指定的标志位是BIND_AUTO_CREATE,说明点击Bind Service按钮的时候Service也会被创建,这时应该怎么销毁Service呢?其实也很简单,点击一下Unbind Service按钮,将Activity和Service的关联解除就可以了。
那么如果我们既点击了Start Service按钮,又点击了Bind Service按钮会怎么样呢?这个时候你会发现,不管你是单独点击Stop Service按钮还是Unbind Service按钮,Service都不会被销毁,必要将两个按钮都点击一下,Service才会被销毁。也就是说,点击Stop Service按钮只会让Service停止,点击Unbind Service按钮只会让Service和Activity解除关联,一个Service必须要在既没有和任何Activity关联又处理停止状态的时候才会被销毁
我们应该始终记得在Service的onDestroy()方法里去清理掉那些不再使用的资源,防止在Service被销毁后还会有一些不再使用的对象仍占用着内存。
(10)Service和Thread的关系
所有的Activity都可以与Service进行关联,然后可以很方便地操作其中的方法,即使Activity被销毁了,之后只要重新与Service建立关联,就又能够获取到原有的Service中Binder的实例。因此,使用Service来处理后台任务,Activity就可以放心地finish,完全不需要担心无法对后台任务进行控制的情况。

public class MyService extends Service {
    public static final String TAG = "MyService";
    private MyBinder mBinder = new MyBinder();

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    @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");
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 开始执行后台任务
                Log.d(TAG, "onStartCommand() Runnable  executed");
            }
        }).start();
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        Log.d(TAG, "onDestroy() executed");
        super.onDestroy();
    }
    public class MyBinder extends Binder {

        public void startDownload() {
            Log.d("MyService" + "", "startDownload() executed");
            // 执行具体的下载任务
            new Thread(new Runnable() {
                @Override
                public void run() {
                    // 开始执行后台任务
                    Log.d(TAG, "startDownload() Runnable  executed");
                }
            }).start();
        }

    }
}

(11)创建前台Service
前台Service和普通Service最大的区别就在于,它会一直有一个正在运行的图标在系统的状态栏显示,下拉状态栏后可以看到更加详细的信息,非常类似于通知的效果。当然有时候你也可能不仅仅是为了防止Service被回收才使用前台Service,有些项目由于特殊的需求会要求必须使用前台Service,比如说墨迹天气,它的Service在后台更新天气数据的同时,还会在系统状态栏一直显示当前天气的信息。
创建一个前台Service代码:

    public class MyService extends Service {  
      
        public static final String TAG = "MyService";  
      
        private MyBinder mBinder = new MyBinder();  
      
        @Override  
        public void onCreate() {  
            super.onCreate();  
            NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        Notification.Builder builder = new Notification.Builder(getApplicationContext());
        builder.setContentTitle("通知的标题");
        builder.setContentText("这是通知的内容");
        builder.setSmallIcon(R.mipmap.ic_launcher);
        Notification notification = builder.build();
        manager.notify(1, notification);
            Log.d(TAG, "onCreate() executed");  
        }  
      
        .........  
      
    }  

这里只是修改了MyService中onCreate()方法的代码。可以看到,我们首先创建了一个Notification对象,然后调用了它的setLatestEventInfo()方法来为通知初始化布局和数据,并在这里设置了点击通知后就打开MainActivity。然后调用startForeground()方法就可以让MyService变成一个前台Service,并会将通知的图片显示出来。

3、ContentProvider
(1)ContentProvider使一个应用程序的指定数据集提供给其他应用程序。其他应用程序通过ContentResolver类从该内容提供者中获取或存入数据。
(2)只有在多个应用程序间共享数据时才使用内容提供者。如通讯录数据被多个应用程序使用,切必须存在一个内容提供者中。他的好处就是统一数据访问方式。
(3)ContentProvider实现数据共享。ContentProvider用于保存和获取数据,并使其对所有应用程序可见。这是不同应用程序间共享数据的唯一方式,因为android没有提供所有应用共同访问的公共存储区。
(4)开发人员不会直接使用ContentProvider类对象,大多数是通过ContentResolver对象实现对ContentProvider的操作。
(5)ContentProvider使用URI来唯一标识其数据集,这里的URI以content://作为前缀,表示该数据由ContentProvider来管理


4、broadcastReceiver
(1)你的应用可以使用它对外部事件进行过滤,只对感兴趣的外部事件(如当电话呼入时,或者数据网络可用时)进行接收并做出响应。广播接收器没有用户界面。然而,它们可以启动一个activity或serice来响应它们收到的信息,或者用NotificationManager来通知用户。通知可以用很多种方式来吸引用户的注意力,例如闪动背灯、震动、播放声音等。一般来说是在状态栏上放一个持久的图标,用户可以打开它并获取消息。
(2)广播接收者的注册有两种方法,分别是程序动态注册和AndroidManifest文件中进行静态注册。
(3)动态注册广播接收器特点是当用来注册的Activity关掉后,广播也就失效了。静态注册无需担忧广播接收器是否被关闭,只要设备是开启状态,广播接收器也是打开着的。也就是说哪怕app本身未启动,该app订阅的广播在触发时也会对它起作用。
(4)广播最大的特点就是发送方不关心接收方是否接收到数据,也不关心接收方如何处理数据,通过这样的方式达到接收,发送双方完全解耦
(5)普通广播
context.sendBroadcast(Intent)发送
创建广播代码如下:

private class SystemMessageReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            
        }
    }

监听广播Intent步骤:
写一个继承BroadcastReceiver的类,重写onReceive()方法,广播接收器仅在它执行这个方法时处于活跃状态,当onReceive()返回后,它即为失活状态。注意:为了保证用户交互过程的流畅,一些费时的操作要放到线程中
注册广播接受者
注册有两种方法:程序动态注册和AndroidManifest文件中进行静态注册
1.静态注册,下面的priority表示接收广播的优先级(-1000到1000)

<receiver android:name=".MyBroadcastReceiver">
     <intent-filter android:priority="1">
          <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
     </intent-filter>
</receiver>
 2.动态注册,一般在Activity可交互时onResume()内注册BroadcastReceiver
IntentFilter intentFilter = new InentFilter("标示")
MyBroadcastReceiver receiver = new MyBroadcastReceiver();
registerReceiver(receiver, intentFilter);
//反注册BroadcastReceiver必须遵循生到死的周期,如果你是使用动态注册广播的则需要在Activity的onDestroy的时候反注册广播
unregisterReceiver(receiver);

通过sendBroadcast()方法发送创建的Intent自定义广播代码如下:

Intent intent= new Intent();
intent.setAction("标记");
intent.putExtra("键", "值");
sendBroadcast(intent);

动态注册广播还有一个特点,当注册广播的Activity关闭后,注册的广播也失效。
静态注册的广播则无需关心广播接收器是否被关闭,只要设备是开启状态,广播接收器也是打开的。
(6)有序广播
content.sendOrderedBroadcastReceiver(intent, receiverPermission) (第二个参数决定广播的级别)
(1)当广播接收器接收到广播后,可以使用onResult()函数结果传递给下一个广播接收器接收,然后通过getResult()函数来获取上一个广播接收器接收返回的结果。当广播接收器接收到广播后,也可以用abortBroadcast()函数来让系统拦截下来该广播,并将广播丢弃,使该广播不再传递到别的广播接收器接收
(2)有优先级的广播接收者,并在最高级广播中传递结果到下一个广播代码如下:

public class OrderBroadcastReceiver{
     public static class SeniorOrder extends BroadcastReceiver{
          @Override
          public void onReceive(Content content, Intent intent){
          //传递到下一个广播接收器
          int code = 0;
          String data = "mes";
          String bundle = null;
          setResult(code, data, bundle);
     }

     public static class IntermediateOrder extends BroadcastReceiver{
          @Override
          public void onReceive(Content content, Intent intent){
          //获取上一个广播接收器结果
          int code = getResultCode();
          String data = getResultData();
          Log.i("receive", "code=" + code + "data=" + data);
        }
     }
     public static class LowerOrder extends BroadcastReceiver {
          @Override
          public void onReceive(Context context, Intent intent) {
          }
     }
}

注意:内部类的BroadcastReceiver必须由public static来修饰否则会报错
(3)注册广播(priority属性来设置广播的优先级)

<receiver android:name=".OrderBroadcastReceiver$SeniorOrder">
    <intent-filter android:priority="1000">
        <action android:name="message" />
    </intent-filter>
</receiver>
<receiver android:name=".OrderBroadcastReceiver$IntermediateOrder ">
    <intent-filter android:priority="500">
        <action android:name="message" />
    </intent-filter>
</receiver>
<receiver android:name=".OrderBroadcastReceiver$LowerOrder">
    <intent-filter android:priority="10">
        <action android:name="message" />
    </intent-filter>
</receiver>

注意:类名与内部类名之间用$来分割
发送广播

Intent intent= new Intent();
intent.setAction(intent);
sendOrderedBroadcast(intent);

注意: 这里需要发送的是有序广播,否则在接收者中通过setResult()和getResult()方法会报错,因为只有有序广播才能传递结果。
(7)终结广播
不关有没有被拦截都执行的广播

sendOrderedBroadcast(intent, null, new OrderBroadcastReceiver.LowerOrder(),new Handler(), 0, null, null);

(8)本地广播
LocalBroadcastManager只发送给自己应用内部的广播,限制在进程内部使用。
(1)只需要把调用context的sendBroadcast,registerReceiver,unregisterReceiver的地方换为LocalBroadcastManager.getInstance(Context context)中对用的函数即可
(2)注册广播

MyBroadcastReceiver receiver = new MyBroadcastReceiver();
LocalBroadcastManager.getInstence(context).registerReceiver(receiver ,intentFilter);

(3)发送广播

LocalBroadcastManager.getInstence(content).sendBroadcast(intent);

(4)反注册广播

LocalBroadcastManager.getInstance(content).unregisterReceiver(receiver);

(5)同步广播

LocalBroadcastManager.getInstance(content).sendBroadcastSync(intent);

总结:
(1)四大组件的注册
四大基本组件都需要注册才能使用,每个Activity、service、Content Provider都需要在AndroidManifest文件中进行配置。AndroidManifest文件中未进行声明的activity、服务以及内容提供者将不为系统所见,从而也就不可用。而broadcast receiver广播接收者的注册分静态注册(在AndroidManifest文件中进行配置)和通过代码动态创建并以调用Context.registerReceiver()的方式注册至系统。需要注意的是在AndroidManifest文件中进行配置的广播接收者会随系统的启动而一直处于活跃状态,只要接收到感兴趣的广播就会触发(即使程序未运行)。
(2)四大组件的激活
内容提供者的激活:当接收到ContentResolver发出的请求后,内容提供者被激活。而其它三种组件activity、服务和广播接收器被一种叫做intent的异步消息所激活。
(3)四大组件的关闭
内容提供者仅在响应ContentResolver提出请求的时候激活。而一个广播接收器仅在响应广播信息的时候激活。所以,没有必要去显式的关闭这些组件。Activity关闭:可以通过调用它的finish()方法来关闭一个activity。服务关闭:对于通过startService()方法启动的服务要调用Context.stopService()方法关闭服务,使用bindService()方法启动的服务要调用Contex.unbindService()方法关闭服务。
(4)android中的任务(activity栈)
任务其实就是activity的栈,它由一个或多个Activity组成,共同完成一个完整的用户体验。栈底的是启动整个任务的Activity,栈顶的是当前运行的用户可以交互的Activity,当一个activity启动另外一个的时候,新的activity就被压入栈,并成为当前运行的activity。而前一个activity仍保持在栈之中。当用户按下BACK键的时候,当前activity出栈,而前一个恢复为当前运行的activity。栈中保存的其实是对象,栈中的Activity永远不会重排,只会压入或弹出。
任务中的所有activity是作为一个整体进行移动的。整个的任务(即activity栈)可以移到前台,或退至后台。
Android系统是一个多任务(Multi-Task)的操作系统,可以在用手机听音乐的同时,也执行其他多个程序。每多执行一个应用程序,就会多耗费一些系统内存,当同时执行的程序过多,或是关闭的程序没有正确释放掉内存,系统就会觉得越来越慢,甚至不稳定。为了解决这个问题,Android引入了一个新的机制,即生命周期(Life Cycle)。

猜你喜欢

转载自blog.csdn.net/weixin_33971205/article/details/87029122
今日推荐