Android面试题

来源:互联网 发布:yii2 cms管理系统 编辑:程序博客网 时间:2024/05/17 10:55

**********嵌入式系统 

***嵌入式操作系统内存管理有哪几种, 各有何特性

  页式,段式,段页,用到了MMU,虚拟空间等技术

 

***什么是嵌入式实时操作系统, Android 操作系统属于实时操作系统吗?

实时操作系统是指当外界事件或数据产生时,能够接受并以足够快的速度予以处理,其处理的结果又能在规定的时间之内来控制生产过程或对处理系统作出快速响应,并控制所有实时任务协调一致运行的嵌入式操作系统。主要用于工业控制、军事设备、航空航天等领域对系统的响应时间有苛刻的要求,这就需要使用实时系统。又可分为软实时和硬实时两种,而android是基于linux内核的,因此属于软实时。 

硬实时. 火星探测车. 

软实时.

 

***写10个简单的linux命令

cat ls ps psw wc mv rm cd ping tracert find grep tail vi gcc make ifconfig

startup dhcp

 

***udp连接和TCP的不同之处

 tcp/滑动窗口协议. 拥塞控制. 

  udp 不关心数据是否达到,是否阻

画面优先. tcp  

流畅优先  udp



***********Android系统

***Android系统中GC什么情况下会出现内存泄露呢?

出现情况:

1. 数据库的cursor没有关闭

2.构造adapter时,没有使用缓存contentview

   衍生listview的优化问题-----减少创建view的对象,充分使用contentview,可以使用一静态类来优化处理getview的过程

3.Bitmap对象不使用时采用recycle()释放内存

4.activity中的对象的生命周期大于activity

调试方法: DDMS==> HEAPSZIE==>dataobject==>[Total Size]

 

***设计模式和IoC(控制反转)

 

Android 框架魅力的源泉在于IoC,在开发Android 的过程中你会时刻感受到IoC 带来

 

的巨大方便,就拿Activity 来说,下面的函数是框架调用自动调用的:

 

protected void onCreate(Bundle savedInstanceState) ;

 

不是程序编写者主动去调用,反而是用户写的代码被框架调用,这也就反转

 

了!当然IoC 本身的内涵远远不止这些,但是从这个例子中也可以窥视出IoC

 

带来的巨大好处。此类的例子在Android 随处可见,例如说数据库的管理类,

 

例如说Android 中SAX 的Handler 的调用等。有时候,您甚至需要自己编写简

 

单的IoC 实现,上面展示的多线程现在就是一个说明。

 

***Android中的长度单位详解

 

现在这里介绍一下dp 和sp。dp 也就是dip。这个和sp 基本类似。如果设置表示长度、高度等属性时可以使用dp 或sp。但如果设置字体,需要使用sp。dp 是与密度无关,sp 除了与密度无关外,还与scale 无关。如果屏幕密度为160,这时dp 和sp 和px 是一样的。1dp=1sp=1px,但如果使用px 作单位,如果屏幕大小不变(假设还是3.2 寸),而屏幕密度变成了320。那么原来TextView 的宽度设成160px,在密度为320 的3.2 寸屏幕里看要比在密度为160 的3.2 寸屏幕上看短了一半。但如果设置成160dp 或160sp 的话。系统会自动将width 属性值设置成320px 的。也就是160 * 320 / 160。其中320 / 160 可称为密

 

度比例因子。也就是说,如果使用dp 和sp,系统会根据屏幕密度的变化自动

 

进行转换。

 

下面看一下其他单位的含义

 

px:表示屏幕实际的象素。例如,320*480 的屏幕在横向有320个象素,

 

在纵向有480 个象素。

 

in:表示英寸,是屏幕的物理尺寸。每英寸等于2.54 厘米。例如,形容

 

手机屏幕大小,经常说,3.2(英)寸、3.5(英)寸、4(英)寸就是指这个

 

单位。这些尺寸是屏幕的对角线长度。如果手机的屏幕是3.2 英寸,表示手机

 

的屏幕(可视区域)对角线长度是3.2*2.54 = 8.128 厘米。读者可以去量

 

一量自己的手机屏幕,看和实际的尺寸是否一致。    

 

***系统上安装了多种浏览器,能否指定某浏览器访问指定页面?

             请说明原由。通过直接发送Uri把参数带过去,或者通过manifest里的intentfilter里的data属性

 

***如何加载的音乐信息,如何改善其效率。

Android提供mediascanner,mediaStore等接口, 音乐文件的信息都会存放到系统的数据库表中,可以通过content provider获取,

显示出来,改善效率,是个常见问题, 可以从以下几个方面作答,

分批加载数据, 延时加载数据, 合理使用缓存等...

Java虚拟机, 目标, 加快java程序执行速度

预先加载一些 都会的使用的大的class的字节码, 提前加载.

时间换时间

空间换时间 

 

***启动应用后,改变系统语言,应用的语言会改变么?

  会

 

***Android中Task任务栈的分配。

假如有三个Activity A B C,A跳到B,然后B跳到C,现在需要从C跳到A如何传递数据而且使效率最高呢?

首先我们来看下Task的定义,Google是这样定义Task的:a task is what the user experiences as an "application." It's a group of related activities, arranged in a stack. A task is a stack of activities, not a class or an element in the manifest file. 这意思就是说Task实际上是一个Activity栈,通常用户感受的一个Application就是一个Task。从这个定义来看,Task跟Service或者其他Components是没有任何联系的,它只是针对Activity而言的。

Activity有不同的启动模式, 可以影响到task的分配

Task,简单的说,就是一组以栈的模式聚集在一起的Activity组件集合。它们有潜在的前后驱关联,新加入的Activity组件,位于栈顶,并仅有在栈顶的Activity,才会有机会与用户进行交互。而当栈顶的Activity完成使命退出的时候,Task会将其退栈,并让下一个将跑到栈顶的Activity来于用户面对面,直至栈中再无更多Activity,Task结束。

事件 Task栈(粗体为栈顶组件)

点开Email应用,进入收件箱(Activity A) A

选中一封邮件,点击查看详情(Activity B) AB

点击回复,开始写新邮件(Activity C) ABC

写了几行字,点击选择联系人,进入选择联系人界面(Activity D) ABCD

选择好了联系人,继续写邮件 ABC

写好邮件,发送完成,回到原始邮件 AB

点击返回,回到收件箱 A

退出Email程序 null

如上表所示,是一个实例。从用户从进入邮箱开始,到回复完成,退出应用整个过程的Task栈变化。这是一个标准的栈模式,对于大部分的状况,这样的Task模型,足以应付,但是,涉及到实际的性能、开销等问题,就会变得残酷许多。

比如,启动一个浏览器,在Android中是一个比较沉重的过程,它需要做很多初始化的工作,并且会有不小的内存开销。但与此同时,用浏览器打开一些内容,又是一般应用都会有的一个需求。设想一下,如果同时有十个运行着的应用(就会对应着是多个Task),都需要启动浏览器,这将是一个多么残酷的场面,十个Task栈都堆积着很雷同的浏览器Activity,

是多么华丽的一种浪费啊。

于是你会有这样一种设想,浏览器Activity,可不可以作为一个单独的Task而存在,不管是来自那个Task的请求,浏览器的Task,都不会归并过去。这样,虽然浏览器Activity本身需要维系的状态更多了,但整体的开销将大大的减少,这种舍小家为大家的行为,还是很值得歌颂的

standard", "singleTop", "singleTask", "singleInstance"。

standard模式, 是默认的也是标准的Task模式,在没有其他因素的影响下,使用此模式的Activity,会构造一个Activity的实例,加入到调用者的Task栈中去,对于使用频度一般开销一般什么都一般的Activity而言,standard模式无疑是最合适的,因为它逻辑简单条理清晰,所以是默认的选择。

而singleTop模式,基本上于standard一致,仅在请求的Activity正好位于栈顶时,有所区别。此时,配置成singleTop的Activity,不再会构造新的实例加入到Task栈中,而是将新来的Intent发送到栈顶Activity中,栈顶的Activity可以通过重载onNewIntent来处理新的Intent(当然,也可以无视...)。这个模式,降低了位于栈顶时的一些重复开销,更避免了一些奇异的行为(想象一下,如果在栈顶连续几个都是同样的Activity,再一级级退出的时候,这是怎么样的用户体验...),很适合一些会有更新的列表Activity展示。一个活生生的实例是,在Android默认提供的应用中,浏览器(Browser)的书签Activity(BrowserBookmarkPage),就用的是singleTop。

singleTask,和singleInstance,则都采取的另辟Task的蹊径。

标志为singleTask的Activity,最多仅有一个实例存在,并且,位于以它为根的Task中。所有对该Activity的请求,都会跳到该Activity的Task中展开进行。singleTask,很象概念中的单件模式,所有的修改都是基于一个实例,这通常用在构造成本很大,但切换成本较小的Activity中。最典型的例子,还是浏览器应用的主Activity(名为Browser...),它是展示当前tab,当前页面内容的窗口。它的构造成本大,但页面的切换还是较快的,于singleTask相配,还是挺天作之合的。

singleInstance显得更为极端一些。在大部分时候singleInstance与singleTask完全一致,唯一的不同在于,singleInstance的Activity,是它所在栈中仅有的一个Activity,如果涉及到的其他Activity,都移交到其他Task中进行。这使得singleInstance的Activity,像一座孤岛,彻底的黑盒,它不关注请求来自何方,也不计较后续由谁执行。在Android默认的各个应用中,很少有这样的Activity,在我个人的工程实践中,曾尝试在有道词典的快速取词Activity中采用过,

是因为我觉得快速取词入口足够方便(从notification中点选进入),并且会在各个场合使用,应该做得完全独立。

大的apk 拆成 很多小的apk  

  ●Activity的 android:taskAffinity=""属性 姻缘关系 

1.配置后 当启动这个activity时就先去找有没有activity的亲和力属性相同 有就加入这个

 activity所在的任务中没有就新开任务

2.affinity起作用需要的条件而者具备一个:

  1.intent包含FLAG_ACTIVITY_NEW_TASK标记

  2.activity元素启用了allowTaskReparenting属性.

 

***在Android中,怎么节省内存的使用,怎么主动回收内存?

  

  回收已经使用的资源,  

  合理的使用缓存 

合理设置变量的作用范围…  application 对象 

//未来的某一段时间执行  

System.gc();

 

***sim卡的EF 文件有何作用

sim卡的文件系统有自己规范,主要是为了和手机通讯,sim本身可以有自己的操作系统,EF就是作存储并和手机通讯用的。

  

***如何判断是否有SD卡?

  配置文件中有sd卡的权限, 通过environment的静态方法,

if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {

 

***一条最长的短信息约占多少byte? 

中文70(包括标点),英文160,160个字节 这个说法不准确,

要跟手机制式运营商等信息有关.

做实验,看源码

ArrayList<String> msgs = sms.divideMessage(message); 

         for (String msg : msgs) {  

            sms.sendTextMessage(phoneNumber, null, msg, pi, null);       

}

 

***Android系统中GC什么情况下会出现内存泄露呢?  视频编解码/内存泄露

检测内存泄露   工具  

导致内存泄漏主要的原因是,先前申请了内存空间而忘记了释放。如果程序中存在对无用对象的引用,那么这些对象就会驻留内存,消耗内存,因为无法让垃圾回收器GC验证这些对象是否不再需要。如果存在对象的引用,这个对象就被定义为"有效的活动",同时不会被释放。要确定对象所占内存将被回收,我们就要务必确认该对象不再会被使用。典型的做法就是把对象数据成员设为null或者从集合中移除该对象。但当局部变量不需要时,不需明显的设为null,因为一个方法执行完毕时,这些引用会自动被清理。

Java带垃圾回收的机制,为什么还会内存泄露呢?

Vector v = new Vector(10);     

 for (int i = 1; i < 100; i++)      {      

 Object o = new Object();       

v.add(o);       

o = null;      

}//此时,所有的Object对象都没有被释放,因为变量v引用这些对象。 

Java 内存泄露的根本原因就是 保存了不可能再被访问的变量类型的引用

 

***通过点击一个网页上的url 就可以完成程序的自动安装,描述下原理

  Day11 AddJavascriptInterface

new Object{

 callphone();

 installapk();

}

 

***系统上安装了多种浏览器,能否指定某浏览器访问指定页面?请说明原由:

 

答:通过直接发送Uri把参数带过去,或者通过manifest里的intentfilter里的data属性。代码如下:

    Intent intent = new Intent();

 

Intent.setAction(“android.intent.action.View”);

 

Uri uriBrowsers = Uri.parse(“http://www.sina.com.cn”);

 

Intent.setData(uriBrowsers);

 

//包名、要打开的activity

    intent.setClassName(“com.android.browser”,”com.android.browser.BrowserActivity”);

 

startActivity(intent);

 

***android开发中怎么去调试bug

逻辑错误 

1.断点 debug  

2. logcat , 

界面布局,显示 hierarchyviewer.bat 。



*********JNI

*** 在android中,请简述jni的调用过程。

 

    1)安装和下载Cygwin,下载 Android NDK

  2)在ndk项目中JNI接口的设计

  3)使用C/C++实现本地方法

  4)JNI生成动态链接库.so文件

  5)将动态链接库复制到java工程,在java工程中调用,运行java工程即可

 

  69. java中如何引用本地语言 

              可以用JNI(java nativeinterface java 本地接口)接口。

 

***JNI调用常用的两个参数

 JNIEnv *env, jobject javaThis



********Android APP

***Android中Activity, Intent, Content Provider, Service各有什么区别。

Activity: 活动,是最基本的android应用程序组件。一个活动就是一个用户可以操作的可视化用户界面,每一个活动都被实现为一个独立的类,并且从活动基类继承而来。

Intent: 意图,描述应用想干什么。最重要的部分是动作和动作对应的数据。

Content Provider:内容提供器,android应用程序能够将它们的数据保存到文件、SQLite数据库中,甚至是任何有效的设备中。当你想将你的应用数据和其他应用共享时,内容提供器就可以发挥作用了。

Service:服务,具有一段较长生命周期且没有用户界面的程序组件。

 

***简要解释一下activity、 intent 、intent filter、service、Broadcast、BroadcaseReceiver

  答:一个activity呈现了一个用户可以操作的可视化用户界面

  一个service不包含可见的用户界面,而是在后台无限地运行

  可以连接到一个正在运行的服务中,连接后,可以通过服务中暴露出来的借口与其进行通信

  一个broadcast receiver是一个接收广播消息并作出回应的component,broadcastreceiver没有界面

  intent:content provider在接收到ContentResolver的请求时被激活。

  activity, service和broadcast receiver是被称为intents的异步消息激活的。

  一个intent是一个Intent对象,它保存了消息的内容。对于activity和service来说,它指定了请求的操作名称和待操作数据的URI

  Intent对象可以显式的指定一个目标component。如果这样的话,android会找到这个component(基于manifest文件中的声明)并激活它。但如果一个目标不是显式指定的,android必须找到响应intent的最佳component。

  它是通过将Intent对象和目标的intent filter相比较来完成这一工作的。一个component的intent filter告诉android该component能处理的intent。intent filter也是在manifest文件中声明的。

 

 

***简述Android应用程序结构是哪些?(7分)

        Android应用程序结构是:

  Linux Kernel(Linux内核)、Libraries(系统运行库或者是c/c++核心库)、Application

  Framework(开发框架包)、Applications (核心应用程序)

 

***请解释下Android程序运行时权限与文件系统权限的区别。

     运行时权限Dalvik( android授权)

  文件系统 linux 内核授权

 

***请解释下Android程序运行时权限与文件系统权限的区别。

   Android程序执行需要读取到安全敏感项必需在androidmanifest.xml中声明相关权限请求, 打电话,访问网络,获取坐标,读写sd卡,读写联系人等..安装的时候会提示用户…

文件系统的权限是linux权限. 比如说sharedpreference里面的Context.Mode.private  Context.Mode.world_read_able   Context.Mode_world_writeable  

777自己 同组 其他

root 是危险的行为 

 

***android本身的一些限制,比如apk包大小限制,读取大文件时的时间限。

 这个问题问的有问题, apk包大小限制不好说,

极品飞车有100M 还是能装到手机上,

世面google market 上大程序  主程序 很小 5~10M    下载sdcard

15分钟之内 申请退款  

apk包,精简包, 素材存放在服务器. 游戏程序.

读大文件的时间限制应该是main线程里面的时间限制吧.5秒.

 

***Android程序与Java程序的区别?

Android程序用android sdk开发,java程序用javasdk开发.

Android SDK引用了大部分的Java SDK,少数部分被Android SDK抛弃,比如说界面部分,java.awt  swing  package除了java.awt.font被引用外,其他都被抛弃,在Android平台开发中不能使用。

android sdk 添加工具jar httpclient , pull  openGL

将Java 游戏或者j2me程序移植到Android平台的过程中,

Android  SDK 与Java SDK的区别是很需要注意的地方。

1.6的 不支持 httpUrlconning 获取 last-modified 信息的处理

simpleDataFormat

 

***什么情况会导致Force Close?如何避免?能否捕获导致其的异常?

 

答:如空指针等可以导致ForceClose;可以看Logcat,然后找到对应的程序代码来解决错误。

 

***如何将SQLite数据库(.db文件)与apk文件一起发布?

 

答:可以将.db文件复制到Eclipse Android工程中的res aw目录中。所有在res aw目录中的文件不会被压缩,这样可以直接提取该目录中的文件。可以将.db文件复制到res aw目录中

 

***如何将打开res aw目录中的数据库文件?

 

