Some points 1. - Four Components

Activity

  • 生命周期

  • onResume():在 Activity 即将开始与用户进行交互之前调用。 此时,Activity 处于 Activity 堆栈的顶层,并具有用户输入焦点。
    onPause():此方法通常用于确认对持久性数据的未保存更改、停止动画以及其他可能消耗 CPU 的内容(例如camera、GPS),它应该非常迅速地执行所需操作。因为它返回后,下一个 Activity 才能继续执行。当按powerOff 锁屏时只回调此方法,而不掉onStop(),自然进入休眠会顺序调用这俩。
    onStop():释放所有用户不再使用的资源。也是一个释放可能造成内存泄露资源的最佳时机,因为当系统直接杀死进程来结束程序时最后一步调用的是此方法而不会走到onDestroy()。也是执行CPU密集型关闭操作的好时机,例如将信息存入数据库。当activity进入此状态时,是仍在内存中的,但不再依附window manager了,也可能因为内存不足而进程被kill掉,这时可以通过存入信息至Bundle来恢复【一个疑问:系统如何判断当前Activity在之前被存过Bundle,而再次重启进程时需要记住那个Activity?这个记忆的时间是多少?】
    onDestroy():当调用了finish()方法或进程被kill用以节省内存时调用,可以通过isFinishing()来区分这两种情况。当屏幕方向发生变化时,也回调此方法然后立刻再回调onCreate()

  • 在onCreate()方法中可以通过参数Bundle来恢复数据,也可以选择onRestoreInstanceState()来实现,这个方法会在onStart()后被调用(仅当存储过Bundle时才会被系统调用,因此不需要判断是否为null),需要为恢复数据的view设置id来让系统自动恢复数据。执行时机是在onStart()onPostCreate()之间。当用户按下返回键从B回到A时,不会调用B的onRestoreInstanceState()方法,因为B永远不会被恢复,因此系统也就不会调用它。

  • 跳转,例Aactivity ->Bactivity:
  1. Aactivity.onPause()
  2. Bactivity.onCreate() -> Bactivity.onStart() -> Bactivity.onResume()
  3. Aactivity.onStop()

next

Service

  • 有两种形式:
    (1) 启动:Context.startService(),一旦启动服务可在后台无限期运行,即使启动服务的组件被销毁也不受影响。例:网络下载、上传文件。
    (2) 绑定:Context.bindService(),绑定服务提供了一个客户端-服务器接口,允许组件与服务进行交互、发送请求、获取结果,甚至是利用进程间通信(IPC)跨进程执行这些操作。多个组件可以同时绑定该服务,但全部取消绑定后,该服务即被销毁。
  • 服务在其托管进程的主线程中运行,它既不创建自己的线程,也不在单独的进程中运行(除非另行指定)。 这意味着,如果服务将执行任何 CPU 密集型工作或阻止性操作(例如 MP3 播放或联网),则应在服务内创建新线程来完成这项工作。通过使用单独的线程,可以降低发生“应用无响应”(ANR) 错误的风险,而应用的主线程仍可继续专注于运行用户与 Activity 之间的交互。
  • 服务与线程的区别?与AsyncTask区别?
    Service is like an activity without UI,service默认在其托管进程的主线程运行,它既不创建自己的线程,也不在单独的进程中运行,在其内部可以创建线程。service有着自己的生命周期,不依赖于组件。而线程,应用启动时,系统会为应用创建一个名为“主线程”的执行线程,负责将事件分发给相应的用户界面小部件,为了不阻塞主线程发生ANR,可以创建工作线程,子线程的声明周期是要依托于创建它的组件的且不能与UI交互,如果在activity.onDestroy()中停止线程,activity将失去对它的控制。AsyncTask简化了异步任务的操作,override它的内部方法可以实现后台操作&UI控制,无需再创建thread&handler。

ContentProvider

  • 读取系统APP,信息,联系人, 多媒体信息等,也可以通过URI向外界程序暴露自己的数据,可以有增-删-改-查的overrider方法。
  • 自定义ContentProvider的步骤

Broadcast

  • 类似于订阅-发布的设计模式,应用能发送或接受来自于系统或其他应用的广播。
  • 注册广播的两种方式:
    1.应用级别的注册广播,此方式在app安装时就注册了,这个receiver成为了一个连接该app的单独入口点,即使当前程序并没有运行系统也可以启动程序传递广播。方式如下:
    (1) 在manifest中声明receiver结点
<receiver android:name=".MyBroadcastReceiver"  android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
        <action android:name="android.intent.action.INPUT_METHOD_CHANGED" />
    </intent-filter>
</receiver>

(2) extends BroadcastReceiver,实现onReceive(Context context, Intent intent)方法

2.通过上下文 context 注册广播,步骤如下:
(1) 声明

 BroadcastReceiver br = new MyBroadcastReceiver();

(2) 创建intent-filter并且注册receiver

IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
intentFilter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
this.registerReceiver(br, filter);

