史上最精炼android四大组件基础总结(忘记了的可以过一遍)

Android基础知识总结

四大组件之一活动

活动状态

  1. 运行状态:活动处于栈顶
  2. 暂停状态:活动不处于栈顶,但仍然可见
  3. 停止状态:完全不可见
  4. 销毁状态:离开返回栈

生存期

  1. onCreate()
  2. onStart():不可见到可见调用
  3. onResume():与用户进行交互,处于栈顶运行态
  4. onPause():准备启动或者恢复另一活动,
  5. onStop():完全不可见的时候调用
  6. onDestory():被销毁之前调用,之后变为销毁状态
  7. onRestart():这个方法由停止状态变为运行状态之前调用,也就是活动重新启动了

当Activity A到Activity B跳转时如果此时内存不够,回收了A,当我们按返回键时仍然会回到A,并且此时执行的不是A的onRestart()。而是onCreate().为了保存数据,我们可以回掉onSaveInstanceState()方法将数据放入bundle对象中,在onCreate()方法中有bundle参数进行获取

活动的启动模式

在配置文件Activity中配置launchMode属性

  1. standard 默认
    每次启动一个新活动,它就会在返回栈中入栈,并处于栈顶位置。如果我们在一个Activity中跳转自己。点击两次创建之后,我们需连按三次Back建才能退出程序。
  2. singleTop
    解决了默认情况下,在栈顶还要创建不合理。也就是如果Activity处于栈顶不创建,不处于栈顶就会重新创建。
  3. singleTask
    解决一个栈中有多个Activity实例,也就是如果发现已经存在栈中就把这活动之上的统统出栈,没有则创建
  4. singleInstance
    指定为该模式的活动会启动一个新的返回栈来管理这个活动。

四大组件之二广播

  • 标准广播:异步执行的广播
  • 有序广播:同步执行的广播(对于广播接收器是有先后顺序)

接收系统广播

动态注册监听网络变化

  • 在代码中注册为动态注册
  • 在AndroidManifest.xml文件中注册时静态注册
首先需要创建广播接收器

我们只需要新建一个类让它继承BroadcastReceiver,并重写父类的onReceive()(有广播来时,这个方法会得到执行)方法就行了。具体逻辑这个方法中处理,注意不能写耗时操作要不然anr异常,如果需要我们可以启动一个服务Service,不要使用新线程完成。因为广播接收器的生命周期很短。可能出现子线程还没有结束,广播解释器已经退出了。

  • 发送广播:
    • 创建一个IntentFilter 实例。并给他添加一个action如:android.net.com.CONNECTIVITY_CHANGE(网络发生变化的广播),
    • 创建一个NetworkChangeReceiver(自定义的广播接收器类)的实例。
    • 调用registerReceiver()方法进行注册。将两个实例传进去。
    • 最后记得动态注册广播接收器一定要取消注册才行。在onDestory()方法中调用unregisterReceiver()方法来实现。

静态注册(实例:实现开机启动)

动态注册广播很灵活但是存在缺点:必须要程序在启动之后才能接受到广播。因为注册逻辑是写在onCreate()方法中。所以有静态注册

  1. 首先我们自定义一个广播接收器:定义一个类BootCompleteReceiver继承BroadcastReceiver。重写onReceiver()方法。里面写个Toast()打印String。
  2. 在AndroidManifest.xml中将这个广播接收器类名进行注册。
  3. 新建一个<receiver>标签,通过android:name来指定注册哪一个广播接收器,然后在<intent-filter>标签加入想要接收的广播就行了。
  4. Android系统启动完成后发出一条值为:android.intent.action.BOOT_COMPLETED的广播。因此将这个添加到<intent-filter>的<action>
  5. 这里还需要一个权限:android.permission.RECEIVE_BOOT_COMPLETED权限。

发生自定义广播

发送标准广播

  • 发送广播之前先定义一个广播接收器,并且进行注册。action("com.zts.broadcast.MY_BROADCOAST");

  • 我们定义一个Button作为发送广播的触发点。

  • 在监听事件中调用

       Intent intent=new Intent("com.zts.broadcast.MY_BROADCOAST");
       sendBroadcast(intent);
    

由于广播是使用intent进行传递的,因此我们可以在intent中携带数据传递给广播接收器

发送有序广播

  • 发送有序广播我们只需要改动一行代码,即将sendBroadcast()方法改成sendOrderedBroadcast(intent,null)
  • 这个时候广播接收器就有先后顺序了,而且前面的广播接收器还可以将广播截断,阻止其继续传播。
  • 设置广播接收器的先后顺序
  • 在intent—filter标签中设置属性android:priority=100意思是优先级设成了100
  • 获得了广播的优先权,我们可以阻止继续传播,在onReceive方法中调用:abortBroadcast();