答: 在Android中不能直接打开res aw目录中的数据库文件,而需要在程序第一次启动时将该文件复制到手机内存或SD卡的某个目录中,然后再打开该数据库文件。复制的基本方法是使用 getResources().openRawResource方法获得res aw目录中资源的 InputStream对象,然后将该InputStream对象中的数据写入其他的目录中相应文件中。在Android SDK中可以使用SQLiteDatabase.openOrCreateDatabase方法来打开任意目录中的SQLite数据库文件。

 

***DDMS和TraceView的区别?

 

答:DDMS是一个程序执行查看器,在里面可以看见线程和堆栈等信息,TraceView是程序性能分析器

 

 

***Application类的作用:

 

答:API里的第一句是:

 

Base class for those who need to maintain global application state

如果想在整个应用中使用全局变量,在java中一般是使用静态变量,public类型;而在android中如果使用这样的全局变量就不符合Android的框架架构,但是可以使用一种更优雅的方式就是使用Application context。

  首先需要重写Application,主要重写里面的onCreate方法,就是创建的时候,初始化变量的值。然后在整个应用中的各个文件中就可以对该变量进行操作了。

  启动Application时,系统会创建一个PID,即进程ID,所有的Activity就会在此进程上运行。那么我们在Application创 建的时候初始化全局变量,同一个应用的所有Activity都可以取到这些全局变量的值,换句话说,我们在某一个Activity中改变了这些全局变量的 值,那么在同一个应用的其他Activity中值就会改变

 

***说明onSaveInstanceState() 和 onRestoreInstanceState()在什么时候被调用:

 

答:Activity 的 onSaveInstanceState() 和 onRestoreInstanceState()并不是生命周期方法,它们不同于 onCreate()、onPause()等生命周期方法,它们并不一定会被触发。当应用遇到意外情况(如:内存不足、用户直接按Home键)由系统销毁 一个Activity时,onSaveInstanceState()才会被调用。但是当用户主动去销毁一个Activity时,例如在应用中按返回 键,onSaveInstanceState()就不会被调用。因为在这种情况下,用户的行为决定了不需要保存Activity的状态。通常 onSaveInstanceState()只适合用于保存一些临时性的状态,而onPause()适合用于数据的持久化保存。

 

另外,当屏幕的方向发生了改变, Activity会被摧毁并且被重新创建,如果你想在Activity被摧毁前缓存一些数据,并且在Activity被重新创建后恢复缓存的数据。可以重 写Activity的 onSaveInstanceState() 和 onRestoreInstanceState()方法。

 

***启动一个程序,可以主界面点击图标进入,也可以从一个程序中跳转过去,二者有什么区别? 

 区别是根据activity在manifest里面的配置,这个activity可能会放在不同的task栈里面

intent设置的flag  flag_new_task

 

***不同工程中的方法是否可以相互调用?

  可以,列举aidl访问远程服务的例子.

 

***书写出android工程的目录结构 

  src 

  android. jar 

  asset

  res

  gen 

  manifest

 

***java中的soft reference是个什么东西

 StrongReference 是 Java 的默认引用实现, 它会尽可能长时间的存活于 JVM 内, 当没有任何对象指向它时 GC 执行后将会被回收

SoftReference 会尽可能长的保留引用直到 JVM 内存不足时才会被回收(虚拟机保证), 这一特性使得 SoftReference 非常适合缓存

应用详细见豆瓣客户端图片的缓存

 

***ddms 和traceview的区别.

   daivilk debug manager system 

1.在应用的主activity的onCreate方法中加入Debug.startMethodTracing("要生成的traceview文件的名字");

2.同样在主activity的onStop方法中加入Debug.stopMethodTracing();

3.同时要在AndroidManifest.xml文件中配置权限

   <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>

3.重新编译,安装,启动服务,测试完成取对应的traceview文件(adb pull /sdcard/xxxx.trace)。

4.直接在命令行输入traceview xxxxtrace,弹出traceview窗口,分析对应的应用即可。

traceview 分析程序执行时间和效率

KPI : key performance information : 关键性能指标:

 splash界面不能超过5秒

 从splash 界面加载mainactivity 不能超过0.7秒 。



***********Intent

***IntentService有何优点?

  答:IntentService 的好处

  * Acitivity的进程,当处理Intent的时候,会产生一个对应的Service

  * Android的进程处理器现在会尽可能的不kill掉你

  * 非常容易使用



************SQlite

*** 请继承SQLiteOpenHelper实现:

       1).创建一个版本为1的“diaryOpenHelper.db”的数据库,

  2).同时创建一个 “diary” 表(包含一个_id主键并自增长,topic字符型100长度, content字符型1000长度)

  3).在数据库版本变化时请删除diary表,并重新创建出diary表。

  publicclass DBHelper extends SQLiteOpenHelper{

  public final static String DATABASENAME ="diaryOpenHelper.db";

  public final static int DATABASEVERSION =1;

  //创建数据库

  public DBHelper(Context context,Stringname,CursorFactory factory,int version)

  {

  super(context, name, factory,version);

  }

  //创建表等机构性文件

  public void onCreate(SQLiteDatabase db)

  {

  String sql ="create tablediary"+

  "("+

  "_idinteger primary key autoincrement,"+

  "topicvarchar(100),"+

  "contentvarchar(1000)"+

  ")";

  db.execSQL(sql);

  }

  //若数据库版本有更新,则调用此方法

  public void onUpgrade(SQLiteDatabasedb,int oldVersion,int newVersion)

  {

  String sql = "drop table ifexists diary";

  db.execSQL(sql);

  this.onCreate(db);

  }

  }


************数字签名

***简单描述下Android 数字签名。

Android 数字签名

       在Android系统中,所有安装到系统的应用程序都必有一个数字证书,此数字证书用于标识应用程序的作者和在应用程序之间建立信任关系 

Android系统要求每一个安装进系统的应用程序都是经过数字证书签名的,数字证书的私钥则保存在程序开发者的手中。Android将数字证书用来标识应用程序的作者和在应用程序之间建立信任关系,不是用来决定最终用户可以安装哪些应用程序。

这个数字证书并不需要权威的数字证书签名机构认证(CA),它只是用来让应用程序包自我认证的。

同一个开发者的多个程序尽可能使用同一个数字证书,这可以带来以下好处。

(1)有利于程序升级,当新版程序和旧版程序的数字证书相同时,Android系统才会认为这两个程序是同一个程序的不同版本。如果新版程序和旧版程序的数字证书不相同,则Android系统认为他们是不同的程序,并产生冲突,会要求新程序更改包名。

(2)有利于程序的模块化设计和开发。Android系统允许拥有同一个数字签名的程序运行在一个进程中,Android程序会将他们视为同一个程序。所以开发者可以将自己的程序分模块开发,而用户只需要在需要的时候下载适当的模块。

在签名时,需要考虑数字证书的有效期:

(1)数字证书的有效期要包含程序的预计生命周期,一旦数字证书失效,持有改数字证书的程序将不能正常升级。

(2)如果多个程序使用同一个数字证书,则该数字证书的有效期要包含所有程序的预计生命周期。

(3)Android Market强制要求所有应用程序数字证书的有效期要持续到2033年10月22日以后。 

Android数字证书包含以下几个要点:

 (1)所有的应用程序都必须有数字证书,Android系统不会安装一个没有数字证书的应用程序

 (2)Android程序包使用的数字证书可以是自签名的,不需要一个权威的数字证书机构签名认证

 (3)如果要正式发布一个Android ,必须使用一个合适的私钥生成的数字证书来给程序签名,而不能使用adt插件或者ant工具生成的调试证书来发布。

 (4)数字证书都是有有效期的,Android只是在应用程序安装的时候才会检查证书的有效期。如果程序已经安装在系统中,即使证书过期也不会影响程序的正常功能。



*********数据存储

***谈谈android数据存储方式

Android提供了5种方式存储数据:

(1)使用SharedPreferences存储数据;它是Android提供的用来存储一些简单配置信息的一种机制,采用了XML格式将数据存储到设备中。只能在同一个包内使用,不能在不同的包之间使用。

(2)文件存储数据;文件存储方式是一种较常用的方法,在Android中读取/写入文件的方法,与Java中实现I/O的程序是完全一样的,提供了openFileInput()和openFileOutput()方法来读取设备上的文件。

(3)SQLite数据库存储数据;SQLite是Android所带的一个标准的数据库,它支持SQL语句,它是一个轻量级的嵌入式数据库。

(4)使用ContentProvider存储数据;主要用于应用程序之间进行数据交换,从而能够让其他的应用保存或读取此Content Provider的各种数据类型。

(5)网络存储数据;通过网络上提供给我们的存储空间来上传(存储)和下载(获取)我们存储在网络空间中的数据信息。



****************五种布局

***请介绍下Android中常用的五种布局

   

 1.FrameLayout (框架布局)

    这个布局可以看成是墙脚堆东西,有一个四方的矩形的左上角墙脚,我们放了第一个东西,要再放一个,那就在放在原来放的位置的上面,这样依次的放,会盖住原来的东西。这个布局比较简单,也只能放一点比较简单的东西。    

 

2.LinearLayout(线性布局)    

    线性布局,这个东西,从外框上可以理解为一个div,他首先是一个一个从上往下罗列在屏幕上。每一个LinearLayout里面又可分为垂直(android:orientation="vertical")和水平布局(android:orientation="horizontal" )。

垂直布局时,每一行就只有一个元素,多个元素依次垂直往下;

水平布局时,只有一行,每一个元素依次向右排列。    

linearLayout中有一个重要的属性 android:layout_weight="1",这个weight在垂直布局时,代表行距;水平的时候代表列宽;weight值越大就越大。    

 

3.AbsoluteLayout(绝对布局)    

    绝对布局犹如div指定了absolute属性,用X,Y坐标来指定元素的位置android:layout_x="20px" android:layout_y="12px" 这种布局方式也比较简单,但是在垂直随便切换时,往往会出问题,而且多个元素的时候,计算比较麻烦。    

 

4.RelativeLayout(相对布局)    

    相对布局可以理解为某一个元素为参照物,来定位的布局方式。主要属性有:    


    相对于某一个元素    

   android:layout_below="@id/aaa" 该元素在 id为aaa的下面    

   android:layout_toLeftOf="@id/bbb" 改元素的左边是bbb    

 

   相对于父元素的地方    

  android:layout_alignParentLeft="true"  在父元素左对齐    

  android:layout_alignParentRight="true" 在父元素右对齐    

  

5.TableLayout(表格布局)    

    表格布局类似Html里面的Table。每一个TableLayout里面有表格行TableRow,TableRow里面可以具体定义每一个元素,设定他的对齐方式 android:gravity=""。每一个布局都有自己适合的方式.另外,这五个布局元素可以相互嵌套应用,做出美观的界面。

 

***android:gravity与android:layout_gravity的区别

LinearLayout有两个非常相似的属性:android:gravity与android:layout_gravity。他们的区别在于:

android:gravity用于设置View组件的对齐方式;

android:layout_gravity用于设置Container组件的对齐方式。

 

举个例子,我们可以通过设置android:gravity="center"来让EditText中的文字在EditText组件中居中显示;同时我们设置EditText的android:layout_gravity="right"来让EditText组件在LinearLayout中居右显示。来实践以下:


正如我们所看到的,在EditText中,其中的文字已经居中显示了,而EditText组件自己也对齐到了LinearLayout的右侧。 

[html] view plaincopyprint?

<LinearLayout   

    xmlns:android="http://schemas.android.com/apk/res/android"   

    android:orientation="vertical"   

    android:layout_width="fill_parent"   

    android:layout_height="fill_parent">   

    <EditText   

        android:layout_width="wrap_content"   

        android:gravity="center"   

        android:layout_height="wrap_content"   

        android:text="one"   

        android:layout_gravity="right"/>   

</LinearLayout>

 


*************常用控件

***Android常用控件的信息

 

单选框(RadioButton与RadioGroup):RadioGroup用于对单选框进行分组,相同组内的单选框只有一个单选框被选中。

 

事件:setOnCheckedChangeListener(),处理单选框被选择事件。把RadioGroup.OnCheckedChangeListener实例作为参数传入。

 

多选框(CheckBox):每个多选框都是独立的,可以通过迭代所有的多选框,然后根据其状态是否被选中在获取其值。

 

事件:setOnCheckChangeListener()处理多选框被选择事件。把CompoundButton.OnCheckedChangeListener实例作为参数传入

 

下拉列表框(Spring):Spinner.getItemAtPosition(Spinner.getSelectedItemPosition());获取下拉列表框的值。

 

事件:setOnItemSelectedListener(),处理下拉列表框被选择事件把AdapterView.OnItemSelectedListener实例作为参数传入;

 

拖动条(SeekBar):SeekBar.getProgress()获取拖动条当前值

 

事件:setOnSeekBarChangeListener(),处理拖动条值变化事件,把SeekBar.OnSeekBarChangeListener实例作为参数传入。

 

菜单(Menu):重写Activity的onCreatOptionMenu(Menu menu)方法,该方法用于创建选项菜单,咋用户按下手机的"Menu"按钮时就会显示创建好的菜单,在                  onCreatOptionMenu(Menu Menu)方法内部可以调用Menu.add()方法实现菜单的添加。重写Activity的onMenuItemSelected()方法,该方法用于处理菜单被选择事件。

 

进度对话框(ProgressDialog):创建并显示一个进度对话框:ProgressDialog.show(ProgressDialogActivity.this,"请稍等","数据正在加载中....",true);

 

设置对话框的风格:setProgressStyle()

 

ProgressDialog.STYLE_SPINNER  旋转进度条风格(为默认风格)

 

ProgressDialog.STYLE_HORIZONTAL 横向进度条风格

 

***页面上现有ProgressBar控件progressBar,请用书写线程以10秒的的时间完成其进度显示工作。

答案:

  publicclass ProgressBarStu extends Activity {

  private ProgressBar progressBar = null;

  protected void onCreate(BundlesavedInstanceState) {

  super.onCreate(savedInstanceState);

  setContentView(R.layout.progressbar);

  //从这到下是关键

  progressBar = (ProgressBar)findViewById(R.id.progressBar);

  Thread thread = new Thread(newRunnable() {

  @Override

  public void run() {

  int progressBarMax =progressBar.getMax();

  try {

  while(progressBarMax!=progressBar.getProgress())

  {

  intstepProgress = progressBarMax/10;

  intcurrentprogress = progressBar.getProgress();

  progressBar.setProgress(currentprogress+stepProgress);

  Thread.sleep(1000);

  }

  } catch(InterruptedException e) {

  // TODO Auto-generatedcatch block

  e.printStackTrace();

  }

  }

  });

  thread.start();

  //关键结束

  }

  }

 

***ListView优化

 

工作原理:

 

ListView 针对List中每个item,要求 adapter “给我一个视图” (getView)。

 

一个新的视图被返回并显示

 

如果我们有上亿个项目要显示怎么办?为每个项目创建一个新视图?NO!这不可能!

 

实际上Android为你缓存了视图。

 

Android中有个叫做Recycler的构件,下图是他的工作原理:

 

如果你有10亿个项目(item),其中只有可见的项目存在内存中,其他的在Recycler中。

 

1. ListView先请求一个type1视图(getView)然后请求其他可见的项目。convertView在getView中是空(null)的。

 

2. 当item1滚出屏幕,并且一个新的项目从屏幕低端上来时,ListView再请求一个type1视图。convertView此时不是空值了,它的值是item1。你只需设定新的数据然后返回convertView,不必重新创建一个视图。

 


***********Android系统架构

***描述一下android的系统架构

答:android系统架构分从下往上为Linux内核层、运行库、应用程序框架层和应用程序层。

 

Linux内核层:负责硬件的驱动程序、网络、电源、系统安全以及内存管理等功能。

 

运 行库和androidruntion:运行库:即c/c++函数库部分,大多数都是开放源代码的函数库,例如webkit,该函数库负责android网 页浏览器的运行;例如标准的c函数库libc、openssl、sqlite等,当然也包括支持游戏开发的2dsgl和3dopengles,在多媒体方 面有mediaframework框架来支持各种影音和图形文件的播放与显示,如mpeg4、h.264、mp3、aac、amr、jpg和png等众多 的多媒体文件格式。Androidruntion负责解释和执行生成的dalvik格式的字节码

 

应用软件架构:java应用程序开发人员主要是使用该层封装好的api进行快速开发的。

 

应用程序层:该层是java的应用程序层,android内置的googlemaps、email、IM、浏览器等,都处于该层,java开发人员工发的程序也处于该层,而且和内置的应用程序具有平等的地位,可以调用内置的应用程序,也可以替换内置的应用程序

 

***Android系统的架构

