知识梳理

个人知识点整理之常见面试题:

【】四大组件之————Activity

基本描述

简单来说就是一个可以点击、响应活动的界面、窗体。

Activity 是Context的子类,同时实现了window.callback 窗体回调,响应窗体相关的点击事件 和keyevent.callback(键盘事件回调,响应键盘事件), 可以处理与窗体用户交互的事件. 

源代码:

public class Activity extends ContextThemeWrapper

        implements LayoutInflater.Factory2,

        Window.Callback, KeyEvent.Callback,

        OnCreateContextMenuListener, ComponentCallbacks2 {

}

Activity生命周期:

生命周期指的是:一个类从创建(new出来)到死亡(垃圾回收)的过程中会执行的方法.在这个过程中 会针对不同的生命阶段会调用不同的方法

Activity从创建到销毁有多种状态,从一种状态到另一种状态时会激发相应的回调方法,这些回调方法包括:

onCreate创建onDestroy销毁;

onStart可见onStop不可见;onRestart再次可见;

onResume得到焦点onPause失去焦点

在Activity被onStop后,但是没有被onDestroy,在再次启动此Activity时就调用onRestart(而不再调用onCreate)方法;

结合项目来说:

比如说豆瓣客户端每次进入某个界面的时候都要看到最新的数据,这个刷新列表的操作 就放在onStart()的方法里面.这样保证每次用户看到的数据都是最新的;再比如在splash界面时检查是否连网也在onStart()方法里面。

在视频播放器中, 播放来电话. onStop() 视频, 视频声音设置为0 , 记录视频播放的位置 mediaplayer.pause();onStart() 根据保存的状态恢复现场. mediaplayer.start(); 

在读文档的时候 还发现 activity还有两个方法 onPostResume() 和 OnPostCreate()这两个生命周期的方法,不过开发的时候没有用到过.(能记住就说出来,充分展示自己)

activity界面切换(跳转)时必然执行的方法:

有两个activity,分别叫A,B ,当在A里面激活B组件的时候, A 会调用 onPause()方法,然后B 调用onCreate() ,onStart(), OnResume() ,

B覆盖了窗体, A会调用onStop()方法.  如果B呢 是个透明的,或者是对话框的样式, 就不会调用onStop()方法(不可点击但可见)

横竖屏切换(ctrl+F11)时候Activity的生命周期。

这个生命周期跟清单文件里的配置有关系

1、不设置Activity的android:configChanges时,切屏会重新调用各个生命周期

默认首先销毁当前activity,然后重新加载

Onpause onstop ondestory oncreate onstart onresume 

2、设置Activity的android:configChanges="orientation|keyboardHidden"时(在清单文件Manifest.xml里面配置),切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法

游戏开发中, 屏幕的朝向都是写死的. 

【】四大组件之————Service

简单地说是一个没有界面的activity(暂时这么理解,有些许不同会在后面提到) 。

Service运行在系统主线程中。四大组件都运行在主线程中为了避免anr异常,需要将耗时操作放在service的子线程中进行 new thread()

提问:为什么不在activity下面开一个子线程而要在service中开启呢?

回答:这就是第一句话说到的activity和service的细微区别。这里要提到进程的优先级了五个优先级:1.前台进程;2.可视进程;3.服务进程;4.后台进程;5.空进程;

在service中开启子线程是属于服务进程。(一般不会被回收)

在activity中开启子线程属于后台进程。 (可能会被回收)

所以为了不被意外回收,会在service中开启子线程。

【如果在service中的onCreate方法中设置setForeground(true);就将服务的优先级提高成了前台级别的(QQ为了不被系统回收就做了如此的操作)】

URL的格式: scheme: // host : port / path

//主机名:端口 / 路径

【】四大组件之————ContentProvider

内容提供者,简单地说,就是提供一个通用(统一)的API,让用户采用URI的方式对内容进行访问、操作。

类似于中介人的作用。

【】对四大组件的理解、认识:

(参考资料)

Android有四大组件:ActivityServiceBroadcast ReceiverContent Provider

Activity

做一个完整的Android程序,不想用到Activity,真的是比较困难的一件事情,除非是想做绿叶想疯了。因为ActivityAndroid程序与用户交互的窗口,在我看来,从这个层面的视角来看,AndroidActivity特像网站的页面。