android.intent.action.TIME_SET:系统时间被修改。
android.intent.action.DATE_CHANGED:系统日期被修改。
android.intent.action.BOOT_COMPLETED:系统启动完成。
android.intent.action.BATTERY_CHANGED:设备电量改变。
android.intent.action.BATTERY_LOW:设备电量低。
android.intent.action.ACTION_POWER_CONNECTED:设备连接电源。
android.intent.action.ACTION_POWER_DISCONNECTED:设备断开电源。

android.provider.Telephony.SMS_RECEIVED:系统收到短信。
android.intent.action.NEW_OUTGOING_CALL:拨打电话。
android.intent.action.SCREEN_OFF当屏幕锁屏的时候触发
android.intent.action.SCREEN_ON屏幕解锁的时候触发
android.intent.action.USER_PRESENT当用户重新唤醒手持设备时触发
ACTION_TIME_CHANGED:系统时间被改变
ACTION_TIMEZONE_CHANGED:系统时区被改变
ACTION_BOOT_COMPLETED:系统启动完成
ACTION_PACKAGE_ADDED:系统添加包
ACTION_PACKAGE_CHANGED:系统的包改变
ACTION_PACKAGE_REMOVED:此外的包被删除
ACTION_PACKAGE_RESTARTED:系统的包被重启
ACTION_PACKAGE_DATA_CLEARED:系统的包数据被清空
ACTION_SHUTDOWN:系统被关闭

使用本地广播

为了简单解决广播安全性问题(自己广播被拦截,或垃圾广播)。LocalBroadcaseManager()

  • 我只需要先获得这个管理类

    LocalBroadcastManager localBroadcastManager=LocalBroadcastManager.getInstance(this);

  • 发生广播时用这个对象发送即可localBroadcastManager.sendBroadcast(intent);

  • 注册和取消注册同样也是用这个对象去调用相应的方法

本地广播是无法通过静态注册方式去接收的。他的优势:

  1. 广播在我们程序内部,不必担心机密数据泄露
  2. 其他的程序无法将广播发送到我们内部
  3. 发生本地广播比起发送系统全局广播将会更加高效

四大组件之三服务

服务的基本用法

定义一个服务

  • 新建一个MyService的类,并让他继承Service此时要重写onBind()方法,我们可以重写如下方法:

  • onCreate():在服务创建的时候调用

  • onStartCommand()方法会在每次服务启动的时候调用

  • onDestory()方法会在服务销毁的时候调用(回收不再使用的资源)

  • 需要在AndroidManifest.xml文件中注册才能生效

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

启动和停止服务

主要也是借助Intent来实现的

  • 启动服务

      startService(new Intent(this,MyService.class))
    
  • 停止服务

      stopService(new Intent(this,MyService.class))
    
  • 如果我们想要让服务自己停止下来,只需要在MyService的任何一个位置调用stopSelf()方法就能让这个服务停止下来

服务和活动之间通信

为了让服务和活动更加紧密一点。

  • 首先在Activity中创建一个ServiceConnection的匿名类,在里面重写了OnServiceConnected()方法和onServiceDisconnected()方法。

  • 绑定服务我们调用的是(BIND_AUTO_CREATE表示活动和服务进行绑定后自动创建服务)

      bindService(intent,connection,BIND_AUTO_CREATE);
    
  • 解除绑定

      unbindService(connection)
    

这个时候要用到的是onBind()方法。这里返回的对象会在onServiceDisconnected()这个第二参数中

服务的生命周期

  • onCreate() 服务之前没有创建过就会先执行
  • onStartCommand()方法执行每次调用startService()就会执行。但是还是只存在一个实例
  • onBind():在Context的bindService()调用时就会执行该方法
  • onDestory(): 调用startService后再调用stopService()时就会执行,调用bindService 后又调用unbindService()也会执行

当调用了startService()又调用bindService()此时只有当两个同时调用stopService和unbindService().onDestory()才会执行。

使用前台服务

前台服务和普通服务最大的区别在于,它会一直有一个正在运行的图标在系统状态栏显示,下拉状态栏后可以看到更加详细的信息,非常类似于通知的效果。比如:墨迹天气,它的服务后台更新天气数据的同时,还会在系统状态栏一直显示当前的天气信息

IntentService

Android中的Service是用于后台服务的,当应用程序被挂到后台的时候,
为了保证应用某些组件仍然可以工作而引入了Service这个概念,
那么这里面要强调的是Service不是独立的进程,也不是独立的线程,
它是依赖于应用程序的主线程的,也就是说,在更多时候
不建议在Service中编写耗时的逻辑和操作,否则会引起ANR(Application Not Responding)。
那么我们当我们编写的耗时逻辑,不得不被service来管理的时候,
在Service启动一个新子线程,在子线程完成耗时操作。
就需要引入IntentService

  • IntentService是继承Service的,那么它包含了Service的全部特性,当然也包含service的生命周期,
  • 那么与service不同的是,IntentService在执行onCreate操作的时候,内部开了一个线程
  • 去你执行你的耗时操作。该线程保证同一时刻只处理一个Intent.这样IntentService不会阻塞主线程。
  • IntentService的使用和Service是类似。它需要重写
    onHandleIntent(Intent intent)方法。