android的系统架构和其操作系统一样,采用了分层的架构。从架构图看,android分为四个层,从高层到低层分别是应用程序层、应用程序框架层、系统运行库层和linux核心层。

 

  1.应用程序

 

  Android会同一系列核心应用程序包一起发布,该应用程序包包括email客户端,SMS短消息程序,日历,地图,浏览器,联系人管理程序等。所有的应用程序都是使用JAVA语言编写的。

 

  2.应用程序框架

 

  开发人员也可以完全访问核心应用程序所使用的API框架。该应用程序的架构设计简化了组件的重用;任何一个应用程序都可以发布它的功能块并且任何其它的应用程序都可以使用其所发布的功能块(不过得遵循框架的安全性限制)。同样,该应用程序重用机制也使用户可以方便的替换程序组件。

 

  隐藏在每个应用后面的是一系列的服务和系统, 其中包括;

 

  * 丰富而又可扩展的视图(Views),可以用来构建应用程序, 它包括列表(lists),网格(grids),文本框(text boxes),按钮(buttons), 甚至可嵌入的web浏览器。

 

  * 内容提供器(Content Providers)使得应用程序可以访问另一个应用程序的数据(如联系人数据库), 或者共享它们自己的数据

 

  * 资源管理器(Resource Manager)提供 非代码资源的访问,如本地字符串,图形,和布局文件( layout files )。

 

  * 通知管理器 (Notification Manager) 使得应用程序可以在状态栏中显示自定义的提示信息。

 

  * 活动管理器( Activity Manager) 用来管理应用程序生命周期并提供常用的导航回退功能。

 

  有关更多的细节和怎样从头写一个应用程序,请参考 如何编写一个 Android 应用程序.

 

  3.系统运行库

 

  1)程序库

 

  Android 包含一些C/C++库,这些库能被Android系统中不同的组件使用。它们通过 Android 应用程序框架为开发者提供服务。以下是一些核心库:

 

  * 系统 C 库 - 一个从 BSD 继承来的标准 C 系统函数库( libc ), 它是专门为基于 embedded linux 的设备定制的。

 

  * 媒体库 - 基于 PacketVideo OpenCORE;该库支持多种常用的音频、视频格式回放和录制,同时支持静态图像文件。编码格式包括MPEG4, H.264, MP3, AAC, AMR, JPG, PNG 。

 

  * Surface Manager - 对显示子系统的管理,并且为多个应用程序提 供了2D和3D图层的无缝融合。

 

  * LibWebCore - 一个最新的web浏览器引擎用,支持Android浏览器和一个可嵌入的web视图。

 

  * SGL - 底层的2D图形引擎

 

  * 3D libraries - 基于OpenGL ES 1.0 APIs实现;该库可以使用硬件 3D加速(如果可用)或者使用高度优化的3D软加速。

 

  * FreeType -位图(bitmap)和矢量(vector)字体显示。

 

  * SQLite - 一个对于所有应用程序可用,功能强劲的轻型关系型数据库引擎。

 

  2)Android 运行库

 

  Android 包括了一个核心库,该核心库提供了JAVA编程语言核心库的大多数功能。

 

  每一个Android应用程序都在它自己的进程中运行,都拥有一个独立的Dalvik虚拟机实例。Dalvik被设计成一个设备可以同时高效地运行多个虚拟系统。 Dalvik虚拟机执行(.dex)的Dalvik可执行文件,该格式文件针对小内存使用做了优化。同时虚拟机是基于寄存器的,所有的类都经由JAVA编译器编译,然后通过SDK中 的 “dx” 工具转化成.dex格式由虚拟机执行。

 

  Dalvik虚拟机依赖于linux内核的一些功能,比如线程机制和底层内存管理机制。

 

  4.Linux 内核

 

Android 的核心系统服务依赖于 Linux 2.6 内核,如安全性,内存管理,进程管理, 网络协议栈和驱动模型。 Linux 内核也同时作为硬件和软件栈之间的抽象层。

 

***谈谈Android的优点和不足之处。

1、开放性,开源 ophone  阿里云( 完全兼容android)

2、挣脱运营商束缚 

3、丰富的硬件选择 mtk android 

4、不受任何限制的开发商

5、无缝结合的Google应用

 

缺点也有5处:

1、安全问题、隐私问题 

2、卖手机的不是最大运营商

3、运营商对Android手机仍然有影响

4、山寨化严重

5、过分依赖开发商,缺乏标准配置 版本过多。



**************XML

***android 中有哪几种解析xml的类?官方推荐哪种?以及它们的原理和区别

 

答:XML 解析主要有三种方式,SAX、DOM、PULL。常规在PC上开发我们使用Dom相对轻松些,但一些性能敏感的数据库或手机上还是主要采用SAX方 式,SAX读取是单向的,优点:不占内存空间、解析属性方便,但缺点就是对于套嵌多个分支来说处理不是很方便。而DOM方式会把整个XML文件加载到内存 中去,这里Android开发网提醒大家该方法在查找方面可以和XPath很好的结合如果数据量不是很大推荐使用,而PULL常常用在J2ME对于节点处 理比较好,类似SAX方式,同样很节省内存,在J2ME中我们经常使用的KXML库来解析。

 

***android中有哪几种解析xml的类,官方推荐哪种?以及它们的原理和区别.

Ø DOM解析

优点:

 

1.XML树在内存中完整存储,因此可以直接修改其数据和结构. 

 

2.可以通过该解析器随时访问XML树中的任何一个节点. 

 

3.DOM解析器的API在使用上也相对比较简单.

 

缺点:如果XML文档体积比较大时,将文档读入内存是非常消耗系统资源的.

 

使用场景:DOM 是用与平台和语言无关的方式表示 XML 文档的官方 W3C 标准.DOM 是以层次结构组织的节点的集合.这个层次结构允许开发人员在树中寻找特定信息.分析该结构通常需要加载整个文档和构造层次结构,然后才能进行任何工作.DOM是基于对象层次结构的.

 

Ø SAX解析

 

优点:

 

SAX 对内存的要求比较低,因为它让开发人员自己来决定所要处理的标签.特别是当开发人员只需要处理文档中所包含的部分数据时,SAX 这种扩展能力得到了更好的体现.

 

缺点:

 

用SAX方式进行XML解析时,需要顺序执行,所以很难访问到同一文档中的不同数据.此外,在基于该方式的解析编码过程也相对复杂.

 

使用场景:

 

对于含有数据量十分巨大,而又不用对文档的所有数据进行遍历或者分析的时候,使用该方法十分有效.该方法不用将整个文档读入内存,而只需读取到程序所需的文档标签处即可.

 

Ø Xmlpull解析

 

android SDK提供了xmlpull api,xmlpull和sax类似,是基于流(stream)操作文件,然后根据节点事件回调开发者编写的处理程序.因为是基于流的处理,因此xmlpull和sax都比较节约内存资源,不会象dom那样要把所有节点以对橡树的形式展现在内存中.xmlpull比sax更简明,而且不需要扫描完整个流.

 

 

 

***Manifest.xml文件中主要包括哪些信息?

manifest:根节点,描述了package中所有的内容。

uses-permission:请求你的package正常运作所需赋予的安全许可。

permission: 声明了安全许可来限制哪些程序能你package中的组件和功能。

instrumentation:声明了用来测试此package或其他package指令组件的代码。

application:包含package中application级别组件声明的根节点。

activity:Activity是用来与用户交互的主要工具。

receiver:IntentReceiver能使的application获得数据的改变或者发生的操作,即使它当前不在运行。

service:Service是能在后台运行任意时间的组件。

provider:ContentProvider是用来管理持久化数据并发布给其他应用程序使用的组件。



**********ANR

***什么是ANR,如何避免?

答:ANR的定义:

在android上,如果你的应用程序有一段时间响应不移灵敏,系统会向用户提示“应用程序无响应”(ANR:application Not Responding)对话框。因此,在程序里对响应性能的设计很重要,这样,系统不会显示ANR给用户。

 

如何避免:

首先来研究下为什么它会在android的应用程序里发生和如何最佳构建应用程序来避免ANR.

    android应用程序通常是运行在一个单独的线程(例如:main)里,这就意味你的应用程序所做的事情如果在主线程里占用了大长时间的话,就会引发ANR对话框,因为你的应用程序并没有给自己机会来处理输入事件或者Intent广播。

 

    因此,运行在主线程里的任何访求都尽可能少做事情。特别是,activity应该在它的关键生命周期方法(onCreate()和onResume()) 里尽可能少的去作创建操作。潜在的耗时操作,例如网络或数据库操作,或者高耗时的计算如改变位图尺寸,应该在子线程里(或者以数据库操作为例,通过异步请 求的方式)来完成。然而,不是说你的主线程阻塞在那里等待子线程的完成---也不是调用Thread.wait()或者Thread.sleep()。替 代的方法是:主线程应该为子线程提供一个Handler,以便完成时能够提交给主线程。以这种方式设计你的应用程序,将能保证你的主线程保持对输入的响应 性并能避免由5秒输入事件的超时引发的ANR对话框。这种做法应该在其它显示UI的线程里效仿,因为它们都受相同的超时影响。

 

    IntentReceiver执行时间的特殊限制意味着它应该做:在后台里做小的、琐碎的工作,如保存设定或注册一个Notification。和在主线 程里调用的其它方法一样,应用程序应该避免在BroadcastReceiver里做耗时的操作或计算,但也不是在子线程里做这些任务(因为 BroadcastReceiver的生命周期短),替代的是,如果响应Intent广播需要执行一个耗时的动作的话,应用程序应该启动一个 Service。顺便提及一句,你也应该避免在Intent Receiver里启动一个Activity,因为它会创建一个新的画面,并从当前用户正在运行的程序上抢夺焦点。如果你的应用程序在响应Intent广 播时需要向用户展示什么,你应该使用Notification Manager来实现。

 

    一般来说,在应用程序里,100到200ms是用户能感知阻滞的时间阈值,下面总结了一些技巧来避免ANR,并有助于让你的应用程序看起来有响应性。

 

    如果你的应用程序为响应用户输入正在后台工作的话,可以显示工作的进度(ProgressBar和ProgressDialog对这种情况来说很有用)。 特别是游戏,在子线程里做移动的计算。如果你的程序有一个耗时的初始化过程的话,考虑可以显示一个Splash Screen或者快速显示主画面并异步来填充这些信息。在这两种情况下,你都应该显示正在进行的进度,以免用户认为程序被冻结了。

 

***什么是ANR 如何避免它?

 

ANR:Application Not Responding,五秒 

 

在Android中,活动管理器和窗口管理器这两个系统服务负责监视应用程序的响应。当出现下列情况时,Android就会显示ANR对话框了: 

 

  对输入事件(如按键、触摸屏事件)的响应超过5秒 

 

  意向接受器(intentReceiver)超过10秒钟仍未执行完毕 

 

  Android应用程序完全运行在一个独立的线程中(例如main)。这就意味着,任何在主线程中运行的,需要消耗大量时间的操作都会引发ANR。因为此时,你的应用程序已经没有机会去响应输入事件和意向广播(Intent broadcast)。 

 

  因此,任何运行在主线程中的方法,都要尽可能的只做少量的工作。特别是活动生命周期中的重要方法如onCreate()和 onResume()等更应如此。潜在的比较耗时的操作,如访问网络和数据库;或者是开销很大的计算,比如改变位图的大小,需要在一个单独的子线程中完成(或者是使用异步请求,如数据库操作)。但这并不意味着你的主线程需要进入阻塞状态已等待子线程结束 -- 也不需要调用Therad.wait()或者Thread.sleep()方法。取而代之的是,主线程为子线程提供一个句柄(Handler),让子线程在即将结束的时候调用它(xing:可以参看Snake的例子,这种方法与以前我们所接触的有所不同)。使用这种方法涉及你的应用程序,能够保证你的程序对输入保持良好的响应,从而避免因为输入事件超过5秒钟不被处理而产生的ANR。这种实践需要应用到所有显示用户界面的线程,因为他们都面临着同样的超时问题。



**************动画

***android中的动画有哪几类,它们的特点和区别是什么?

两种,一种是Tween动画、还有一种是Frame动画。

Tween动画,这种实现方式可以使视图组件移动、放大、缩小以及产生透明度的变化;

可以通过布局文件,可以通过代码

 1、 控制View的动画 

a) alpha(AlphaAnimation) 

渐变透明 

b) scale(ScaleAnimation) 

渐变尺寸伸缩 

c) translate(TranslateAnimation)

画面转换、位置移动 

d) rotate(RotateAnimation)

画面转移,旋转动画 

 

2、 控制一个Layout里面子View的动画效果

a) layoutAnimation(LayoutAnimationController)

b) gridAnimation(GridLayoutAnimationController)

另一种Frame动画,传统的动画方法,通过顺序的播放排列好的图片来实现,类似电影。

 

***android的动画有哪几种?他们的特点和区别是什么?

 

答:两种,一种是tween动画,一种是frame动画。tween动画,这种实现方式可以使视图组件移动,放大或缩小以及产生透明度的变化。frame动画,传统的动画方法,通过顺序的播放排列好的图片来实现,类似电影。

 

 

***android中的动画有哪几类,它们的特点和区别是什么?

Android提供两种创建简单动画的机制:tweened animation(补间动画) 和 frame-by-frame animation(帧动画).

tweened animation:通过对场景里的对象不断做图像变换(平移、缩放、旋转)产生动画效果

frame-by-frame animation:顺序播放事先做好的图像,跟电影类似

这两种动画类型都能在任何View对象中使用,用来提供简单的旋转计时器,activity图标及其他有用的UI元素。Tweened animation被andorid.view.animation包所操作;frame-by-frame animation被android.graphics.drawable.AnimationDrawable类所操作。

 

想了解更多关于创建tweened和frame-by-frame动画的信息,读一下Dev Guide-Graphics-2D Graphics里面相关部分的讨论。

 

Animation 是以 XML格式定义的,定义好的XML文件存放在res/anim中。由于Tween Animation与Frame-by-frame Animation的定义、使用都有很大的差异,我们将分开介绍,本篇幅中主要介绍Tween Animation的定义与使用。按照XML文档的结构【父节点,子节点,属性】来介绍Tween Animation,其由4种类型:

 

Alpha: 渐变透明度动画效果

Scale:渐变尺寸伸缩动画效果

Translate:画面转换位置移动动画效果

Rotate: 画面转换角度移动动画效果

在介绍以上4种 类型前,先介绍Tween Animation共同的节点属性。

 

表一

属性[类型] 功能  

Duration[long] 属性为动画持续时间 时间以毫秒为单位

fillAfter [boolean] 当设置为true ,该动画转化在动画结束后被应用

fillBefore[boolean] 当设置为true ,该动画转化在动画开始前被应用

interpolator

 

指定一个动画的插入器 有一些常见的插入器

accelerate_decelerate_interpolator

加速-减速 动画插入器

accelerate_interpolator

加速-动画插入器

decelerate_interpolator

减速- 动画插入器

其他的属于特定的动画效果

repeatCount[int] 动画的重复次数  

RepeatMode[int] 定义重复的行为 1:重新开始  2:plays backward

startOffset[long] 动画之间的时间间隔,从上次动画停多少时间开始执行下个动画

zAdjustment[int] 定义动画的Z Order的改变 0:保持Z Order不变

1:保持在最上层

-1:保持在最下层

 

下面我们开始结 合具体的例子,分别介绍4种类型各自特有的节点元素。

 

表二

XML节点 功能说明

alpha 渐变透明度动画效果

<alpha

android:fromAlpha=”0.1″

android:toAlpha=”1.0″

android:duration=”3000″ />

fromAlpha 

属性为动画起始时透明度

 

0.0表示完全不透明

1.0表示完全透明

以上值取0.0-1.0之间的float数据类型的数字

toAlpha 属性为动画结束时透明度

 

表三

scale 渐变尺寸伸缩动画效果

<scale

android:interpolator= “@android:anim/accelerate_decelerate_interpolator”

android:fromXScale=”0.0″

android:toXScale=”1.4″

android:fromYScale=”0.0″

android:toYScale=”1.4″

android:pivotX=”50%”

android:pivotY=”50%”

android:fillAfter=”false”

android:startOffset=“700”

android:duration=”700″

android:repeatCount=”10″ />

fromXScale[float] fromYScale[float] 为动画起始时,X、Y坐标上的伸缩尺寸 0.0表示收缩到没有

1.0表示正常无伸缩

值小于1.0表示收缩

值大于1.0表示放大

toXScale [float]

toYScale[float] 为动画结束时,X、Y坐标上的伸缩尺寸

pivotX[float]

pivotY[float] 为动画相对于物件的X、Y坐标的开始位置 属性值说明:从0%-100%中取值,50%为物件的X或Y方向坐标上的中点位置

       

表四

translate 画面转换位置移动动画效果

<translate

android:fromXDelta=”30″

android:toXDelta=”-80″

android:fromYDelta=”30″

android:toYDelta=”300″

android:duration=”2000″ />

fromXDelta

toXDelta 为动画、结束起始时 X坐标上的位置  

fromYDelta

toYDelta 为动画、结束起始时 Y坐标上的位置  

       

表五

rotate 画面转移旋转动画效果

<rotate

android:interpolator=”@android:anim/accelerate_decelerate_interpolator”

android:fromDegrees=”0″

android:toDegrees=”+350″

android:pivotX=”50%”

android:pivotY=”50%”

android:duration=”3000″ />

fromDegrees 为动画起始时物件的角度 说明

当角度为负数——表示逆时针旋转

当角度为正数——表示顺时针旋转

(负数from——to正数:顺时针旋转)

(负数from——to负数:逆时针旋转)

(正数from——to正数:顺时针旋转)

(正数from——to负数:逆时针旋转)

toDegrees 

为动画结束时物 件旋转的角度 可以大于360度

 

 

 

pivotX

pivotY 为动画相对于物件的X、Y坐标的开始位置 说明:以上两个属性值 从0%-100%中取值

50%为物件的X或Y方向坐标上的中点位置

 

Android SDK提供了基类:Animation,包含大量的set/getXXXX()函数来设置、读取Animation的属性,也就是前面表一中显示的各种属性。Tween Animation由4种类型:alpha、scale、translate、roate,在Android SDK中提供了相应的类,Animation类派生出了AlphaAnimation、ScaleAnimation、 TranslateAnimation、RotateAnimation分别实现了 改变 Alpha值 、 伸缩 、 平移 、 旋转 等动画,每个子类都在父类的基础上增加了各自独有的属性。

 

(补充)

 

     Android的动画效果分为两种,一种是tweened animation(补间动画),第二种是frame by frame animation。一般我们用的是第一种。补间动画又分为AlphaAnimation,透明度转换  RotateAnimation,旋转转换  ScaleAnimation,缩放转换  TranslateAnimation 位置转换(移动)。

动画效果在anim目录下的xml文件中定义,在程序中用AnimationUtils.loadAnimation(Context context,int ResourcesId)载入成Animation对象,在需要显示动画效果时,执行需要动画的View的startAnimation方法,传入Animation,即可。切换Activity也可以应用动画效果,在startActivity方法后,执行overridePendingTransition方法,两个参数分别是切换前的动画效果,切换后的动画效果。