Activity,在四大组件中,无疑是最复杂的,这年头,一样东西和界面挂上了勾,都简化不了,想一想,独立做一个应用有多少时间沦落在了界面上,就能琢磨清楚了。从视觉效果来看,一个Activity占据当前的窗口,响应所有窗口事件,具备有控件,菜单等界面元素。从内部逻辑来看,Activity需要为了保持各个界面状态,需要做很多持久化的事情,还需要妥善管理生命周期,和一些转跳逻辑。对于开发者而言,就需要派生一个Activity的子类,然后埋头苦干上述事情。对于Activity的更多细节,先可以参见:reference/android/app/Activity.html。后续,会献上更为详尽的剖析。

Service

服务,从最直白的视角来看,就是剥离了界面的Activity,它们在很多Android的概念方面比较接近,都是封装有一个完整的功能逻辑实现,只不过Service不抛头露脸,只是默默无声的做坚实的后盾。

但其实,换个角度来看,Android中的服务,和我们通常说的Windows服务,Web的后台服务又有一些相近,它们通常都是后台长时间运行,接受上层指令,完成相关事务的模块。用运行模式来看,Activity是跳,从一个跳到一个,呃...,这有点像模态对话框(或者还像web页面好了...),给一个输入(抑或没有...),然后不管不顾的让它运行,离开时返回输出(同抑或没有...)。

Service不是,它是等,等着上层连接上它,然后产生一段持久而缠绵的通信,这就像一个用了Ajax页面,看着没啥变化,偷偷摸摸的和Service不知眉来眼去多少回了。

但和一般的Service还是有所不同,AndroidService和所有四大组件一样,其进程模型都是可以配置的,调用方和发布方都可以有权利来选择是把这个组件运行在同一个进程下,还是不同的进程下。这句话,可以拿把指甲刀刻进脑海中去,它凸显了Android的运行特征。如果一个 Service,是有期望运行在于调用方不同进程的时候,就需要利用Android提供的RPC机制,为其部署一套进程间通信的策略。

AndroidRPC实现,如上图所示(好吧,也是从SDK中拿来主义的...),无甚稀奇,基于代理模式的一个实现,在调用端和服务端都去生成一个代理类,做一些序列化和反序列化的事情,使得调用端和服务器端都可以像调用一个本地接口一样使用RPC接口。

Android中用来做数据序列化的类是Parcel,参见:/reference/android/os/Parcel.html,封装了序列化的细节,向外提供了足够对象化的访问接口,Android号称实现非常高效。

还有就是AIDL (Android Interface Definition Language) ,一种接口定义的语言,服务的RPC接口,可以用AIDL来描述,这样,ADT就可以帮助你自动生成一整套的代理模式需要用到的类,都是想起来很乏力写起来很苦力的那种。更多内容,可以再看看:guide/developing/tools/aidl.html,如果有兴致,可以找些其他PRC实现的资料lou几眼。

关于Service的实现,还强推参看API Demos这个Sample里面的RemoteService实现。它完整的展示了实现一个Service需要做的事情:那就是定义好需要接受的Intent,提供同步或异步的接口,在上层绑定了它后,通过这些接口(很多时候都是RPC...)进行通信。在RPC接口中使用的数据、回调接口对象,如果不是标准的系统实现(系统可序列化的),则需要自定义aidl,所有一切,在这个Sample里都有表达,强荐。

Service从实现角度看,最特别的就是这些RPC的实现了,其他内容,都会接近于Activity的一些实现,也许不再会详述了。

Broadcast Receiver

在实际应用中,我们常需要等,等待系统抑或其他应用发出一道指令,为自己的应用擦亮明灯指明方向。而这种等待,在很多的平台上,都会需要付出不小的代价。

比如,在Symbian中,你要等待一个来电消息,显示归属地之类的,必须让自己的应用忍辱负重偷偷摸摸的开机启动,消隐图标隐藏任务项,潜伏在后台,监控着相关事件,等待转瞬即逝的出手机会。这是一件很发指的事情,不但白白耗费了系统资源,还留了个流氓软件的骂名,这真是卖力不讨好的正面典型。

Android中,充分考虑了广泛的这类需求,于是就有了Broadcast Receiver这样的一个组件。每个Broadcast Receiver都可以接收一种或若干种Intent作为触发事件(有不知道Intent的么,后面会知道了...),当发生这样事件的时候,系统会负责唤醒或传递消息到该Broadcast Receiver,任其处置。在此之前和这以后,Broadcast Receiver是否在运行都变得不重要了,及其绿色环保。