内容提供器Content Provider

内容提供器简介

当系统部署多个Android应用之后,有时候就需要在不同的应用之间共享数据,比如现在有一个短信接收应用,用户想把接收到的陌生短信的发信人添加到联系人管理应用中,就需要不同应用之间共享数据。对于这种需要在不同应用之间共享数据的需求,可以让一个应用程序直接去操作另外一个应用程序所记录的数据
1 比如操作它所记录的SharedPreferences,文件
或数据库等。这种方式显得太杂乱了。
2 不同
应用程序记录数据的方式差别很大,这种方式
不利于应用程序之间进行数据交换。

为了在应用程序之间交换数据,Android提供
了ContentProvider,ContentProvider是不同应用程序之间进行数据交换的标准API,
当一个应用程序需要把自己的数据暴露给其他程序使用时,
该应用程序就可通过提供ContentProvider来实现,其他应用程序可通过ContentResolver
来操作ContentProvider暴露的数据

  • 包括增加数据

  • 删除数据

  • 修改数据

  • 查询数据等。

    ContentProvider也是Android应用的四大组件之一,需要在AndroidManifest.xml文件中进行配置.
    Android已经为常见的一些数据提供了默认的ContentProvider.
    比如说短信,电话,多媒体等

  • 开发ContentProvider

  • :定义自己的ContentProvider类,该类继承ContentProvider基类

  • :暴露ContentProvider提供的数据
    * 重写onCreate():该方法在ContentProvider创建后被调用

    • 重写getType():该方法用于返回当前Uri所代表的数据的MIME类型,
      如果该Uri对应的数据可能包括多条记录,那么MIME类型
      字符串应用以vnd.android.cursor.dir/开始
      如果该Uri对应的数据只包括一条记录,那么MIME类型
      字符串应用以vnd.android.cursor.item/开始
    • 重写insert(Uri,ContentValue values):根据Uri插入values对应的数据
    • 重写delete(Uri,String selection,String[] selectArgs):根据Uri删除select条件匹配的全部记录
    • 重写update():根据Uri修改select条件所匹配的全部记录
    • 重写query():根据Uri查询出select条件所匹配的全部记录

    注意:重写的这些方法并不是给该应用本身调用的,
    而是供其他应用来调用。

  • 第三步:在AndroidManifest.xml文件中注册该ContentProvider,
    指定android:authorities属性
    <provider android:name=""
    authorities=""
    android:exported/>

  • .Uri:用于表示这个ContentProvider所提供的数据

      Uri:统一资源标识符
      --URL:统一资源定位符
      --URN:统一资源命名符
      如:http://www.baidu.com/index.html
      http:// 是URL的协议部分,是固定的
      www.baidu.com是域名部分,是固定的
      index.html是网站资源部分,是动态的
    

而ContentProvider提供的Uri,例如:

如:content://com.briup.dictprovider/users

content://是Uri的协议部分,暴露ContentProvider,访问
contentProvider的协议默认是content://,这个部分是固定的。
com.briup.dictprovider:是ContentProvider的authority。
      系统就是由这个部分找到操作哪个ContentProvider.
  只要访问指定的ContentProvider,这个部分总是固定的。
users:是资源部分,当访问者需要访问不同资源时,
     这个部分是动态改变的。

Uri提供了parse()静态方法,可以将字符串转换为Uri:
Uri uri = Uri.parse("content://com.briup.dictprovider/user/2");

  • .ContentResolver
    通过ContentResolver来操作ContentProvider所暴露的数据
    使用步骤:
    第一步通过Context中获取ContentResolver对象:getContentResolver()
    第二步调用ContentResolver中相应的方法:
    insert,delete,update,query

原理:

A应用:提供数据    ContentProvider
            ^
            |
            |
            Uri
            ^
            |
            |    

B应用: 获取数据ContentResolver
当B应用调用ContentResolver的insert方法时
实际上相当于调用了该Uri对应的ContentProvider(属于A应用)的insert方法
当B应用调用ContentResolver的update方法时,实际上相当于调用了
该Uri对应的ContentProvider(属于A应用)的update方法。

在A应用编写ContentProvider,
  • 重写onCreate(),getType(),insert(),delete(),update(),query()
  • 在Manifest中配置<provider />标签
    android:name    provider的全类名
     android:authorities    为该Provider设置访问URI的Host部分
     android:exported    设置该Provider可以被其他应用程序访问
在B应用
  • 调用getContentResolver,获取resolver对象
  • 调用insert(),delete(),update(),query(),传入URI实现数据访问
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容