*************NDK

***谈谈对Android NDK的理解。

native develop kit   只是一个交叉编译的工具  .so 

 1.什么时候用ndk,  实时性要求高,游戏,图形渲染,  

opencv (人脸识别) , ffmpeg , rmvb  mp5 avi 高清解码. ffmpeg, opencore.

2.为什么用ndk,ndk的优点 ,缺点 ,

我们项目中那些地方用到了ndk,  

 

***NDK是什么:

 

答:NDK是一系列工具的集合

    NDK提供了一系列的工具,帮助开发者迅速的开发C/C++的动态库,并能自动将so和java应用打成apk包

    NDK集成了交叉编译器,并提供了相应的mk文件和隔离cpu,平台等的差异,开发人员只需简单的修改mk文件就可以创建出so

 

***谈谈对Android NDK的理解

NDK全称:Native Development Kit。

 

  1、NDK是一系列工具的集合。

 

  * NDK提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成apk。这些工具对开发者的帮助是巨大的。

 

  * NDK集成了交叉编译器,并提供了相应的mk文件隔离CPU、平台、ABI等差异,开发人员只需要简单修改mk文件(指出“哪些文件需要编译”、“编译特性要求”等),就可以创建出so。

 

  * NDK可以自动地将so和Java应用一起打包,极大地减轻了开发人员的打包工作。

 

  2、NDK提供了一份稳定、功能有限的API头文件声明。

 

  Google明确声明该API是稳定的,在后续所有版本中都稳定支持当前发布的API。从该版本的NDK中看出,这些API支持的功能非常有限,包含有:C标准库(libc)、标准数学库(libm)、压缩库(libz)、Log库(liblog)。

 

1,双缓冲技术原理以及优缺点:

 

创建一幅后台图像,将每一帧画入图像,然后调用drawImage()方法将整个后台图像一次画到屏幕上去。

 

优点:双缓冲技术的优点在于大部分绘制是离屏的。

 

            将离屏图像一次绘至屏幕上,比直接在屏幕上绘制要有效得多。

 

            双缓冲技术可以使动画平滑。

 

缺点:要分配一个后台图像的缓冲,如果图像相当大,这将占用很大一块内存。

 

***AsyncTask简介

 

在开发Android移动客户端的时候往往要使用多线程来进行操作,我们通常会将耗时的操作放在单独的线程执行,避免其占用主线程而给用户带来不好的用户体验。但是在子线程中无法去操作主线程(UI 线程),在子线程中操作UI线程会出现错误。因此android提供了一个类Handler来在子线程中来更新UI线程,用发消息的机制更新UI界面,呈现给用户。这样就解决了子线程更新UI的问题。但是费时的任务操作总会启动一些匿名的子线程,太多的子线程给系统带来巨大的负担,随之带来一些性能问题。因此android提供了一个工具类AsyncTask,顾名思义异步执行任务。这个AsyncTask生来就是处理一些后台的比较耗时的任务,给用户带来良好用户体验的,从编程的语法上显得优雅了许多,不再需要子线程和Handler就可以完成异步操作并且刷新用户界面。

 

***Socket通信编程

 

客户端编程步骤:

1、 创建客户端套接字(指定服务器端IP地址与端口号)

2、 连接(Android 创建Socket时会自动连接)

3、 与服务器端进行通信

4、 关闭套接字

 

服务器端:

1.创建一个ServerSocket,用于监听客户端Socket的连接请求

2.采用循环不断接受来自客户端的请求

3.每当接受到客户端Socket的请求,服务器端也对应产生一个Socket。



************MVC

***说说mvc模式的原理,它在android中的运用。

MVC英文即Model-View-Controller,即把一个应用的输入、处理、输出流程按照Model、View、Controller的方式进行分离,这样一个应用被分成三个层——模型层、视图层、控制层。

Android中界面部分也采用了当前比较流行的MVC框架,在Android中M就是应用程序中二进制的数据,V就是用户的界面。Android的界面直接采用XML文件保存的,界面开发变的很方便。在Android中C也是很简单的,一个Activity可以有多个界面,只需要将视图的ID传递到setContentView(),就指定了以哪个视图模型显示数据。

 

在Android SDK中的数据绑定,也都是采用了与MVC框架类似的方法来显示数据。在控制层上将数据按照视图模型的要求(也就是Android SDK中的Adapter)封装就可以直接在视图模型上显示了,从而实现了数据绑定。比如显示Cursor中所有数据的ListActivity,其视图层就是一个ListView,将数据封装为ListAdapter,并传递给ListView,数据就在ListView中显示。

 

***利用mvc的模式重构代码

1) 重构前的代码Bmi.java:

package com.demo.android.bmi;

import java.text.DecimalFormat;

import android.app.Activity;

import android.os.Bundle;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.EditText;

import android.widget.TextView;

public class Bmi extends Activity {

 /** Called when the activity is first created. */

 @Override

 public void onCreate(Bundle savedInstanceState) {

  super.onCreate(savedInstanceState);

  setContentView(R.layout.main);

  // Listen for button clicks

  Button button = (Button) findViewById(R.id.submit);

  button.setOnClickListener(calcBMI);

 }

 private OnClickListener calcBMI = new OnClickListener() {

  @Override

  public void onClick(View v) {

   DecimalFormat nf = new DecimalFormat("0.00");

   EditText fieldheight = (EditText) findViewById(R.id.height);

   EditText fieldweight = (EditText) findViewById(R.id.weight);

   double height = Double.parseDouble(fieldheight.getText().toString()) / 100;

   double weight = Double.parseDouble(fieldweight.getText().toString());

   double BMI = weight / (height * height);

   TextView result = (TextView) findViewById(R.id.result);

   result.setText("Your BMI is " + nf.format(BMI));

   // Give health advice

   TextView fieldsuggest = (TextView) findViewById(R.id.suggest);

   if (BMI > 25) {

    fieldsuggest.setText(R.string.advice_heavy);

   } else if (BMI < 20) {

    fieldsuggest.setText(R.string.advice_light);

   } else {

    fieldsuggest.setText(R.string.advice_average);

   }

  }

 };

}

 

 

Step1:抽取所有界面元件的声明和定义,整合到单独一个函数findViews()中;

// 声明 view 

private Button button_calc;

private EditText field_height;

private EditText field_weight;

private TextView view_result;

private TextView view_suggest;

// 定义

private void findViews() {

 button_calc = (Button) findViewById(R.id.submit);

 field_height = (EditText) findViewById(R.id.height);

 field_weight = (EditText) findViewById(R.id.weight);

 view_result = (TextView) findViewById(R.id.result);

 view_suggest = (TextView) findViewById(R.id.suggest);

}

此部分即是MVC中的V:View视图。 

 

Step2:抽取程序的逻辑(即界面元件的处理逻辑),整合到函数setListensers()中;

//Listen for button clicks

private void setListensers() {

    button_calc.setOnClickListener(calcBMI);

}

此部分即是MVC中的C:Controller控制器。

接着,onCreate()就显得非常简洁、明了了:

public void onCreate(Bundle savedInstanceState) {

 super.onCreate(savedInstanceState);

 setContentView(R.layout.main);

 findViews();

 setListensers();

}

 

Step3:修改按钮监听器calcBMI中相应的部分(主要是变量已经在视图部分定义了);

private OnClickListener calcBMI = new OnClickListener() {

 @Override

 public void onClick(View v) {

  DecimalFormat nf = new DecimalFormat("0.00");

  double height = Double.parseDouble(field_height.getText().toString()) / 100;

  double weight = Double.parseDouble(field_weight.getText().toString());

  double BMI = weight / (height * height);

  // Present result

  view_result.setText("Your BMI is " + nf.format(BMI));

  // Give health advice

  if (BMI > 25) {

   view_suggest.setText(R.string.advice_heavy);

  } else if (BMI < 20) {

   view_suggest.setText(R.string.advice_light);

  } else {

   view_suggest.setText(R.string.advice_average);

  }

 }

};

 

总之,此重构的目的无非是使程序的脉络更加清晰,即让人一眼望去,就能很容易地分辨出界面(View)应该写在哪里,程序逻辑(Controller)应该写在哪里,最终使维护和扩展代码变得更加容易!

其实,重构很简单,通读代码,感觉哪边不太爽,就改那边吧!(我目前的感受)

一个良好的代码应该是能让人感到舒服的!

 

2)     重构后的代码Bmi.java:

package com.demo.android.bmi;

import java.text.DecimalFormat;

import android.app.Activity;

import android.os.Bundle;

import android.view.View;

import android.widget.Button;

import android.widget.EditText;

import android.widget.TextView;

public class Bmi extends Activity {

 private Button button_calc;

 private EditText field_height;

 private EditText field_weight;

 private TextView view_result;

 private TextView view_suggest;

 /** Called when the activity is first created. */

 @Override

 public void onCreate(Bundle savedInstanceState) {

  super.onCreate(savedInstanceState);

  setContentView(R.layout.main);

  findViews();

  setListensers();

 }

 // 定义

 private void findViews() {

  button_calc = (Button) findViewById(R.id.submit);

  field_height = (EditText) findViewById(R.id.height);

  field_weight = (EditText) findViewById(R.id.weight);

  view_result = (TextView) findViewById(R.id.result);

  view_suggest = (TextView) findViewById(R.id.suggest);

 }

 // Listen for button clicks

 private void setListeners() {

  calcbutton.setOnClickListener(calcBMI);

 }

 private Button.OnClickListener calcBMI = new Button.OnClickListener() {

  public void onClick(View v) {

   DecimalFormat nf = new DecimalFormat("0.0");

   double height = Double.parseDouble(field_height.getText().toString()) / 100;

   double weight = Double.parseDouble(field_weight.getText().toString());

   double BMI = weight / (height * height);

   // Present result

   view_result.setText(getText(R.string.bmi_result) + nf.format(BMI));

   // Give health advice

   if (BMI > 25) {

    view_suggest.setText(R.string.advice_heavy);

   } else if (BMI < 20) {

    view_suggest.setText(R.string.advice_light);

   } else {

    view_suggest.setText(R.string.advice_average);

   }

  }

 };

}

 

***说说mvc模式的原理,它在android中的运用

 

答:android的官方建议应用程序的开发采用mvc模式。何谓mvc?

 

mvc是model,view,controller的缩写,mvc包含三个部分:

l模型(model)对象:是应用程序的主体部分,所有的业务逻辑都应该写在该层。

2视图(view)对象:是应用程序中负责生成用户界面的部分。也是在整个mvc架构中用户唯一可以看到的一层,接收用户的输入,显示处理结果。

 

3控制器(control)对象:是根据用户的输入,控制用户界面数据显示及更新model对象状态的部分,控制器更重要的一种导航功能,想用用户出发的相关事件,交给m哦得了处理。

 

android鼓励弱耦合和组件的重用,在android中mvc的具体体现如下:

 

    1)视图层(view):一般采用xml文件进行界面的描述,使用的时候可以非常方便的引入,当然,如何你对android了解的比较的多了话,就一定 可以想到在android中也可以使用javascript+html等的方式作为view层,当然这里需要进行java和javascript之间的通 信,幸运的是,android提供了它们之间非常方便的通信实现。

 

  2)控制层(controller):android的控制层的重 任通常落在了众多的acitvity的肩上,这句话也就暗含了不要在acitivity中写代码,要通过activity交割model业务逻辑层处理, 这样做的另外一个原因是android中的acitivity的响应时间是5s,如果耗时的操作放在这里,程序就很容易被回收掉。

 

 3)模型层(model):对数据库的操作、对网络等的操作都应该在model里面处理,当然对业务计算等操作也是必须放在的该层的。

 

***在android中mvc的具体体现

Android 的官方建议应用程序的开发采用MVC 模式。何谓MVC?先看看下图

 

MVC 是Model,View,Controller 的缩写,从上图可以看出MVC 包含三个部分:

 

1)模型(Model)对象:是应用程序的主体部分,所有的业务逻辑都应该写在该

 

层。

 

2)视图(View)对象:是应用程序中负责生成用户界面的部分。也是在整个

 

MVC 架构中用户唯一可以看到的一层,接收用户的输入,显示处理结果。

 

3)控制器(Control)对象:是根据用户的输入,控制用户界面数据显示及更新

 

Model 对象状态的部分,控制器更重要的一种导航功能,响应用户出发的相

 

关事件,交给M 层处理。

 

Android 鼓励弱耦合和组件的重用,在Android 中MVC 的具体体现如下

 

       1)视图层(view):一般采用xml文件进行界面的描述,使用的时候可以非常方便的引入,当然,如何你对android了解的比较多的话,就一定可以想到在android中也可以使用javascript+html等的方式作为view层,当然这里需要进行java和javascript之间的通信,幸运的是,android提供了它们之间非常方便的通信实现。

 

  2)控制层(controller):android的控制层的重任通常落在了众多的acitvity的肩上,这句话也就暗含了不要在acitivity中写代码,要通过activity交给model层做业务逻辑的处理, 这样做的另外一个原因是android中的acitivity的响应时间是5s,如果耗时的操作放在这里,程序就很容易被回收掉。

 

  3)模型层(model):对数据库的操作、对网络等的操作都应该在model里面处理,当然对业务计算等操作也是必须放在的该层的。




************MVC

***说说mvc模式的原理,它在android中的运用。

MVC英文即Model-View-Controller,即把一个应用的输入、处理、输出流程按照Model、View、Controller的方式进行分离,这样一个应用被分成三个层——模型层、视图层、控制层。

Android中界面部分也采用了当前比较流行的MVC框架,在Android中M就是应用程序中二进制的数据,V就是用户的界面。Android的界面直接采用XML文件保存的,界面开发变的很方便。在Android中C也是很简单的,一个Activity可以有多个界面,只需要将视图的ID传递到setContentView(),就指定了以哪个视图模型显示数据。

 

在Android SDK中的数据绑定,也都是采用了与MVC框架类似的方法来显示数据。在控制层上将数据按照视图模型的要求(也就是Android SDK中的Adapter)封装就可以直接在视图模型上显示了,从而实现了数据绑定。比如显示Cursor中所有数据的ListActivity,其视图层就是一个ListView,将数据封装为ListAdapter,并传递给ListView,数据就在ListView中显示。

 

***利用mvc的模式重构代码

1) 重构前的代码Bmi.java:

package com.demo.android.bmi;

import java.text.DecimalFormat;

import android.app.Activity;

import android.os.Bundle;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.EditText;

import android.widget.TextView;

public class Bmi extends Activity {

 /** Called when the activity is first created. */

 @Override

 public void onCreate(Bundle savedInstanceState) {

  super.onCreate(savedInstanceState);

  setContentView(R.layout.main);

  // Listen for button clicks

  Button button = (Button) findViewById(R.id.submit);

  button.setOnClickListener(calcBMI);

 }

 private OnClickListener calcBMI = new OnClickListener() {

  @Override

  public void onClick(View v) {

   DecimalFormat nf = new DecimalFormat("0.00");

   EditText fieldheight = (EditText) findViewById(R.id.height);

   EditText fieldweight = (EditText) findViewById(R.id.weight);

   double height = Double.parseDouble(fieldheight.getText().toString()) / 100;

   double weight = Double.parseDouble(fieldweight.getText().toString());

   double BMI = weight / (height * height);

   TextView result = (TextView) findViewById(R.id.result);

   result.setText("Your BMI is " + nf.format(BMI));

   // Give health advice

   TextView fieldsuggest = (TextView) findViewById(R.id.suggest);

   if (BMI > 25) {

    fieldsuggest.setText(R.string.advice_heavy);

   } else if (BMI < 20) {

    fieldsuggest.setText(R.string.advice_light);

   } else {

    fieldsuggest.setText(R.string.advice_average);

   }

  }

 };

}

 

 

Step1:抽取所有界面元件的声明和定义,整合到单独一个函数findViews()中;

// 声明 view 

private Button button_calc;

private EditText field_height;

private EditText field_weight;

private TextView view_result;

private TextView view_suggest;

// 定义

private void findViews() {

 button_calc = (Button) findViewById(R.id.submit);

 field_height = (EditText) findViewById(R.id.height);

 field_weight = (EditText) findViewById(R.id.weight);

 view_result = (TextView) findViewById(R.id.result);

 view_suggest = (TextView) findViewById(R.id.suggest);

}

此部分即是MVC中的V:View视图。 

 

Step2:抽取程序的逻辑(即界面元件的处理逻辑),整合到函数setListensers()中;

//Listen for button clicks

private void setListensers() {

    button_calc.setOnClickListener(calcBMI);

}

此部分即是MVC中的C:Controller控制器。

接着,onCreate()就显得非常简洁、明了了:

public void onCreate(Bundle savedInstanceState) {

 super.onCreate(savedInstanceState);

 setContentView(R.layout.main);

 findViews();

 setListensers();

}

 

Step3:修改按钮监听器calcBMI中相应的部分(主要是变量已经在视图部分定义了);

private OnClickListener calcBMI = new OnClickListener() {

 @Override

 public void onClick(View v) {

  DecimalFormat nf = new DecimalFormat("0.00");

  double height = Double.parseDouble(field_height.getText().toString()) / 100;

  double weight = Double.parseDouble(field_weight.getText().toString());

  double BMI = weight / (height * height);

  // Present result

  view_result.setText("Your BMI is " + nf.format(BMI));

  // Give health advice

  if (BMI > 25) {

   view_suggest.setText(R.string.advice_heavy);

  } else if (BMI < 20) {

   view_suggest.setText(R.string.advice_light);

  } else {

   view_suggest.setText(R.string.advice_average);

  }

 }

};

 

总之,此重构的目的无非是使程序的脉络更加清晰,即让人一眼望去,就能很容易地分辨出界面(View)应该写在哪里,程序逻辑(Controller)应该写在哪里,最终使维护和扩展代码变得更加容易!