这个实现机制,显然是基于一种注册方式的,Broadcast Receiver将其特征描述并注册在系统中,根据注册时机,可以分为两类,被我冠名为冷热插拔。所谓冷插拔,就是Broadcast Receiver的相关信息写在配置文件中(求配置文件详情?稍安,后续奉上...),系统会负责在相关事件发生的时候及时通知到该Broadcast Receiver,这种模式适合于这样的场景。某事件方式 -> 通知Broadcast -> 启动相关处理应用。比如,监听来电、邮件、短信之类的,都隶属于这种模式。而热插拔,顾名思义,插拔这样的事情,都是由应用自己来处理的,通常是在 OnResume事件中通过registerReceiver进行注册,在OnPause等事件中反注册,通过这种方式使其能够在运行期间保持对相关事件的关注。比如,一款优秀的词典软件(比如,有道词典...),可能会有在运行期间关注网络状况变化的需求,使其可以在有廉价网络的时候优先使用网络查询词汇,在其他情况下,首先通过本地词库来查词,从而兼顾腰包和体验,一举两得一石二鸟一箭双雕(注,真实在有道词典中有这样的能力,但不是通过 Broadcast Receiver实现的,仅以为例...)。而这样的监听,只需要在其工作状态下保持就好,不运行的时候,管你是天大的网路变化,与我何干。其模式可以归结为:启动应用 -> 监听事件 -> 发生时进行处理。

除了接受消息的一方有多种模式,发送者也有很重要的选择权。通常,发送这有两类,一个就是系统本身,我们称之为系统Broadcast消息,在reference/android/content/Intent.html Standard Broadcast Actions,可以求到相关消息的详情。除了系统,自定义的应用可以放出Broadcast消息,通过的接口可以是 Context.sendBroadcast,抑或是Context.sendOrderedBroadcast。前者发出的称为Normal broadcast,所有关注该消息的Receiver,都有机会获得并进行处理;后者放出的称作Ordered broadcasts,顾名思义,接受者需要按资排辈,排在后面的只能吃前面吃剩下的,前面的心情不好私吞了,后面的只能喝西北风了。

Broadcast Receiver接收到相关的消息,它们通常做一些简单的处理,然后转化称为一条Notification,一次振铃,一次震动,抑或是启动一个 Activity进行进一步的交互和处理。所以,虽然Broadcast整个逻辑不复杂,却是足够有用和好用,它统一了Android的事件广播模型,让很多平台都相形见绌了。更多Broadcast Receiver相关内容,参见:/reference/android/content/BroadcastReceiver.html

Content Provider

Content Provider,听着就和数据相关,没错,这就是Android提供的第三方应用数据的访问方案。在Android中,对数据的保护是很严密的,除了放在SD卡中的数据,一个应用所持有的数据库、文件、等等内容,都是不允许其他直接访问的,但有时候,沟通是必要的,不仅对第三方很重要,对应用自己也很重要。

比如,一个联系人管理的应用。如果不允许第三方的应用对其联系人数据库进行增删该查,整个应用就失去了可扩展力,必将被其他应用抛弃,然后另立门户,自个玩自个的去了。

Andorid当然不会真的把每个应用都做成一座孤岛,它为所有应用都准备了一扇窗,这就是Content Provider。应用想对外提供的数据,可以通过派生ContentProvider类, 封装成一枚Content Provider,每个Content Provider都用一个uri作为独立的标识,形如:content://com.xxxxx。所有东西看着像REST的样子,但实际上,它比REST 更为灵活。和REST类似,uri也可以有两种类型,一种是带id的,另一种是列表的,但实现者不需要按照这个模式来做,给你iduri你也可以返回列表类型的数据,只要调用者明白,就无妨,不用苛求所谓的REST

另外,Content Provider不和REST一样只有uri可用,还可以接受ProjectionSelectionOrderBy等参数,这样,就可以像数据库那样进行投影,选择和排序。查询到的结果,以Cursor(参见:reference/android/database/Cursor.html )的形式进行返回,调用者可以移动Cursor来访问各列的数据。

Content Provider屏蔽了内部数据的存储细节,向外提供了上述统一的接口模型,这样的抽象层次,大大简化了上层应用的书写,也对数据的整合提供了更方便的途径。Content Provider内部,常用数据库来实现,Android提供了强大的Sqlite支持,但很多时候,你也可以封装文件或其他混合的数据。