(3) 不再使用时,需要调用** unregisterReceiver(br)解除注册
值得注意的是接收者能否接收广播取决于发布者context是否存活,如果是
activity.reregisterReceiver,那么当activity执行了onDestroy()**
之后接收者就收不到广播了。如果使用 Application context来注册,那么在程序运行阶段都可以收到。

  • broadcast 对进程状态的影响
    执行着onReceive()的进程具有较高优先级被认为是前台进程,不会被系统kill,当从该方法返回时,广播将失活,其宿主进程不再被认定为具有高优先级,随时可能被kill用以释放内存。因此不能在onReceive()中执行耗时操作(系统只允许10s),即使另开线程用以执行耗时操作也不可以,因为宿主进程一旦被kill,在其内部生产的线程也会被kill。要想让广播组件在onReceive()返回后仍能进行长时间操作,有2种方案:(1)在onReceive()方法内调用PendingResult pendingResult = goAsync();,在子线程完成操作后必须再调用pendingResult.finish(),这个pendingResult里有着失活的broadcastReceiver的intent数据。官方文档有示例代码。(2)使用JobScheduler调度JobService
    JobService的五个约束条件如下:a.最小延时 b.最晚执行时间 c.需要充电 d.需要设备为idle(空闲)状态 e.联网状态(NETWORK_TYPE_NONE--不需要网络,NETWORK_TYPE_ANY--任何可用网络,NETWORK_TYPE_UNMETERED--不按用量计费的网络)。如果后台任务满足以上的一个或多个条件,就可以考虑是不是应该用JobService来执行。

  • 发送广播,有3种方式:
    1.sendOrderedBroadcast(Intent, String),有序广播,为不同 broadcastReceiver 定义优先级顺序,receiver间可以传递数据,也可以阻拦优先级低的receiver接收广播。
    2.sendBroadcast(Intent),普通广播
    3.LocalBroadcastManager.sendBroadcast(Intent),本地广播,在应用所在的进程内发送,有以下优点:a.发送的广播数据只在当前应用的进程中,无需担心泄露私密数据 b.其他应用不可能将此类广播发送至当前的应用,无需担心有可被利用的安全漏洞 c.相对于全局广播,本地广播更高效(无需进程间通信)

  • 使用permisson限制广播的发送和接收,发送时指定permission,只有声明了permission的receiver(通过context注册或是在manifest的receiver结点)并且application也声明了同样的permission的应用才能收到广播。

  • 关于使用的几点安全性建议:

    • 如果不需要发送广播到当前app以外的组件,尽量使用本地广播LocalBroadcastManager.sendBroadcast(Intent)
    • 如果很多app通过manifest注册了相同的broadcastReceiver,当触发时可能会启动多个app,这对用户体验不好,因此尽量使用通过context注册广播的方式而取代manifest,android系统对此也做了一些限制,比如检测网络连接的广播 CONNECTIVITY_ACTION 就只能通过context注册。
    • 发送广播的安全性做法:发送时指定permission、4.0以上可以指定package、使用本地广播
    • 接收广播的安全性做法: 注册时可指定permission、在receiver结点声明android:exported= false,可不接收外部广播、使用本地广播
    • 广播的 actions 是系统全局的,因此需要使用包命名的action
    • onReceive()最多10s内执行完成,不要做耗时操作
    • 不要在onReceive()中打开其他activity,尤其有多个receiver,可以考虑使用Notification。

Intent

  • 基本用图:启动Activity、启动服务、传递广播
  • Intent类型:
    1.显示Intent(Explicit intents):指定完全限定类名的接收组件,比如启动activity,启动服务下载文件。
    2.隐式 Intent(Implicit intents):声明要执行的 action,接收的组件通过声明 intent-filter 来匹配,比如通过打开其他地图类app来显示位置。
    出于安全性考虑,启动服务要通过显示intent,因为你不知道什么服务会响应该意图并且用户也不知道什么服务被启动了。在 API 5.0+时,当使用隐式intent启动服务时,当调用bindService()时系统会抛出 SecurityException。
  • PendingIntent 的使用场景:当Intent用于 执行Notification的操作、执行App Widget的操作、在指定的未来某一时间执行操作(AlarmManager)。
  • 就像 Intent 被设计的要由特定组件接收那样,PendingIntent 也需要指明处理它的组件类型,因此它的实例化有以下3种入口:PendingIntent.getActivity()PendingIntent.getService()PendingIntent.getBroadcast()
  • Intent 与 PendingIntent 的区别?
    1.Intent立即执行,PendingIntent 可以等到事件发生后触发,还可以取消
    2.Intent 需要在某个 context 内使用,而 PendingIntent 自带 context,当程序终止时 Intent 失效,而PendingIntent 依然有效
    3.Intent 在原 task 中运行,PendingIntent 在新的 task 中运行
  • Intent matching:intent 与 intent filters 匹配,意义不只是找出目标组件来处理,还能找出整个系统中匹配 intent filters的组件集合。例如Home app 就是通过找出匹配了action为ACTION_MAIN和 category为CATEGORY_LAUNCHER 的activities,利用 PackageManager 的一系列query...()方法也能实现主界面程序的功能,利用queryIntentActivitiesqueryIntentServices等方法来查看系统中有哪些应用和服务,在 PackageManager 中与之对应的一系列resolve...()方法就是列出匹配了意图的组件们,列表中的第一个就是最佳匹配的要被激活的。
如何创建一个开机自启动的service和应用?:

1.手机在启动的过程中会触发一个Standard Broadcast Action,名字叫android.intent.action.BOOT_COMPLETED,通过构建一个广播接收者来接收这个这个action

 public class BootBroadcastReceiver extends BroadcastReceiver {  
        //重写onReceive方法  
        @Override  
        public void onReceive(Context context, Intent intent) {  
            Intent service = new Intent(context,XXService.class);  
            context.startService(service);  
            //启动应用,参数为需要自动启动的应用的包名
            Intent intent = getPackageManager().getLaunchIntentForPackage(packageName);
            context.startActivity(intent);        
        } 
} 

2.在manifest中为这个BroadcastReceiver添加intent-filter

<receiver android:name="BootBroadcastReceiver">  
    <intent-filter>  
       <action android:name="android.intent.action.BOOT_COMPLETED"></action>  
       <category android:name="android.intent.category.LAUNCHER" />  
    </intent-filter>  
</receiver>

3.在manifest中添加权限:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />  
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容