其实,重构很简单,通读代码,感觉哪边不太爽,就改那边吧!(我目前的感受)

一个良好的代码应该是能让人感到舒服的!

 

2)     重构后的代码Bmi.java:

package com.demo.android.bmi;

import java.text.DecimalFormat;

import android.app.Activity;

import android.os.Bundle;

import android.view.View;

import android.widget.Button;

import android.widget.EditText;

import android.widget.TextView;

public class Bmi extends Activity {

 private Button button_calc;

 private EditText field_height;

 private EditText field_weight;

 private TextView view_result;

 private TextView view_suggest;

 /** Called when the activity is first created. */

 @Override

 public void onCreate(Bundle savedInstanceState) {

  super.onCreate(savedInstanceState);

  setContentView(R.layout.main);

  findViews();

  setListensers();

 }

 // 定义

 private void findViews() {

  button_calc = (Button) findViewById(R.id.submit);

  field_height = (EditText) findViewById(R.id.height);

  field_weight = (EditText) findViewById(R.id.weight);

  view_result = (TextView) findViewById(R.id.result);

  view_suggest = (TextView) findViewById(R.id.suggest);

 }

 // Listen for button clicks

 private void setListeners() {

  calcbutton.setOnClickListener(calcBMI);

 }

 private Button.OnClickListener calcBMI = new Button.OnClickListener() {

  public void onClick(View v) {

   DecimalFormat nf = new DecimalFormat("0.0");

   double height = Double.parseDouble(field_height.getText().toString()) / 100;

   double weight = Double.parseDouble(field_weight.getText().toString());

   double BMI = weight / (height * height);

   // Present result

   view_result.setText(getText(R.string.bmi_result) + nf.format(BMI));

   // Give health advice

   if (BMI > 25) {

    view_suggest.setText(R.string.advice_heavy);

   } else if (BMI < 20) {

    view_suggest.setText(R.string.advice_light);

   } else {

    view_suggest.setText(R.string.advice_average);

   }

  }

 };

}

 

***说说mvc模式的原理,它在android中的运用

 

答:android的官方建议应用程序的开发采用mvc模式。何谓mvc?

 

mvc是model,view,controller的缩写,mvc包含三个部分:

l模型(model)对象:是应用程序的主体部分,所有的业务逻辑都应该写在该层。

2视图(view)对象:是应用程序中负责生成用户界面的部分。也是在整个mvc架构中用户唯一可以看到的一层,接收用户的输入,显示处理结果。

 

3控制器(control)对象:是根据用户的输入,控制用户界面数据显示及更新model对象状态的部分,控制器更重要的一种导航功能,想用用户出发的相关事件,交给m哦得了处理。

 

android鼓励弱耦合和组件的重用,在android中mvc的具体体现如下:

 

    1)视图层(view):一般采用xml文件进行界面的描述,使用的时候可以非常方便的引入,当然,如何你对android了解的比较的多了话,就一定 可以想到在android中也可以使用javascript+html等的方式作为view层,当然这里需要进行java和javascript之间的通 信,幸运的是,android提供了它们之间非常方便的通信实现。

 

  2)控制层(controller):android的控制层的重 任通常落在了众多的acitvity的肩上,这句话也就暗含了不要在acitivity中写代码,要通过activity交割model业务逻辑层处理, 这样做的另外一个原因是android中的acitivity的响应时间是5s,如果耗时的操作放在这里,程序就很容易被回收掉。

 

 3)模型层(model):对数据库的操作、对网络等的操作都应该在model里面处理,当然对业务计算等操作也是必须放在的该层的。

 

***在android中mvc的具体体现

Android 的官方建议应用程序的开发采用MVC 模式。何谓MVC?先看看下图

 

MVC 是Model,View,Controller 的缩写,从上图可以看出MVC 包含三个部分:

 

1)模型(Model)对象:是应用程序的主体部分,所有的业务逻辑都应该写在该

 

层。

 

2)视图(View)对象:是应用程序中负责生成用户界面的部分。也是在整个

 

MVC 架构中用户唯一可以看到的一层,接收用户的输入,显示处理结果。

 

3)控制器(Control)对象:是根据用户的输入,控制用户界面数据显示及更新

 

Model 对象状态的部分,控制器更重要的一种导航功能,响应用户出发的相

 

关事件,交给M 层处理。

 

Android 鼓励弱耦合和组件的重用,在Android 中MVC 的具体体现如下

 

       1)视图层(view):一般采用xml文件进行界面的描述,使用的时候可以非常方便的引入,当然,如何你对android了解的比较多的话,就一定可以想到在android中也可以使用javascript+html等的方式作为view层,当然这里需要进行java和javascript之间的通信,幸运的是,android提供了它们之间非常方便的通信实现。

 

  2)控制层(controller):android的控制层的重任通常落在了众多的acitvity的肩上,这句话也就暗含了不要在acitivity中写代码,要通过activity交给model层做业务逻辑的处理, 这样做的另外一个原因是android中的acitivity的响应时间是5s,如果耗时的操作放在这里,程序就很容易被回收掉。

 

  3)模型层(model):对数据库的操作、对网络等的操作都应该在model里面处理,当然对业务计算等操作也是必须放在的该层的。



***********进程

***android中线程与线程,进程与进程之间如何通信

1、一个 Android 程序开始运行时,会单独启动一个Process。

   默认情况下,所有这个程序中的Activity或者Service都会跑在这个Process。

   默认情况下,一个Android程序也只有一个Process,但一个Process下却可以有许多个Thread。

 

2、一个 Android 程序开始运行时,就有一个主线程Main Thread被创建。该线程主要负责UI界面的显示、更新和控件交互,所以又叫UI Thread。

   一个Android程序创建之初,一个Process呈现的是单线程模型--即Main Thread,所有的任务都在一个线程中运行。所以,Main Thread所调用的每一个函数,其耗时应该越短越好。而对于比较费时的工作,应该设法交给子线程去做,以避免阻塞主线程(主线程被阻塞,会导致程序假死 现象)。 

 

3、Android单线程模型:Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行。如果在子线程中直接修改UI,会导致异常。

 

***AIDL的全称是什么?如何工作?能处理哪些类型的数据?

    AIDL全称Android Interface Definition Language(Android接口描述语言)是一种借口描述语言; 编译器可以通过aidl文件生成一段代码,通过预先定义的接口达到两个进程内部通信进程跨界对象访问的目的.AIDL的IPC的机制和COM或CORBA类似, 是基于接口的,但它是轻量级的。它使用代理类在客户端和实现层间传递值. 如果要使用AIDL, 需要完成2件事情: 

1. 引入AIDL的相关类.; 

2. 调用aidl产生的class.理论上, 参数可以传递基本数据类型和String, 还有就是Bundle的派生类, 不过在Eclipse中,目前的ADT不支持Bundle做为参数,

 

具体实现步骤如下:

1、创建AIDL文件, 在这个文件里面定义接口, 该接口定义了可供客户端访问的方法和属性。

 

2、编译AIDL文件, 用Ant的话, 可能需要手动, 使用Eclipse plugin的话,可以根据adil文件自动生产java文件并编译, 不需要人为介入.

 

3、在Java文件中, 实现AIDL中定义的接口. 编译器会根据AIDL接口, 产生一个JAVA接口。这个接口有一个名为Stub的内部抽象类,它继承扩展了接口并实现了远程调用需要的几个方法。接下来就需要自己去实现自定义的几个接口了.

4、向客户端提供接口ITaskBinder, 如果写的是service,扩展该Service并重载onBind ()方法来返回一个实现上述接口的类的实例。

5、在服务器端回调客户端的函数. 前提是当客户端获取的IBinder接口的时候,要去注册回调函数, 只有这样, 服务器端才知道该调用那些函数

 

AIDL语法很简单,可以用来声明一个带一个或多个方法的接口,也可以传递参数和返回值。 由于远程调用的需要, 这些参数和返回值并不是任何类型.下面是些AIDL支持的数据类型:

 

1. 不需要import声明的简单Java编程语言类型(int,boolean等)

 

2. String, CharSequence不需要特殊声明

 

3. List, Map和Parcelables类型, 这些类型内所包含的数据成员也只能是简单数据类型, String等其他比支持的类型.

 

(另外: 我没尝试Parcelables, 在Eclipse+ADT下编译不过, 或许以后会有所支持).

 

实现接口时有几个原则:

 

.抛出的异常不要返回给调用者. 跨进程抛异常处理是不可取的.

 

.IPC调用是同步的。如果你知道一个IPC服务需要超过几毫秒的时间才能完成地话,你应该避免在Activity的主线程中调用。也就是IPC调用会挂起应用程序导致界面失去响应. 这种情况应该考虑单起一个线程来处理.

 

.不能在AIDL接口中声明静态属性。

 

IPC的调用步骤:

 

1. 声明一个接口类型的变量,该接口类型在.aidl文件中定义。

 

2. 实现ServiceConnection。

 

3. 调用ApplicationContext.bindService(),并在ServiceConnection实现中进行传递.

 

4. 在ServiceConnection.onServiceConnected()实现中,你会接收一个IBinder实例(被调用的Service). 调用

 

YourInterfaceName.Stub.asInterface((IBinder)service)将参数转换为YourInterface类型。

 

5. 调用接口中定义的方法。你总要检测到DeadObjectException异常,该异常在连接断开时被抛出。它只会被远程方法抛出。

 

6. 断开连接,调用接口实例中的ApplicationContext.unbindService()

 

***AIDL的全称是什么?如何工作?

Android interface definition language (android接口定义语言) , 

用来跨进程的访问方法, 

访问远程的服务的方法. 如何工作 day7 queryStudent .  

手机卫士 Itelephony 接口挂断电话. 

 

***AIDL的全称是什么?如何工作?能处理哪些类型的数据?AIDL的英文全称是Android Interface Define Language

 

  当A进程要去调用B进程中的service时,并实现通信,我们通常都是通过AIDL来操作的

  A工程:

  首先我们在net.blogjava.mobile.aidlservice包中创建一个RemoteService.aidl文件,在里面我们自定义一个接口,含有方法get。ADT插件会在gen目录下自动生成一个RemoteService.java文件,该类中含有一个名为RemoteService.stub的内部类,该内部类中含有aidl文件接口的get方法。

  说明一:aidl文件的位置不固定,可以任意

  然后定义自己的MyService类,在MyService类中自定义一个内部类去继承RemoteService.stub这个内部类,实现get方法。在onBind方法中返回这个内部类的对象,系统会自动将这个对象封装成IBinder对象,传递给他的调用者。

  其次需要在AndroidManifest.xml文件中配置MyService类,代码如下:

  为什么要指定调用AIDL服务的ID,就是要告诉外界MyService这个类能够被别的进程访问,只要别的进程知道这个ID,正是有了这个ID,B工程才能找到A工程实现通信。

  说明:AIDL并不需要权限

 

  B工程:

  首先我们要将A工程中生成的RemoteService.java文件拷贝到B工程中,在bindService方法中绑定aidl服务

  绑定AIDL服务就是将RemoteService的ID作为intent的action参数。

  说明:如果我们单独将RemoteService.aidl文件放在一个包里,那个在我们将gen目录下的该包拷贝到B工程中。如果我们将RemoteService.aidl文件和我们的其他类存放在一起,那么我们在B工程中就要建立相应的包,以保证RmoteService.java文件的报名正确,我们不能修改RemoteService.java文件

  bindService(newInten("net.blogjava.mobile.aidlservice.RemoteService"),serviceConnection, Context.BIND_AUTO_CREATE);

  ServiceConnection的onServiceConnected(ComponentName name, IBinderservice)方法中的service参数就是A工程中MyService类中继承了RemoteService.stub类的内部类的对象。

 

***Linux中跨进程通信的几种方式 。

linux编程 

# 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。

# 有名管道 (named pipe) : 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。

# 信号量( semophore ) : 信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。

# 消息队列( message queue ) : 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。

# 信号 ( sinal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。

# 共享内存( shared memory ) :共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信。

# 套接字( socket ) : 套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信。

 

***AIDL的全称是什么?如何工作?能处理哪些类型的数据?

 

答:AIDL(AndroidInterface Definition Language)android接口描述语言

 

***谈谈Android的IPC机制

 

答:IPC 是内部进程通信的简称,是共享"命名管道"的资源。Android中的IPC机制是为了让Activity和Service之间可以随时的进行交互,故在 Android中该机制,只适用于Activity和Service之间的通信,类似于远程方法调用,类似于C/S模式的访问。通过定义AIDL接口文件 来定义IPC接口。Servier端实现IPC接口,Client端调用IPC接口本地代理。

 

*** 谈谈Android的IPC(进程间通信)机制 

         IPC是内部进程通信的简称, 是共享"命名管道"的资源。Android中的IPC机制是为了让Activity和Service之间可以随时的进行交互,故在Android中该机制,只适用于Activity和Service之间的通信,类似于远程方法调用,类似于C/S模式的访问。通过定义AIDL接口文件来定义IPC接口。Servier端实现IPC接口,Client端调用IPC接口本地代理。



***********线程

 ***对android主线程的运用和理解。

    主ui线程不能执行耗时的操作,

 

***Service和Activity在同一个线程吗?

    默认情况同一线程 main主线程 ui线程


***handler机制的原理

 andriod提供了Handler 和 Looper 来满足线程间的通信。Handler先进先出原则。Looper类用来管理特定线程内对象之间的消息交换(MessageExchange)。

  1)Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的MessageQueue(消息队列)。

  2)Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到MessageQueue里;或者接收Looper从Message Queue取出)所送来的消息。

  3) Message Queue(消息队列):用来存放线程放入的消息。

  4)线程:UIthread 通常就是main thread,而Android启动程序时会替它建立一个MessageQueue。

 

*** 请解释下在单线程模型中Message、Handler、Message Queue、Looper之间的关系。

Handler获取当前线程中的looper对象,looper用来从存有Message的Message Queue里取出message,再由Handler进行message的分发和处理。

#Handler简介:

一个Handler允许你发送和处理Message和Runable对象,这些对象和一个线程的MessageQueue相关联。每一个线程实例和一个单独的线程以及该线程的MessageQueue相关联。当你创建一个新的Handler时,它就和创建它的线程绑定在一起了。这里,线程我们也可以理解为线程的MessageQueue。从这一点上来看,Handler把Message和Runable对象传递给MessageQueue,而且在这些对象离开MessageQueue时,Handler负责执行他们。

Handler有两个主要的用途:

(1)确定在将来的某个时间点执行一个或者一些Message和Runnable对象。

(2)在其他线程(不是Handler绑定线程)中排入一些要执行的动作。

Scheduling Message,即(1),可以通过以下方法完成:

post(Runnable):Runnable在handler绑定的线程上执行,也就是说不创建新线程。

postAtTime(Runnable,long):

postDelayed(Runnable,long):

sendEmptyMessage(int):

sendMessage(Message):

sendMessageAtTime(Message,long):

sendMessageDelayed(Message,long):

post这个动作让你把Runnable对象排入MessageQueue,MessageQueue受到这些消息的时候执行他们,当然以一定的排序。sendMessage这个动作允许你把Message对象排成队列,这些Message对象包含一些信息,Handler的hanlerMessage(Message)会处理这些Message.当然,handlerMessage(Message)必须由Handler的子类来重写。这是编程人员需要作的事。

当posting或者sending到一个Hanler时,你可以有三种行为:当MessageQueue准备好就处理,定义一个延迟时间,定义一个精确的时间去处理。后两者允许你实现timeout,tick,和基于时间的行为。

当你的应用创建一个新的进程时,主线程(也就是UI线程)自带一个MessageQueue,这个MessageQueue管理顶层的应用对象(像activities,broadcast receivers等)和主线程创建的窗体。你可以创建自己的线程,并通过一个Handler和主线程进行通信。这和之前一样,通过post和sendmessage来完成,差别在于在哪一个线程中执行这么方法。在恰当的时候,给定的Runnable和Message将在Handler的MessageQueue中被Scheduled。

 

#Message简介:

Message类就是定义了一个信息,这个信息中包含一个描述符和任意的数据对象,这个信息被用来传递给Handler.Message对象提供额外的两个int域和一个Object域,这可以让你在大多数情况下不用作分配的动作。

尽管Message的构造函数是public的,但是获取Message实例的最好方法是调用Message.obtain(),或者Handler.obtainMessage()方法,这些方法会从回收对象池中获取一个。

 

#MessageQueue简介:

这是一个包含message列表的底层类。Looper负责分发这些message。Messages并不是直接加到一个MessageQueue中,而是通过MessageQueue.IdleHandler关联到Looper。

你可以通过Looper.myQueue()从当前线程中获取MessageQueue。

 

#Looper简介:

Looper类被用来执行一个线程中的message循环。默认情况,没有一个消息循环关联到线程。在线程中调用prepare()创建一个Looper,然后用loop()来处理messages,直到循环终止。

大多数和message loop的交互是通过Handler。

下面是一个典型的带有Looper的线程实现。

  class LooperThread extends Thread {

      public Handler mHandler;

      

      public void run() {

          Looper.prepare();

          

          mHandler = new Handler() {

              public void handleMessage(Message msg) {

                  // process incoming messages here

              }

          };

          

          Looper.loop();

      }

  }

 

***请解释下在单线程模型中Message、Handler、Message Queue、Looper之间的关系。

 

答:

    简单的说,Handler获取当前线程中的looper对象,looper用来从存放Message的MessageQueue中取出Message,再有Handler进行Message的分发和处理.


Message Queue(消息队列):用来存放通过Handler发布的消息,通常附属于某一个创建它的线程,可以通过Looper.myQueue()得到当前线程的消息队列

Handler:可以发布或者处理一个消息或者操作一个Runnable,通过Handler发布消息,消息将只会发送到与它关联的消息队列,然也只能处理该消息队列中的消息