Android中,ContentResolver是用来发起Content Provider的定位和访问的。不过它仅提供了同步访问的Content Provider的接口。但通常,Content Provider需要访问的可能是数据库等大数据源,效率上不足够快,会导致调用线程的拥塞。因此Android提供了一个AsyncQueryHandler(参见:reference/android/content/AsyncQueryHandler.html),帮助进行异步访问Content Provider

在各大组件中,ServiceContent Provider都是那种需要持续访问的。Service如果是一个耗时的场景,往往会提供异步访问的接口,而Content Provider不论效率如何,都提供的是约定的同步访问接口。我想这遵循的就是场景导向设计的原则,因为Content Provider仅是提供数据访问的,它不能确信具体的使用场景如何,会怎样使用它的数据;而相比之下,Service包含的逻辑更复杂更完整,可以抉择大部分时候使用某接口的场景,从而确定最贴切的接口是同步还是异步,简化了上层调用的逻辑。

【】Android下的数据储存方式:

1.文件的方式存储:SD卡 和 内存  

访问权限.   sdcard  

/data/data/包名/files 内存里面

2.以 数据库 方式存储数据 sqlite   

3.以SharedPreference 方式存储数据  

  <data>/<data>/包名/shared_preps   Context.modeprivate

4.以 网络 的方式

  socket tcp 面向连接 打电话   udp  平信  udp,  

http  httpurlconnection  

Android httpclient  post get 

ftp的网络  file transport protocol

5.也可以用 内容提供者 来完成数据的存储;可将其看做一个工具,一个接口API,通过接口可以用以上4种方式的任意一种进行存储。

【】Android中常用的五种布局

1.FrameLayout(帧布局) (叠加、覆盖显示)

2.LinearLayout (线性布局) 【常用】

3.AbsoluteLayout(绝对布局)

4.RelativeLayout(相对布局) 【常用 】

5.TableLayout(表格布局)

【】dippx的区别

px 就是像屏幕上的像素点 (自己起个好记的名字:绝对像素。类比绝对布局)

dip: device independent pixels(设备独立像素).  

dip是按照屏幕比例抽象出来的像素点(起个好记得名字:相对像素。类比相对布局)

dip和dp 基本是一个概念.

dp(与密度无关的像素):一种基于屏幕密度的抽象单位。在每英寸160点的显示器上,1dp = 1px


【】Activity , WindowView的关系

跟踪Activity的源码就会发现:Activity.attch() -> PolicyManager -> Policy -> PhoneWindow -> mLayoutInflater.inflate()&mContentParent.addView()

Activity 工匠 (控制单元)

Window     窗户 (承载模型),

View        窗花 (显示视图)

Xml配置    窗花图纸 (设计布局)

LayoutInflater  剪刀   (填充界面)

1)一个Activity构造的时候会初始化一个Window,准确的说是PhoneWindow

2)这个PhoneWindow有一个“ViewRoot”,引号是说其实这个“ViewRoot”是一个View或者说ViewGroup,是最初始的根视图。

3)ViewRoot”通过addView方法来一个个的添加View。比如TextViewButton

4)这些View的事件监听,是由WindowManagerService来接受消息,并且回调Activity函数。比如onClickListeneronKeyDown

2Activityandroid的显示视图么? 不是

3LayoutInflater是做什么的 ? layoutInflater.inflater()做什么的?

一般来讲,我们用LayoutInflater做一件事:inflateinflate这个方法总共有四种形式,目的都是把xml表述的layout转化为View

【】对android主线程的运用和理解

四大组件都是运行在主线程中的;主ui线程不能执行耗时的操作

主线程三大作用:1.维护生命周期相关回调函数;

2.更新UI;

3.响应系统事件。

其实系统桌面也是一个程序(launcher),点击桌面开启其他图标就是在一个应用中通过intent开启另外的应用,实现方式是一样的。所以制作着自定义桌面,只需在应用的清单文件中配置一段intent filter的代码即可,代码可在launcher源代码中找到。

【】android下的消息机制

1.在主线程中创建一个消息处理器handler

2.子线程利用handler发送一条信息到主线程里的消息队列MessageQueue (底层实现是链表的结构)

3.主线程里的looper发现有新消息到来,将其取出,调用handler的handlemessage

4.方法处理消息。【主线程(UI线程)其实就是一个不停刷新界面的activity,是个死循环,不停地从MessageQueue里面取数据,更新ui】

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值