Looper:是Handler和消息队列之间通讯桥梁,程序组件首先通过Handler把消息传递给Looper,Looper把消息放入队列。Looper也把消息队列里的消息广播给所有的

Handler:Handler接受到消息后调用handleMessage进行处理

Message:消息的类型,在Handler类中的handleMessage方法中得到单个的消息进行处理


在单线程模型下,为了线程通信问题,Android设计了一个Message Queue(消息队列), 线程间可以通过该Message Queue并结合Handler和Looper组件进行信息交换。下面将对它们进行分别介绍:

1. Message

    Message消息,理解为线程间交流的信息,处理数据后台线程需要更新UI,则发送Message内含一些数据给UI线程。

 

2. Handler

    Handler处理者,是Message的主要处理者,负责Message的发送,Message内容的执行处理。后台线程就是通过传进来的 Handler对象引用来sendMessage(Message)。而使用Handler,需要implement 该类的 handleMessage(Message)方法,它是处理这些Message的操作内容,例如Update UI。通常需要子类化Handler来实现handleMessage方法。

 

3. Message Queue

    Message Queue消息队列,用来存放通过Handler发布的消息,按照先进先出执行。

    每个message queue都会有一个对应的Handler。Handler会向messagequeue通过两种方法发送消息:sendMessage或post。这两种消息都会插在message queue队尾并按先进先出执行。但通过这两种方法发送的消息执行的方式略有不同:通过sendMessage发送的是一个message对象,会被 Handler的handleMessage()函数处理;而通过post方法发送的是一个runnable对象,则会自己执行。

 

4. Looper

    Looper是每条线程里的Message Queue的管家。Android没有Global的MessageQueue,而Android会自动替主线程(UI线程)建立Message Queue,但在子线程里并没有建立Message Queue。所以调用Looper.getMainLooper()得到的主线程的Looper不为NULL,但调用Looper.myLooper()得到当前线程的Looper就有可能为NULL。对于子线程使用Looper,API Doc提供了正确的使用方法:这个Message机制的大概流程:

    1. 在Looper.loop()方法运行开始后,循环地按照接收顺序取出Message Queue里面的非NULL的Message。


    2. 一开始Message Queue里面的Message都是NULL的。当Handler.sendMessage(Message)到Message Queue,该函数里面设置了那个Message对象的target属性是当前的Handler对象。随后Looper取出了那个Message,则调用 该Message的target指向的Hander的dispatchMessage函数对Message进行处理。在dispatchMessage方法里,如何处理Message则由用户指定,三个判断,优先级从高到低:

    1) Message里面的Callback,一个实现了Runnable接口的对象,其中run函数做处理工作;

    2) Handler里面的mCallback指向的一个实现了Callback接口的对象,由其handleMessage进行处理;

    3) 处理消息Handler对象对应的类继承并实现了其中handleMessage函数,通过这个实现的handleMessage函数处理消息。

    由此可见,我们实现的handleMessage方法是优先级最低的!


    3. Handler处理完该Message (updateUI) 后,Looper则设置该Message为NULL,以便回收!

     在网上有很多文章讲述主线程和其他子线程如何交互,传送信息,最终谁来执行处理信息之类的,个人理解是最简单的方法——判断Handler对象里面的Looper对象是属于哪条线程的,则由该线程来执行!

    1. 当Handler对象的构造函数的参数为空,则为当前所在线程的Looper;

    2. Looper.getMainLooper()得到的是主线程的Looper对象,Looper.myLooper()得到的是当前线程的Looper对象。




**********UI

***谈谈UI中, Padding和Margin有什么区别?

 Padding 文字对边框, margin是控件与控件之间的距离 

 

*** Android UI中的View如何刷新。

在主线程中拿到view调用Invalide()方法,查看画画板里面更新imageview的方法

在子线程里面可以通过postInvalide()方法;

 

***ListView如何提高其效率?

复用convertview , 历史的view对象 

异步加载数据,  分页加载数据, onscallLinster();

Static class ViewHolder 

使用静态的view对象 避免创建过多的view.

把下载后的数据缓存到数据库里  

客户端和服务器协同作战 .

Http 请求 

If-modify-since : 检查数据是否更新  1.html 2001年  302 拿缓存

 

***android view的刷新

 

答:android中对View的更新有很多种方式,使用时要区分不同的应用场合。我感觉最要紧的是分清:多线程和双缓冲的使用情况。

 

    1).不使用多线程和双缓冲

   这种情况最简单了,一般只是希望在View发生改变时对UI进行重绘。你只需在Activity中显式地调用View对象中的invalidate()方法即可。系统会自动调用 View的onDraw()方法。

 

    2).使用多线程和不使用双缓冲

    这种情况需要开启新的线程,新开的线程就不好访问View对象了。强行访问的话会 报:android.view.ViewRoot$CalledFromWrongThreadException:Only the originalthread that created a view hierarchy can touch its views.

 

    这时候你需要创建一个继承了android.os.Handler的子类,并重写handleMessage(Messagemsg)方法。 android.os.Handler是能发送和处理消息的,你需要在Activity中发出更新UI的消息,然后再你的Handler(可以使用匿名内 部类)中处理消息(因为匿名内部类可以访问父类变量,你可以直接调用View对象中的invalidate()方法 )。也就是说:在新线程创建并发送一个Message,然后再主线程中捕获、处理该消息。

 

    3).使用多线程和双缓冲

    Android中SurfaceView是View的子类,她同时也实现了双缓冲。你可以定义一个她的子类并实现 SurfaceHolder.Callback接口。由于实现SurfaceHolder.Callback接口,新线程就不需要 android.os.Handler帮忙了。SurfaceHolder中lockCanvas()方法可以锁定画布,绘制玩新的图像后调用 unlockCanvasAndPost(canvas)解锁(显示),还是比较方便得。

 

 

***android view,surfaceview,glsurfaceview的区别

答:

    SurfaceView是从View基类中派生出来的显示类,直接子类有GLSurfaceView和VideoView,可以看出GL和视频播放以及Camera摄像头一般均使用SurfaceView

SurfaceView和View最本质的区别在于,surfaceView是在一个新起的单独线程中可以重新绘制画面而View必须在UI的主线程中更新画面。

那么在UI的主线程中更新画面 可能会引发问题,比如你更新画面的时间过长,那么你的主UI线程会被你正在画的函数阻塞。那么将无法响应按键,触屏等消息。

当使用surfaceView 由于是在新的线程中更新画面所以不会阻塞你的UI主线程。但这也带来了另外一个问题,就是事件同步。比如你触屏了一下,你需要surfaceView中 thread处理,一般就需要有一个event queue的设计来保存touch event,这会稍稍复杂一点,因为涉及到线程同步。

 

所以基于以上,根据游戏特点,一般分成两类。

 

1)被动更新画面的。比如棋类,这种用view就好了。因为画面的更新是依赖于 onTouch 来更新,可以直接使用 invalidate。 因为这种情况下,这一次Touch和下一次的Touch需要的时间比较长些,不会产生影响。

 

2)主动更新。比如一个人在一直跑动。这就需要一个单独的thread不停的重绘人的状态,避免阻塞main UI thread。所以显然view不合适,需要surfaceView来控制。

 

***View, surfaceView, GLSurfaceView有什么区别

view是最基础的,必须在UI主线程内更新画面,速度较慢。

SurfaceView 是view的子类,类似使用双缓机制,在新的线程中更新画面所以刷新界面速度比view快

GLSurfaceView 是SurfaceView的子类,opengl 专用的。



*********contentprovider

***请介绍下ContentProvider是如何实现数据共享的。

      创建一个属于你自己的Content provider或者将你的数据添加到一个已经存在的Contentprovider中,前提是有相同数据类型并且有写入Content provider的限。

 

***请介绍下ContentProvider是如何实现数据共享的。

 把自己的数据通过uri的形式共享出去

android  系统下 不同程序 数据默认是不能共享访问 

  

 需要去实现一个类去继承ContentProvider

 public class PersonContentProvider extends ContentProvider{

 public boolean onCreate(){

  //..

 }

query(Uri, String[], String, String[], String)

insert(Uri, ContentValues)

update(Uri, ContentValues, String, String[])

delete(Uri, String, String[])

}

content:// 代表contentprovider 

技巧: 1.看urlmarcher. 

       2. 根据匹配码 查看增删改查的具体实现

 

***请介绍下Android的数据存储方式。

 1)文件  访问权限.  sdcard 

    <data>/<data>      context.openFileInput(name) 默认是私有的访问权限 

 

2)数据库 sqlite 

 

    SharedPreference  <data>/<data>/shared_preps   Context.modeprivate

 

3)网络  socket tcp udp , 

      http httpurlconnection 

      ftp的网络

 

***为什么要用ContentProvider?它和sql的实现上有什么差别?

 屏蔽数据存储的细节,对用户透明,用户只需要关心操作数据的uri就可以了,对应的参数 .

 不同app之间共享,操作数据

 但是contentprovider 还可以去增删改查本地文件. xml文件的读取,更改,

 网络数据读取更改

 Sql也有增删改查的方法.



*********Intent

***Android Intent的使用

在一个Android应用中,主要是由一些组件组成,(Activity,Service,ContentProvider,etc.)在这些组件之间的通讯中,由Intent协助完成。

 

正如网上一些人解析所说,Intent负责对应用中一次操作的动作、动作涉及数据、附加数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,将 Intent传递给调用的组件,并完成组件的调用。Intent在这里起着实现调用者与被调用者之间的解耦作用。

Intent传递过程中,要找到目标消费者(另一个Activity,IntentReceiver或Service),也就是Intent的响应者,有两种方法来匹配:

1,显示匹配(Explicit): 

 

[java] view plaincopyprint?

public TestB extents Activity  

{  

 .........  

};  

 public class Test extends Activity  

{  

     ......  

     public void switchActivity()  

     {  

            Intent i = new Intent(Test.this, TestB.class);  

            this.startActivity(i);  

     }  }  

 

 

代码简洁明了,执行了switchActivity()函数,就会马上跳转到名为TestB的Activity中。 

 

2,隐式匹配(Implicit):

   

  隐式匹配,首先要匹配Intent的几项值:Action, Category, Data/Type,Component

如果填写了Componet就是上例中的Test.class)这就形成了显示匹配。所以此部分只讲前几种匹配。匹配规则为最大匹配规则,

 

1,如果你填写了Action,如果有一个程序的Manifest.xml中的某一个Activity的IntentFilter段中定义了包含了相同的 Action那么这个Intent就与这个目标Action匹配,如果这个Filter段中没有定义Type,Category,那么这个 Activity就匹配了。但是如果手机中有两个以上的程序匹配,那么就会弹出一个对话可框来提示说明。

Action的值在Android中有很多预定义,如果你想直接转到你自己定义的Intent接收者,你可以在接收者的IntentFilter中加入一个自定义的Action值(同时要设定Category值为"android.intent.category.DEFAULT"),在你的Intent 中设定该值为Intent的Action,就直接能跳转到你自己的Intent接收者中。因为这个Action在系统中是唯一的。

2,data/type,你可以用Uri来做为data,比如Uri uri = Uri.parse(http://www.google.com );

Intent i = new Intent(Intent.ACTION_VIEW,uri);手机的Intent分发过程中,会根据http://www.google.com 的scheme判断出数据类型type

手机的Brower则能匹配它,在Brower的Manifest.xml中的IntenFilter中首先有ACTION_VIEW Action,也能处理http:的type,

 

3,至于分类Category,一般不要去在Intent中设置它,如果你写Intent的接收者,就在Manifest.xml的Activity的 IntentFilter中包含android.category.DEFAULT,这样所有不设置 Category(Intent.addCategory(String c);)的Intent都会与这个Category匹配。

 

4,extras(附加信息),是其它所有附加信息的集合。使用extras可以为组件提供扩展信息,比如,如果要执行“发送电子邮件”这个动作,可以将电子邮件的标题、正文等保存在extras里,传给电子邮件发送组件。 

 

 

***请描述一下Intent 和 Intent Filter

 Android 中通过 Intent 对象来表示一条消息,一个 Intent 对象不仅包含有这个消息的目的地,还可以包含消息的内容,这好比一封 Email,其中不仅应该包含收件地址,还可以包含具体的内容。对于一个 Intent 对象,消息“目的地”是必须的,而内容则是可选项。

通过Intent 可以实现各种系统组件的调用与激活.  

Intent filter: 可以理解为邮局或者是一个信笺的分拣系统…

这个分拣系统通过3个参数来识别

Action: 动作    view 

Data: 数据uri   uri 

Category : 而外的附加信息 

Action 匹配

Action 是一个用户定义的字符串,用于描述一个 Android 应用程序组件,一个 Intent Filter 可以包含多个 Action。在 AndroidManifest.xml 的 Activity 定义时可以在其 <intent-filter >节点指定一个 Action 列表用于标示 Activity 所能接受的“动作”,例如:

 <intent-filter > 

 <action android:name="android.intent.action.MAIN" /> 

 <action android:name="cn.itcast.action" /> 

……

 </intent-filter>

如果我们在启动一个 Activity 时使用这样的 Intent 对象:

 Intent intent =new Intent(); 

 intent.setAction("cn.itcast.action");

那么所有的 Action 列表中包含了“cn.itcast”的 Activity 都将会匹配成功。

Android 预定义了一系列的 Action 分别表示特定的系统动作。这些 Action 通过常量的方式定义在 android.content. Intent中,以“ACTION_”开头。我们可以在 Android 提供的文档中找到它们的详细说明。

URI 数据匹配

一个 Intent 可以通过 URI 携带外部数据给目标组件。在 <intent-filter >节点中,通过 <data/>节点匹配外部数据。

mimeType 属性指定携带外部数据的数据类型,scheme 指定协议,host、port、path 指定数据的位置、端口、和路径。如下:

 <data android:mimeType="mimeType" android:scheme="scheme" 

 android:host="host" android:port="port" android:path="path"/> 

电话的uri   tel: 12345 

     http://www.baidu.com

自己定义的uri  itcast://cn.itcast/person/10

如果在 Intent Filter 中指定了这些属性,那么只有所有的属性都匹配成功时 URI 数据匹配才会成功。

Category 类别匹配

<intent-filter >节点中可以为组件定义一个 Category 类别列表,当 Intent 中包含这个列表的所有项目时 Category 类别匹配才会成功。

默认是DEFAULT

 

***Intent传递数据时,可以传递哪些类型数据?

 1.一般的基本数据类型  Intent .putextra() intent.getStringextra();

 2.数据的uri, intent.setData() intent.getData();

 

***系统上安装了多种浏览器,能否指定某浏览器访问指定页面?

   找到对应的浏览器的意图,传递数据URI , 激活这个意图

       Intent intent = new Intent();

       intent.setClassName(packageName, className);

       Intent.setdata(uri);



******Service

***service里面可以弹土司么

    可以

 

*** 如何启用Service,如何停用Service。

      Android中的service类似于windows中的service,service一般没有用户操作界面,它运行于系统中不容易被用户发觉,

  可以使用它开发如监控之类的程序。

  一.步骤

  1)继承Service类

  public class SMSService extends Service { }

 

  2)在AndroidManifest.xml文件中的节点里对服务进行配置:

 

  二.Context.startService()和Context.bindService

  服务不能自己运行,需要通过调用Context.startService()或Context.bindService()方法启动服务。这两个方法都可以启动Service,但是它们的使用场合有所不同。

  1.使用startService()方法启用服务,调用者与服务之间没有关连,即使调用者退出了,服务仍然运行。

  使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止。

 

  2.采用Context.startService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onStart()方法。

       如果调用startService()方法前服务已经被创建,多次调用startService()方法并不会导致多次创建服务,但会导致多次调用onStart()方法。

  采用startService()方法启动的服务,只能调用Context.stopService()方法结束服务,服务结束时会调用onDestroy()方法。

 

  3.采用Context.bindService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,

  接着调用onBind()方法。这个时候调用者和服务绑定在一起,调用者退出了,系统就会先调用服务的onUnbind()方法,

  接着调用onDestroy()方法。如果调用bindService()方法前服务已经被绑定,多次调用bindService()方法并不会

  导致多次创建服务及绑定(也就是说onCreate()和onBind()方法并不会被多次调用)。如果调用者希望与正在绑定的服务

  解除绑定,可以调用unbindService()方法,调用该方法也会导致系统调用服务的onUnbind()-->onDestroy()方法。

 

  三.Service的生命周期

  1.Service常用生命周期回调方法如下:

  onCreate() 该方法在服务被创建时调用,该方法只会被调用一次,无论调用多少次startService()或bindService()方法,

  服务也只被创建一次。 onDestroy()该方法在服务被终止时调用。

 

  2. Context.startService()启动Service有关的生命周期方法

  onStart() 只有采用Context.startService()方法启动服务时才会回调该方法。该方法在服务开始运行时被调用。

  多次调用startService()方法尽管不会多次创建服务,但onStart()方法会被多次调用。

 

  3. Context.bindService()启动Service有关的生命周期方法

  onBind()只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务绑定时被调用,

  当调用者与服务已经绑定,多次调用Context.bindService()方法并不会导致该方法被多次调用。

  onUnbind()只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务解除绑定时被调用。

  备注:

  1. 采用startService()启动服务

  Intent intent =new Intent(DemoActivity.this, DemoService.class);

  startService(intent);

 

  2.Context.bindService()启动

  Intent intent =new Intent(DemoActivity.this, DemoService.class);

  bindService(intent, conn, Context.BIND_AUTO_CREATE);

  //unbindService(conn);//解除绑定

 

***service是否在main thread中执行, service里面是否能执行耗时的操作?

默认情况,如果没有显示的指定service所运行的进程, Service和activity是运行在当前app所在进程的main thread(UI主线程)里面  

service里面不能执行耗时的操作(网络请求,拷贝数据库,大文件 ),在子线程中执行 new Thread(){}.start();

 

特殊情况 ,可以在清单文件配置 service 执行所在的进程 ,让service在另外的进程中执行                     

<service  android:process="cn.itcast.xxx"></service>

 

***什么是Service以及描述下它的生命周期。Service有哪些启动方法,有什么区别,怎样停用Service?

在Service的生命周期中,被回调的方法比Activity少一些,只有onCreate, onStart, onDestroy,

onBind和onUnbind。

通常有两种方式启动一个Service,他们对Service生命周期的影响是不一样的。

1 通过startService

    Service会经历 onCreate 到onStart,然后处于运行状态,stopService的时候调用onDestroy方法。

   如果是调用者自己直接退出而没有调用stopService的话,Service会一直在后台运行。

 

2 通过bindService   

    Service会运行onCreate,然后是调用onBind, 这个时候调用者和Service绑定在一起。调用者退出了,Srevice就会调用onUnbind->onDestroyed方法。

   所谓绑定在一起就共存亡了。调用者也可以通过调用unbindService方法来停止服务,这时候Srevice就会调用onUnbind->onDestroyed方法。

 

需要注意的是如果这几个方法交织在一起的话,会出现什么情况呢?

1)一个原则是Service的onCreate的方法只会被调用一次,就是你无论多少次的startService又bindService,Service只被创建一次。

 

2)如果先是bind了,那么start的时候就直接运行Service的onStart方法,如果先是start,那么bind的时候就直接运行onBind方法。

 

3)如果service运行期间调用了bindService,这时候再调用stopService的话,service是不会调用onDestroy方法的,service就stop不掉了,只能调用UnbindService, service就会被销毁

 

4)如果一个service通过startService 被start之后,多次调用startService 的话,service会多次调用onStart方法。多次调用stopService的话,service只会调用一次onDestroyed方法。

 

5)如果一个service通过bindService被start之后,多次调用bindService的话,service只会调用一次onBind方法。

多次调用unbindService的话会抛出异常。

 

***不用service,B页面为音乐播放,从A跳转到B,再返回,如何使音乐继续播放?

 这个问题问的很山寨.默认不做任何处理,B里面的音乐都能播放. 

遇到问题, 可以随机应变,灵活发挥,多考虑些细节,比如说这个题就可以这样说,说说你对startActivityForResult的理解()

A开启B的时候,用startActivityForResult()方法, B返回的时候把播放的状态信息返回给A ,A继续播放音乐.

 

***什么是IntentService?有何优点?

    普通的service ,默认运行在ui main 主线程

    Sdk给我们提供的方便的,带有异步处理的service类,异步处理的方法OnHandleIntent(),处理耗时的操作

 

***什么时候使用Service?

拥有service的进程具有较高的优先级

官方文档告诉我们,Android系统会尽量保持拥有service的进程运行,只要在该service已经被启动(start)或者客户端连接(bindService)到它。当内存不足时,需要保持,拥有service的进程具有较高的优先级。

1. 如果service正在调用onCreate,  onStartCommand或者onDestory方法,那么用于当前service的进程相当于前台进程以避免被killed。

2. 如果当前service已经被启动(start),拥有它的进程则比那些用户可见的进程优先级低一些,但是比那些不可见的进程更重要,这就意味着service一般不会被killed.

3. 如果客户端已经连接到service (bindService),那么拥有Service的进程则拥有最高的优先级,可以认为service是可见的。

4. 如果service可以使用startForeground(true)方法来将service设置为前台状态,那么系统就认为是对用户可见的,并不会在内存不足时killed。

 

如果有其他的应用组件作为Service,Activity等运行在相同的进程中,那么将会增加该进程的重要性。

 1.Service的特点可以让他在后台一直运行,可以在service里面创建线程去完成耗时的操作. 天气预报 widget TimerTask Timer 定期执行timertask

 2.Broadcast receiver捕获到一个事件之后,可以起一个service来完成一个耗时的操作.Broadcast receiver生命周期 和 响应时间很短 

 3.远程的service如果被启动起来,可以被多次bind, 但不会重新create.  索爱手机X10i的人脸识别的service可以被图库使用,可以被摄像机,照相机等程序使用.

 

***android的service的生命周期?哪个方法可以多次被调用:

 

答:

1)与采用Context.startService()方法启动服务有关的生命周期方法

onCreate() -> onStart() -> onDestroy()

 

onCreate()该方法在服务被创建时调用,该方法只会被调用一次,无论调用多少次startService()或bindService()方法,服务也只被创建一次。

onStart() 只有采用Context.startService()方法启动服务时才会回调该方法。该方法在服务开始运行时被调用。多次调用startService()方法尽管不会多次创建服务,但onStart() 方法会被多次调用。

onDestroy()该方法在服务被终止时调用。

 

2)与采用Context.bindService()方法启动服务有关的生命周期方法

onCreate() -> onBind() -> onUnbind() -> onDestroy()

 

onBind()只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务绑定时被调用,当调用者与服务已经绑定,多次调用Context.bindService()方法并不会导致该方法被多次调用。

onUnbind()只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务解除绑定时被调用。

如果先采用startService()方法启动服务,然后调用bindService()方法绑定到服务,再调用unbindService()方法解除绑定,最后调用bindService()方法再次绑定到服务,

 

触发的生命周期方法如下:

onCreate() ->onStart() ->onBind() ->onUnbind()[重载后的方法需返回true] ->onRebind()

 

***如何启用Service,如何停用Service 

Android中的服务和windows中的服务是类似的东西,服务一般没有用户操作界面,它运行于系统中不容易被用户发觉,可以使用它开发如监控之类的程序。服务的开发比较简单,如下:

 

第一步:继承Service类

 

public class SMSService extends Service {

 

}

 

第二步:在AndroidManifest.xml文件中的<application>节点里对服务进行配置:

 

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

 

服务不能自己运行,需要通过调用Context.startService()或Context.bindService()方法启动服务。这两个方法都可以启动Service,但是它们的使用场合有所不同。使用startService()方法启用服务,调用者与服务之间没有关连,即使调用者退出了,服务仍然运行。使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止,大有“不求同时生,必须同时死”的特点。

 

如果打算采用Context.startService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onStart()方法。如果调用startService()方法前服务已经被创建,多次调用startService()方法并不会导致多次创建服务,但会导致多次调用onStart()方法。采用startService()方法启动的服务,只能调用Context.stopService()方法结束服务,服务结束时会调用onDestroy()方法。

 

如果打算采用Context.bindService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onBind()方法。这个时候调用者和服务绑定在一起,调用者退出了,系统就会先调用服务的onUnbind()方法,接着调用onDestroy()方法。如果调用bindService()方法前服务已经被绑定,多次调用bindService()方法并不会导致多次创建服务及绑定(也就是说onCreate()和onBind()方法并不会被多次调用)。如果调用者希望与正在绑定的服务解除绑定,可以调用unbindService()方法,调用该方法也会导致系统调用服务的onUnbind()-->onDestroy()方法。

 

服务常用生命周期回调方法如下:

 

onCreate() 该方法在服务被创建时调用,该方法只会被调用一次,无论调用多少次startService()或bindService()方法,服务也只被创建一次。

 

onDestroy()该方法在服务被终止时调用。

 

 

 

与采用Context.startService()方法启动服务有关的生命周期方法

 

onStart() 只有采用Context.startService()方法启动服务时才会回调该方法。该方法在服务开始运行时被调用。多次调用startService()方法尽管不会多次创建服务,但onStart() 方法会被多次调用。

 

 

 

与采用Context.bindService()方法启动服务有关的生命周期方法

 

onBind()只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务绑定时被调用,当调用者与服务已经绑定,多次调用Context.bindService()方法并不会导致该方法被多次调用。

 

onUnbind()只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务解除绑定时被调用

 

[java] view plaincopyprint?

采用Context. bindService()方法启动服务的代码如下:  

public class HelloActivity extends Activity {  

     ServiceConnection conn = new ServiceConnection() {  

              public void onServiceConnected(ComponentName name, IBinder service) {  

           }  

           public void onServiceDisconnected(ComponentName name) {  

           }  

     };  

    @Override   

public void onCreate(Bundle savedInstanceState) {   

        Button button =(Button) this.findViewById(R.id.button);  

        button.setOnClickListener(new View.OnClickListener(){  

               public void onClick(View v) {  

                  Intent intent = new Intent(HelloActivity.this, SMSService.class);  

                  bindService(intent, conn, Context.BIND_AUTO_CREATE);  

                  //unbindService(conn);//解除绑定  

          }});         

    }  

}



****广播

***广播接收者生命周期

 

一个广播接收者有一个回调方法:void onReceive(Context curContext, Intent broadcastMsg)。当一个广播消息到达接收者是,Android调用它的onReceive()方法并传递给它包含消息的Intent对象。广播接收者被认为仅当它执行这个方法时是活跃的。当onReceive()返回后,它是不活跃的。

 

有一个活跃的广播接收者的进程是受保护的,不会被杀死。但是系统可以在任何时候杀死仅有不活跃组件的进程,当占用的内存别的进程需要时。

 

这带来一个问题,当一个广播消息的响应时费时的,因此应该在独立的线程中做这些事,远离用户界面其它组件运行的主线程。如果onReceive()衍生线程然后返回,整个进程,包括新的线程,被判定为不活跃的(除非进程中的其它应用程序组件是活跃的),将使它处于被杀的危机。解决这个问题的方法是onReceive()启动一个服务,及时服务做这个工作,因此系统知道进程中有活跃的工作在做。

 

***发送特定广播:

在需要结束应用时,发送一个特定的广播,每个Activity收到广播后,关闭即可。

//给某个activity 注册接受接受广播的意图  

 registerReceiver(receiver, filter)

//如果过接受到的是 关闭activity的广播  就调用finish()方法 把当前的activity finish()掉

 

***请描述一下Broadcast Receiver。

有很多广播接收者 ,系统已经实现了.

广播分两种 

有序广播

无序广播

指定接收者的广播 .  是不可以被拦截掉的  

<intent-filter android:priority="1000">

<action android:name="android.provider.Telephony.SMS_RECEIVED"/>

</intent-filter>

onReceive() 方法. 

abortBroadcast();

有序广播有一个特例

  sendOrderedBroadcast(intent, receiverPermission, resultReceiver, scheduler, initialCode, initialData, initialExtras);

resultReceiver 广播接受者 如果我们显示的指定了广播接收者 

无论如何 都会接受广播 时间 abortBroadcast(); 的方法不会终止广播时间

Sticky 

sendStickyBroadcast(intent)  // 阴魂不散的广播 

Wifi设置 

 用于接收系统的广播通知, 系统会有很多sd卡挂载,手机重启,广播通知,低电量,来短信等,一个apk的安装成功….

 手机卫士中自定义一个broadcast receiver

<intent-filter  android:> <action> sms_received </action>  </intent-filter>

来获取短信到来的广播, 根据黑名单来判断是否拦截该短信.

 画画板生成图片后,发送一个sd挂载的通知,通知系统的gallery去获取到新的图片.

Intent intent = new Intent(Intent.ACTION_MEDIA_MOUNTED,Uri.parse("file://"+Environment.getExternalStorageDirectory()));

sendBroadcast(intent);

 

***在manifest和代码中如何注册和使 用 broadcast receiver 。

 设置广播接收者的优先级,设置广播接受者的action名字 等…

详细见工程代码.

         <intent-filter android:priority="1000">

     <action android:name="android.intent.action.NEW_OUTGOING_CALL"/>         

         </intent-filter>

        </receiver>

  <receiver android:name=".SmsReceiver">

   <intent-filter android:priority="1000">

    <action android:name="android.provider.Telephony.SMS_RECEIVED"/>

   </intent-filter>

  </receiver>

  <receiver android:name=".BootCompleteReceiver">

   <intent-filter >

    <action android:name="android.intent.action.BOOT_COMPLETED" />  

    </intent-filter>

  </receiver>

代码中注册,如果代码没有执行,就接受不到广播事件 

        registerReceiver(receiver, filter)

 

***android的broadcast的生命周期:

答:

1)Broadcast receiver生命周期中仅有一个回调方法:

void onReceive(Context curContext, Intent broadcastMsg)

当接收器接收到一条broadcast消息,Android就会调用onReceiver(),并传递给它一个Intent对象,这个对象携带着那条 broadcast消息。我们认为仅当执行这个方式时,Broadcast receiver是活动的;这个方法返回时,它就终止了。这就是Broadcast receiver的生命周期。

 

 

2)由于Broadcast receiver的生命周期很短,一个带有活动的Broadcast receiver的进程是受保护的,以避免被干掉;但是别忘了有一点,Android会在任意时刻干掉那些携带不再活动的组件的进程,所以很可能会造成这个问题。

 

 

3)解决上述问题的方案采用一个Service来完成这项工作,Android会认为那个进程中(Service所在的进程)仍然有在活动的组件。

 

***注册广播接收者两种方式的区别,及优缺点

 

答:首先写一个类要继承BroadcastReceiver

第一种:在清单文件中声明,添加

<receiveandroid:name=".IncomingSMSReceiver " >

<intent-filter>

   <actionandroid:name="android.provider.Telephony.SMS_RECEIVED")

<intent-filter>

<receiver>

 

第二种使用代码进行注册如:

IntentFilter  filter =  newIntentFilter("android.provider.Telephony.SMS_RECEIVED");

IncomingSMSReceiver   receiver = new IncomgSMSReceiver();

registerReceiver(receiver.filter);

两种注册类型的区别是:

 

1)第一种是常驻型(静态注册),也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行。

2)第二种不是常驻型广播(动态注册),也就是说广播跟随程序的生命周期。

 

注册的方法有两种,一种是静态注册,一种是动态注册。

动态注册优点:在 Android 的广播机制中,动态注册的优先级是要高于静态注册优先级的,因此在必要的情况下,我们是需要动态注册广播接收器的。

静态注册优点:动态注册广播接收器还有一个特点,就是当用来注册的 Activity 关掉后,广播也就失效了。同时反映了静态注册的一个优势,就是无需担忧广播接收器是否被关闭,只要设备是开启状态,广播接收器就是打开着的。

 

***注册广播有几种方式,这些方式有何优缺点?请谈谈Android引入广播机制的用意。 Android广播机制(两种注册方法)

  在android下,要想接受广播信息,那么这个广播接收器就得我们自己来实现了,我们可以继承BroadcastReceiver,就可以有一个广播接受器了。有个接受器还不够,我们还得重写BroadcastReceiver里面的onReceiver方法,当来广播的时候我们要干什么,这就要我们自己来实现,不过我们可以搞一个信息防火墙。具体的代码:

  public class SmsBroadCastReceiverextends BroadcastReceiver

  {

  @Override

  public void onReceive(Context context, Intent intent)

  {

  Bundle bundle = intent.getExtras();

  Object[] object = (Object[])bundle.get("pdus");

  SmsMessage sms[]=new SmsMessage[object.length];

  for(int i=0;i

  {

  sms[0] =SmsMessage.createFromPdu((byte[])object);

  Toast.makeText(context, "来自"+sms.getDisplayOriginatingAddress()+"的消息是:"+sms.getDisplayMessageBody(),Toast.LENGTH_SHORT).show();

  }

  //终止广播,在这里我们可以稍微处理,根据用户输入的号码可以实现短信防火墙。

  abortBroadcast();

  }

  }

  当实现了广播接收器,还要设置广播接收器接收广播信息的类型,这里是信息:android.provider.Telephony.SMS_RECEIVED

  我们就可以把广播接收器注册到系统里面,可以让系统知道我们有个广播接收器。这里有两种,一种是代码动态注册:

  //生成广播处理

  smsBroadCastReceiver = newSmsBroadCastReceiver();

  //实例化过滤器并设置要过滤的广播

  IntentFilter intentFilter = newIntentFilter("android.provider.Telephony.SMS_RECEIVED");

  //注册广播

  BroadCastReceiverActivity.this.registerReceiver(smsBroadCastReceiver,intentFilter);

  一种是在AndroidManifest.xml中配置广播

  package="spl.broadCastReceiver"

  android:versionCode="1"

  android:versionName="1.0">

  android:label="@string/app_name">

  两种注册类型的区别是:

  1)第一种不是常驻型广播,也就是说广播跟随程序的生命周期。

  2)第二种是常驻型,也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行。

 

***Android引入广播机制的用意?

 

  答:a:从MVC的角度考虑(应用程序内)

  其实回答这个问题的时候还可以这样问,android为什么要有那4大组件,现在的移动开发模型基本上也是照搬的web那一套MVC架构,只不过是改了点嫁妆而已。android的四大组件本质上就是为了实现移动或者说嵌入式设备上的MVC架构,它们之间有时候是一种相互依存的关系,有时候又是一种补充关系,引入广播机制可以方便几大组件的信息和数据交互。

  b:程序间互通消息(例如在自己的应用程序内监听系统来电)

  c:效率上(参考UDP的广播协议在局域网的方便性)

  d:设计模式上(反转控制的一种应用,类似监听者模式)



****Activity

***什么是Activity? 

四大组件之一,一般的,一个用户交互界面对应一个activity

setContentView() ,    // 要显示的布局 , activity 是Context的子类,同时实现了window.callback和keyevent.callback,     //可以处理与窗体用户交互的事件. 

button.setOnclickLinstener{

}

我开发常用的的有ListActivity  , PreferenceActivity ,TabAcitivty等…

如果界面有共同的特点或者功能的时候,还会自己定义一个BaseActivity. 

进度对话框的显示与销毁  doubanservice

 

***让Activity变成一个窗口:Activity属性设定 

  讲点轻松的吧,可能有人希望做出来的应用程序是一个漂浮在手机主界面的东西,那么很 简单你只需要设置 一下Activity的主题就可以了在AndroidManifest.xml 中定义 Activity的 地方一句话: 

  Xml代码 

  1. android :theme="@android:style/Theme.Dialog" 

  这就使你的应用程序变成对话框的形式弹出来了,或者 

 

  Xml代码 

  1. android:theme="@android:style/Theme.Translucent" 

  就变成半透明的,[友情提示-.-]类似的这种activity的属性可以在android.R.styleable 类的AndroidManifestActivity 方法中看到,AndroidManifest.xml中所有元素的属性的介绍都可以参考这个类android.R.styleable 

 

  上面说的是属性名称,具体有什么值是在android.R.style中 可以看到,比如这个"@android:style/Theme.Dialog" 就对应于android.R.style.Theme_Dialog ,('_'换成'.' < --注意:这个是文章内容不是笑脸)就可以用在描述文件 中了,找找类定义和描述文件中的对应关系就都明白了。 

 

***请描述下Activity的生命周期。 必调用的三个方法:onCreate() --> onStart() --> onResume(),用AAA表示

  (1)父Activity启动子Activity,子Actvity退出,父Activity调用顺序如下

  AAA --> onFreeze() --> onPause() --> onStop() --> onRestart()--> onStart(),onResume() …

 

  (2)用户点击Home,Actvity调用顺序如下

  AAA --> onFreeze() --> onPause() --> onStop() -- Maybe -->onDestroy() – Maybe

 

  (3)调用finish(), Activity调用顺序如下

  AAA --> onPause() --> onStop() --> onDestroy()

 

  (4)在Activity上显示dialog,Activity调用顺序如下

  AAA

 

  (5)在父Activity上显示透明的或非全屏的activity,Activity调用顺序如下

  AAA --> onFreeze() --> onPause()

 

  (6)设备进入睡眠状态,Activity调用顺序如下

  AAA --> onFreeze() --> onPause()

 

***如果后台的Activity由于某原因被系统回收了,如何在被系统回收之前保存当前状态?

  当你的程序中某一个Activity A在运行时,主动或被动地运行另一个新的Activity B,这个时候A会执行onSaveInstanceState()。B完成以后又会来找A,这个时候就有两种情况:一是A被回收,二是A没有被回收,被回收的A就要重新调用onCreate()方法,不同于直接启动的是这回onCreate()里是带上了参savedInstanceState;而没被收回的就直接执行onResume(),跳过onCreate()了。

 

*** 如何退出Activity?如何安全退出已调用多个Activity的Application?

       对于单一Activity的应用来说,退出很简单,直接finish()即可。

  当然,也可以用killProcess()和System.exit()这样的方法。

  但是,对于多Activity的应用来说,在打开多个Activity后,如果想在最后打开的Activity直接退出,上边的方法都是没有用的,因为上边的方法都是结束一个              Activity而已。

  当然,网上也有人说可以。

 

  就好像有人问,在应用里如何捕获Home键,有人就会说用keyCode比较KEYCODE_HOME即可,而事实上如果不修改framework,根本不可能做到这一点一样。

  所以,最好还是自己亲自试一下。

 

  那么,有没有办法直接退出整个应用呢?

 

  在2.1之前,可以使用ActivityManager的restartPackage方法。

  它可以直接结束整个应用。在使用时需要权限android.permission.RESTART_PACKAGES。

  注意不要被它的名字迷惑。

  可是,在2.2,这个方法失效了。

 

  在2.2添加了一个新的方法,killBackgroundProcesses(),需要权限android.permission.KILL_BACKGROUND_PROCESSES。

  可惜的是,它和2.2的restartPackage一样,根本起不到应有的效果。

  另外还有一个方法,就是系统自带的应用程序管理里,强制结束程序的方法,forceStopPackage()。

  它需要权限android.permission.FORCE_STOP_PACKAGES。

  并且需要添加android:sharedUserId="android.uid.system"属性

  同样可惜的是,该方法是非公开的,他只能运行在系统进程,第三方程序无法调用。

  因为需要在Android.mk中添加LOCAL_CERTIFICATE := platform。

  而Android.mk是用于在Android源码下编译程序用的。

  从以上可以看出,在2.2,没有办法直接结束一个应用,而只能用自己的办法间接办到。

  现提供几个方法,供参考:

  1、抛异常强制退出:

 该方法通过抛异常,使程序Force Close。 

验证可以,但是,需要解决的问题是,如何使程序结束掉,而不弹出Force Close的窗口。

//安全结束进程  android.os.Process.killProcess(android.os.Process.myPid());

 

  2、记录打开的Activity:

 每打开一个Activity,就记录下来。在需要退出时,关闭每一个Activity即可。

  List<Activity> lists ; 在application 全集的环境里面 

  lists = new ArrayList<Activity>();

  lists.add(activity);

for(Activity activity: lists)

{

activity.finish();

}

 

  3、发送特定广播:

  在需要结束应用时,发送一个特定的广播,每个Activity收到广播后,关闭即可。

 

  4、递归退出

  在打开新的Activity时使用startActivityForResult,然后自己加标志,在onActivityResult中处理,递归关闭。

      上面是网上的一些做法.

其实 可以通过 intent的flag 来实现.. intent.setFlag(FLAG_ACTIVITY_CLEAR_TOP)激活一个新的activity,然后在新的activity的oncreate方法里面 finish掉.

Intent intent = new Intent(this,B.class);

intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

局限性 :所有的activity的启动模式都要是默认的启动模式 

 

  除了第一个,都是想办法把每一个Activity都结束掉,间接达到目的。

 

  但是这样做同样不完美。

  你会发现,如果自己的应用程序对每一个Activity都设置了nosensor,在两个Activity结束的间隙,sensor可能有效了。

  但至少,我们的目的达到了,而且没有影响用户使用。

  为了编程方便,最好定义一个Activity基类,处理这些共通问题。

 

***如何退出Activity

 

对于单一Activity的应用来说,退出很简单,直接finish()即可。当然,也可以用killProcess()和System.exit()这样的方法。现提供几个方法,供参考:

1、抛异常强制退出:该方法通过抛异常,使程序Force Close。验证可以,但是,需要解决的问题是,如何使程序结束掉,而不弹出Force Close的窗口。

2、记录打开的Activity:每打开一个Activity,就记录下来。在需要退出时,关闭每一个Activity即可。

3、发送特定广播:在需要结束应用时,发送一个特定的广播,每个Activity收到广播后,关闭即可。

4、递归退出在打开新的Activity时使用startActivityForResult,然后自己加标志,在onActivityResult中处理,递归关闭。除了第一个,都是想办法把每一个Activity都结束掉,间接达到目的。但是这样做同样不完美。你会发现,如果自己的应用程序对每一个Activity都设置了nosensor,在两个Activity结束的间隙,sensor可能有效了。但至少,我们的目的达到了,而且没有影响用户使用。为了编程方便,最好定义一个Activity基类,处理这些共通问题。

 

***两个Activity之间跳转时必然会执行的是哪几个方法。

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

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

 

***如果后台的Activity由于某原因被系统回收了,如何在被系统回收之前保存当前状态?

 

当你的程序中某一个Activity A 在运行时中,主动或被动地运行另一个新的Activity B 

这个时候A会执行。

 

Java代码

 

public void onSaveInstanceState(Bundle outState) {   

 

      super.onSaveInstanceState(outState);    

 

      outState.putLong("id", 1234567890);

 

}  

 

B 完成以后又会来找A, 这个时候就有两种情况,一种是A被回收,一种是没有被回收,被回

收的A就要重新调用onCreate()方法,不同于直接启动的是这回onCreate()里是带上参数savedInstanceState,没被收回的就还是onResume就好了。

 

savedInstanceState是一个Bundle对象,你基本上可以把他理解为系统帮你维护的一个Map对象。在onCreate()里你可能会 用到它,如果正常启动onCreate就不会有它,所以用的时候要判断一下是否为空。

 

Java代码

 

if(savedInstanceState != null){  

     long id = savedInstanceState.getLong("id");  

}  

 

就像官方的Notepad教程 里的情况,你正在编辑某一个note,突然被中断,那么就把这个note的id记住,再起来的时候就可以根据这个id去把那个note取出来,程序就完整 一些。这也是看你的应用需不需要保存什么,比如你的界面就是读取一个列表,那就不需要特殊记住什么,哦, 没准你需要记住滚动条的位置...

 

 

***两个Activity之间怎么传递数据?

基本数据类型可以通过.  Intent 传递数据  

extras.putDouble(key, value)

intent.putExtra(name, value)  

// 通过intent putExtra 方法 基本数据类型 都传递 

 Bundle bundle = new  Bundle();

     bumdle.putShort(key, value);

     intent.putExtras(bundle);

intent.putExtras(bundle)

获取到激活他的  getIntent();

        Intent intent = getIntent();

        Bundle bundle = intent.getExtras();

intent.getStringExtra("key","value");

intent.getBooleanExtra("key","value")

 

Application 全局里面存放 对象 ,自己去实现自己的application的这个类,基础系统的application , 每个activity都可以取到

让对象实现 implements  Serializable 接口把对象存放到文件上.  

 

让类实现Serializable 接口,然后可以通过 ObjectOutputStream    //对象输出流  

  File file = new File("c:\\1.obj");

  FileOutputStream fos  = new FileOutputStream(file);

  ObjectOutputStream oos = new ObjectOutputStream(fos);

  

  Student stu = new Student();

  stu.setId("10001");

  stu.setName("zs");

  oos.writeObject(stu);

  

  FileInputStream fis = new FileInputStream(file);

  ObjectInputStream ois = new ObjectInputStream(fis);

   Student stu1 = (Student) ois.readObject();

  System.out.println(stu1.getName());

Parcelable 和 Serializable

Parcelable 把对象序列化到android操作系统 的一块公用的内存空间 

文件/网络

intent.setData(Uri) 

Uri.fromFile();  //大图片的传递

contentResolver.getInputStream(url);

 

***怎么让在启动一个Activity是就启动一个service?

在activity的onCreate()方法里面 startService();

 

*** 同一个程序,但不同的Activity是否可以放在不同的Task任务栈中?

比方说在激活一个新的activity时候, 给intent设置flag

Intent的flag添加FLAG_ACTIVITY_NEW_TASK

   这个被激活的activity就会在新的task栈里面…

 Intent intent = new Intent(A.this,B.class);

 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

 startActivity(intent);

 

 

***Activity怎么和service绑定,怎么在activity中启动自己对应的service?

startService() 一旦被创建  调用着无关   没法使用service里面的方法 

bindService () 把service 与调用者绑定 ,如果调用者被销毁, service会销毁

bindService() 我们可以使用service 里面的方法

 bindService().  让activity能够访问到 service里面的方法

 构建一个intent对象,

Intent service = new Intent(this,MyService.class);

 通过bindService的方法去启动一个服务,

    bindService(intent, new MyConn(), BIND_AUTO_CREATE);

 ServiceConnection 对象(重写onServiceConnected和OnServiceDisconnected方法) 和BIND_AUTO_CREATE.

 private class myconn implements ServiceConnection

 {

  public void onServiceConnected(ComponentName name, IBinder service) {

   // TODO Auto-generated method stub

   //可以通过IBinder的对象 去使用service里面的方法

  }

  public void onServiceDisconnected(ComponentName name) {

   // TODO Auto-generated method stub

   

  }

  

 }

 

***说说Activity,Intent,Service是什么关系 。

 麦当劳和麦当娜的关系是什么关系?

 这种问题,就讲下activity,讲一下service,说一下 通过intent去激活组件,传递数据.

 说自己项目中有这样一个网络更新的功能,显示界面就用的activity, 后台有个service每隔半小时都去访问下服务器获取更新的数据…

开启服务用的是intent来开启

 

***widget相对位置的完成在activity的哪个生命周期阶段实现。

 这个题没看懂… 

widget可以理解成桌面小控件,

也可以理解成 某个button, imageview这样的控件…

onmeasure() // 计算 控件在屏幕上的位子 

某个view 要显示在界面  ondraw 被显示到界面上的

 

***Framework工作方式及原理,Activity是如何生成一个view的,机制是什么。

反射 , 配置文件 

 可以讲下activity的源码,比如说 每个activity里面都有window.callback和keyevent.callback,一些回调的接口或者函数吧. 框架把activity创建出来就会调用里面的这些回调方法,会调用activity生命周期相关的方法.

setContentView();

普通的情况:

Activity创建一个view是通过 ondraw 画出来的, 画这个view之前呢,还会调用onmeasure方法来计算显示的大小.

Surfaceview 直接操作硬件  opengl .

图像要想被显示到界面上, 需要设备显卡, 显存.

写到显存.

 

***横竖屏切换时候activity的生命周期

1.不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次. 

 

2.设置Activity的android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次. 

 

3.设置Activity的android:configChanges="orientation|keyboardHidden"时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法.

 

***Activity 与 Task的启动模式有哪些,它们含义具体是什么?

 

答:在一个activity中,有多次调用startActivity来启动另一个activity,要想只生成一个activity实例,可以设置启动模式。

 

    一个activity有四种启动模式:standed,signleTop,singleTask,singleInstance

 

    Standed:标准模式,一调用startActivity()方法就会产生一个新的实例。

 

    SingleTop:如果已经有一个实例位于activity栈顶,就不产生新的实例,而只是调用activity中的newInstance()方法。如果不位于栈顶,会产生一个新的实例。

 

    singleTask:会在一个新的task中产生这个实例,以后每次调用都会使用这个,不会去产生新的实例了。

 

    SingleInstance:这个和singleTask基本一样,只有一个区别:在这个模式下的activity实例所处的task中,只能有这个activity实例,不能有其他实例

  

****请描述一下Activity 生命周期。

生命周期描述的是一个类 从创建(new出来)到死亡(垃圾回收)的过程中会执行的方法..

在这个过程中 会针对不同的生命阶段会调用不同的方法

 

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

 

其实这些方法都是两两对应的:

onCreate创建与onDestroy销毁;

onStart可见与onStop不可见;

onResume可编辑(即焦点)与onPause;

 

对话框的弹出, Activity.this 

这6个方法是相对应的,那么就只剩下一个onRestart方法了,这个方法在什么时候调用呢?

 

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

如果被onDestroy了,则是调用onCreate方法。

最后讲自己项目中的经验,比如说豆瓣客户端每次进入某个界面的时候都要看到最新的数据,这个刷新列表的操作 就放在onStart()的方法里面.

fillData() 这样保证每次用户看到的数据都是最新的.

多媒体播放, 播放来电话. onStop() 视频, 视频声音设置为0 , 记录视频播放的位置 mediaplayer.pause();

onStart() 根据保存的状态恢复现场. mediaplayer.start();

在读文档的时候 还发现 activity还有两个方法 onPostResume() 和 OnPostCreate()这两个生命周期的方法,不过开发的时候没有用到过.


再总结下整个activity的生命周期:

 

1)  当前activity产生事件弹出Toast和AlertDialog的时候Activity的生命周期不会有改变

 

2)  Activity运行时按下HOME键(跟被完全覆盖一样的)

 

onSavaInstanceState

 

onPause

 

onStop

 

 

onRestart

 

onStart

 

onResume

 

    3)  未被完全覆盖,只是失去焦点:

 

        onPause

 

        onResume

 

****Activity的生命周期:

 

答:onCreate: 在这里创建界面,做一些数据 的初始化工作

 

  onStart: 到这一步变成用户可见不可交互的

 

      onResume:变成和用户可交互 的,(在activity 栈系统通过栈的方式管理这些个Activity的最上面,运行完弹出栈,则回到上一个Activity)

 

  onPause: 到这一步是可见但不可交互的,系统会停止动画 等消耗CPU 的事情从上文的描述已经知道,应该在这里保存你的一些数据,因为这个时候你的程序的优先级降低,有可能被系统收回。在这里保存的数据,应该在

 

  onstop: 变得不可见,被下一个activity覆盖了

 

      onDestroy: 这是activity被干掉前最后一个被调用方法了,可能是外面类调用finish方法或者是系统为了节省空间将它暂时性的干掉


1、onCreate():当Activity被创建的时候调用(第一次)。操作:设置布局文件,初始化视图,绑定数据文件等。

 

2、onStart():当Activity能被我们看到的时候。

 

3、onResume():当Activity获得用户的焦点的时候,就是能被用户操作的时候。

 

4、onPause()[pause暂停的意思]:Activity暂停。应用程序启动了另一个Activity的时候。例子:来了一个电话,系统启动了电话Activity。在这个函数里要做的就是把Activity的数据保存起来,当接完电话的时候,再把这些数据读出来,把原来的Activity还原出来。

 

5、onstop():当第二个Activity把第一个Activity完全遮挡住了的时候。对话框并没有把原来的Activity完全遮挡起来,不会调用。

 

6、onDestroy():销毁Activity。1)调用了finish()方法。2)系统资源不够用了。

 

函数调用过程:

启动第一个Activity的时候:

第一次创建onCreate()-->Activity可见了onStart()-->Activity可以操作了onResume()。

 

点击第一个Activity上的按钮通过Intent跳到第二个Activity:

第一个Activity暂停onPause()-->创建第二个ActivityonCreate()-->Activity可见onStart()-->Activity可操作onResume()-->第一个Activity被第二个Activity完全遮盖onStop()(如果调用了finish(),或者系统资源紧缺,则会被销毁onDestory())。

 

 

点击系统返回功能建,从第二个Activity回到第一个Activity :

第二个Activity暂停onPause()-->第一个Activity重启动OnRestart()(并没有被销毁,如果销毁了则要创建onCreate())-->第一个Activity可见onStart()-->第一个Activity可操作onResume()-->第二个Activity被完全遮盖onStop()(如果调用了finish(),或者系统资源紧缺,则会被销毁onDestory())。


0 0
原创粉丝点击