android Java 笔试考题
前19题为常考题目!!(版本号:201108141031)
1、Android的四大组件是哪些,它们的作用?3
2、请介绍下Android中常用的五种布局。3
3、android中的动画有哪几类,它们的特点和区别是什么3
4、android中有哪几种解析xml的类?官方推荐哪种?以及它们的原理和区别。3
5、ListView的优化方案4
6、请介绍下Android的数据存储方式。4
7、activity的启动模式有哪些?是什么含义?6
8、跟activity和Task有关的Intent启动方式有哪些?其含义?7
9、请描述下Activity的生命周期。9
10、activity在屏幕旋转时的生命周期10
11、如何启用Service,如何停用Service。10
12、注册广播有几种方式,这些方式有何优缺点?请谈谈Android引入广播机制的用意。11
13、请解释下在单线程模型中Message、Handler、MessageQueue、Looper之间的关系。11
14、简要解释一下activity、intent、intentfilter、service、Broadcase、BroadcaseReceiver13
15、说说mvc模式的原理,它在android中的运用,android的官方建议应用程序的开发采用mvc模式。何谓mvc?13
16、什么是ANR如何避免它?13
17、什么情况会导致ForceClose?如何避免?能否捕获导致其的异常?14
18、描述一下android的系统架构14
19、请介绍下ContentProvider是如何实现数据共享的。14
20、Android本身的api并未声明会抛出异常,则其在运行时有无可能抛出runtime异常,你遇到过吗?诺有的话会导致什么问题?如何解决?15
21、IntentService有何优点?15
22、如果后台的Activity由于某原因被系统回收了,如何在被系统回收之前保存当前状态?15
23、如何将一个Activity设置成窗口的样式。15
24、如何退出Activity?如何安全退出已调用多个Activity的Application?15
25、AIDL的全称是什么?如何工作?能处理哪些类型的数据?16
26、请解释下Android程序运行时权限与文件系统权限的区别。17
27、系统上安装了多种浏览器,能否指定某浏览器访问指定页面?请说明原由。17
28、android系统的优势和不足17
29、Androiddvm的进程和Linux的进程,应用程序的进程是否为同一个概念18
30、sim卡的EF文件是什么?有何作用18
31、嵌入式操作系统内存管理有哪几种,各有何特性18
32、什么是嵌入式实时操作系统,Android操作系统属于实时操作系统吗?18
33、一条最长的短信息约占多少byte?18
34、有一个一维整型数组int[]data保存的是一张宽为width,高为height的图片像素值信息。请写一个算法,将该图片所有的白色不透明(0xffffffff)像素点的透明度调整为50%。18
35、如何将SQLite数据库(dictionary.db文件)与apk文件一起发布19
36、如何将打开resaw目录中的数据库文件?19
37、DDMS和TraceView的区别?19
38、java中如何引用本地语言19
39、谈谈Android的IPC(进程间通信)机制19
40、NDK是什么19
1、Android的四大组件是哪些,它们的作用?
答:Activity:Activity是Android程序与用户交互的窗口,是Android构造块中最基本的一种,它需要为保持各界面的状态,做很多持久化的事情,妥善管理生命周期以及一些跳转逻辑
service:后台服务于Activity,封装有一个完整的功能逻辑实现,接受上层指令,完成相关的食物,定义好需要接受的Intent提供同步和异步的接口
ContentProvider:是Android提供的第三方应用数据的访问方案,可以派生ContentProvider类,对外提供数据,可以像数据库一样进行选择排序,屏蔽内部数据的存储细节,向外提供统一的借口模型,大大简化上层应用,对数据的整合提供了更方便的途径
BroadCastReceiver:接受一种或者多种Intent作触发事件,接受相关消息,做一些简单处理,转换成一条Notification,统一了Android的事件广播模型
2、请介绍下Android中常用的五种布局。
常用五种布局方式,分别是:FrameLayout(框架布局),LinearLayout(线性布局),AbsoluteLayout(绝对布局),RelativeLayout(相对布局),TableLayout(表格布局)。
一、FrameLayout:所有东西依次都放在左上角,会重叠,这个布局比较简单,也只能放一点比较简单的东西。二、LinearLayout:线性布局,每一个LinearLayout里面又可分为垂直布局(android:orientation="vertical")和水平布局(android:orientation="horizontal")。当垂直布局时,每一行就只有一个元素,多个元素依次垂直往下;水平布局时,只有一行,每一个元素依次向右排列。三、AbsoluteLayout:绝对布局用X,Y坐标来指定元素的位置,这种布局方式也比较简单,但是在屏幕旋转时,往往会出问题,而且多个元素的时候,计算比较麻烦。四、RelativeLayout:相对布局可以理解为某一个元素为参照物,来定位的布局方式。主要属性有:相对于某一个元素android:layout_below、android:layout_toLeftOf相对于父元素的地方android:layout_alignParentLeft、android:layout_alignParentRigh;五、TableLayout:表格布局,每一个TableLayout里面有表格行TableRow,TableRow里面可以具体定义每一个元素。每一个布局都有自己适合的方式,这五个布局元素可以相互嵌套应用,做出美观的界面。
3、android中的动画有哪几类,它们的特点和区别是什么
答:两种,一种是Tween动画、还有一种是Frame动画。Tween动画,这种实现方式可以使视图组件移动、放大、缩小以及产生透明度的变化;另一种Frame动画,传统的动画方法,通过顺序的播放排列好的图片来实现,类似电影。
4、android中有哪几种解析xml的类?官方推荐哪种?以及它们的原理和区别。
答:XML解析主要有三种方式,SAX、DOM、PULL。常规在PC上开发我们使用Dom相对轻松些,但一些性能敏感的数据库或手机上还是主要采用SAX方式,SAX读取是单向的,优点:不占内存空间、解析属性方便,但缺点就是对于套嵌多个分支来说处理不是很方便。而DOM方式会把整个XML文件加载到内存中去,这里Android开发网提醒大家该方法在查找方面可以和XPath很好的结合如果数据量不是很大推荐使用,而PULL常常用在J2ME对于节点处理比较好,类似SAX方式,同样很节省内存,在J2ME中我们经常使用的KXML库来解析。
5、ListView的优化方案
答:1、如果自定义适配器,那么在getView方法中要考虑方法传进来的参数contentView是否为null,如果为null就创建contentView并返回,如果不为null则直接使用。在这个方法中尽可能少创建view。
2、给contentView设置tag(setTag()),传入一个viewHolder对象,用于缓存要显示的数据,可以达到图像数据异步加载的效果。
3、如果listview需要显示的item很多,就要考虑分页加载。比如一共要显示100条或者更多的时候,我们可以考虑先加载20条,等用户拉到列表底部的时候再去加载接下来的20条。
6、请介绍下Android的数据存储方式。
答:使用SharedPreferences存储数据;文件存储数据;SQLite数据库存储数据;使用ContentProvider存储数据;网络存储数据;
Preference,File,DataBase这三种方式分别对应的目录是/data/data/PackageName/Shared_Pref,/data/data/PackageName/files,/data/data/PackageName/database。
一:使用SharedPreferences存储数据
首先说明SharedPreferences存储方式,它是Android提供的用来存储一些简单配置信息的一种机制,例如:登录用户的用户名与密码。其采用了Map数据结构来存储数据,以键值的方式存储,可以简单的读取与写入,具体实例如下:
voidReadSharedPreferences(){
StringstrName,strPassword;
SharedPreferencesuser=getSharedPreferences(“user_info”,0);
strName=user.getString(“NAME”,””);
strPassword=usergetString(“PASSWORD”,””);
}
voidWriteSharedPreferences(StringstrName,StringstrPassword){
SharedPreferencesuser=getSharedPreferences(“user_info”,0);
uer.edit();
user.putString(“NAME”,strName);
user.putString(“PASSWORD”,strPassword);
user.commit();
}
数据读取与写入的方法都非常简单,只是在写入的时候有些区别:先调用edit()使其处于编辑状态,然后才能修改数据,最后使用commit()提交修改的数据。实际上SharedPreferences是采用了XML格式将数据存储到设备中,在DDMS中的FileExplorer中的/data/data/<packagename>/shares_prefs下。使用SharedPreferences是有些限制的:只能在同一个包内使用,不能在不同的包之间使用。
二:文件存储数据
文件存储方式是一种较常用的方法,在Android中读取/写入文件的方法,与Java中实现I/O的程序是完全一样的,提供了openFileInput()和openFileOutput()方法来读取设备上的文件。具体实例如下:
Stringfn=“moandroid.log”;
FileInputStreamfis=openFileInput(fn);
FileOutputStreamfos=openFileOutput(fn,Context.MODE_PRIVATE);
三:网络存储数据
网络存储方式,需要与Android网络数据包打交道,关于Android网络数据包的详细说明,请阅读AndroidSDK引用了JavaSDK的哪些package?。
四:ContentProvider
1、ContentProvider简介
当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据。虽然使用其他方法也可以对外共享数据,但数据访问方式会因数据存储的方式而不同,如:采用文件方式对外共享数据,需要进行文件操作读写数据;采用sharedpreferences共享数据,需要使用sharedpreferencesAPI读写数据。而使用ContentProvider共享数据的好处是统一了数据访问方式。
2、Uri类简介
Uri代表了要操作的数据,Uri主要包含了两部分信息:1.需要操作的ContentProvider,2.对ContentProvider中的什么数据进行操作,一个Uri由以下几部分组成:
1.scheme:ContentProvider(内容提供者)的scheme已经由Android所规定为:content://…
2.主机名(或Authority):用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。
3.路径(path):可以用来表示我们要操作的数据,路径的构建应根据业务而定,如下:
要操作contact表中id为10的记录,可以构建这样的路径:/contact/10
要操作contact表中id为10的记录的name字段,contact/10/name
要操作contact表中的所有记录,可以构建这样的路径:/contact?
要操作的数据不一定来自数据库,也可以是文件等他存储方式,如下:
要操作xml文件中contact节点下的name节点,可以构建这样的路径:/contact/name
如果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法,如下:
Uriuri=Uri.parse("content://com.changcheng.provider.contactprovider/contact")
3、UriMatcher、ContentUrist和ContentResolver简介
因为Uri代表了要操作的数据,所以我们很经常需要解析Uri,并从Uri中获取数据。Android系统提供了两个用于操作Uri的工具类,分别为UriMatcher和ContentUris。掌握它们的使用,会便于我们的开发工作。
UriMatcher:用于匹配Uri,它的用法如下:
1.首先把你需要匹配Uri路径全部给注册上,如下:
//常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码(-1)。
UriMatcheruriMatcher=newUriMatcher(UriMatcher.NO_MATCH);
//如果match()方法匹配content://com.changcheng.sqlite.provider.contactprovider/contact路径,返回匹配码为1
uriMatcher.addURI(“com.changcheng.sqlite.provider.contactprovider”,“contact”,1);//添加需要匹配uri,如果匹配就会返回匹配码
//如果match()方法匹配content://com.changcheng.sqlite.provider.contactprovider/contact/230路径,返回匹配码为2
uriMatcher.addURI(“com.changcheng.sqlite.provider.contactprovider”,“contact/#”,2);//#号为通配符
2.注册完需要匹配的Uri后,就可以使用uriMatcher.match(uri)方法对输入的Uri进行匹配,如果匹配就返回匹配码,匹配码是调用addURI()方法传入的第三个参数,假设匹配content://com.changcheng.sqlite.provider.contactprovider/contact路径,返回的匹配码为1。
ContentUris:用于获取Uri路径后面的ID部分,它有两个比较实用的方法:
withAppendedId(uri,id)用于为路径加上ID部分
parseId(uri)方法用于从路径中获取ID部分
ContentResolver:当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver类来完成,要获取ContentResolver对象,可以使用Activity提供的getContentResolver()方法。ContentResolver使用insert、delete、update、query方法,来操作数据。
7、activity的启动模式有哪些?是什么含义?
答:在android里,有4种activity的启动模式,分别为:
“standard”(默认)
“singleTop”
“singleTask”
“singleInstance”
它们主要有如下不同:
1.如何决定所属task
“standard”和”singleTop”的activity的目标task,和收到的Intent的发送者在同一个task内,除非intent包括参数FLAG_ACTIVITY_NEW_TASK。
如果提供了FLAG_ACTIVITY_NEW_TASK参数,会启动到别的task里。
“singleTask”和”singleInstance”总是把activity作为一个task的根元素,他们不会被启动到一个其他task里。
2.是否允许多个实例
“standard”和”singleTop”可以被实例化多次,并且存在于不同的task中,且一个task可以包括一个activity的多个实例;
“singleTask”和”singleInstance”则限制只生成一个实例,并且是task的根元素。singleTop要求如果创建intent的时候栈顶已经有要创建的Activity的实例,则将intent发送给该实例,而不发送给新的实例。
3.是否允许其它activity存在于本task内
“singleInstance”独占一个task,其它activity不能存在那个task里;如果它启动了一个新的activity,不管新的activity的launchmode如何,新的activity都将会到别的task里运行(如同加了FLAG_ACTIVITY_NEW_TASK参数)。
而另外三种模式,则可以和其它activity共存。
4.是否每次都生成新实例
“standard”对于没一个启动Intent都会生成一个activity的新实例;
“singleTop”的activity如果在task的栈顶的话,则不生成新的该activity的实例,直接使用栈顶的实例,否则,生成该activity的实例。
比如现在task栈元素为A-B-C-D(D在栈顶),这时候给D发一个启动intent,如果D是“standard”的,则生成D的一个新实例,栈变为A-B-C-D-D。
如果D是singleTop的话,则不会生产D的新实例,栈状态仍为A-B-C-D
如果这时候给B发Intent的话,不管B的launchmode是”standard”还是“singleTop”,都会生成B的新实例,栈状态变为A-B-C-D-B。
“singleInstance”是其所在栈的唯一activity,它会每次都被重用。
“singleTask”如果在栈顶,则接受intent,否则,该intent会被丢弃,但是该task仍会回到前台。
当已经存在的activity实例处理新的intent时候,会调用onNewIntent()方法如果收到intent生成一个activity实例,那么用户可以通过back键回到上一个状态;如果是已经存在的一个activity来处理这个intent的话,用户不能通过按back键返回到这之前的状态。
8、跟activity和Task有关的Intent启动方式有哪些?其含义?
核心的IntentFlag有:
FLAG_ACTIVITY_NEW_TASK
FLAG_ACTIVITY_CLEAR_TOP
FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
FLAG_ACTIVITY_SINGLE_TOP
FLAG_ACTIVITY_NEW_TASK
如果设置,这个Activity会成为历史stack中一个新Task的开始。一个Task(从启动它的Activity到下一个Task中的Activity)定义了用户可以迁移的Activity原子组。Task可以移动到前台和后台;在某个特定Task中的所有Activity总是保持相同的次序。
这个标志一般用于呈现“启动”类型的行为:它们提供用户一系列可以单独完成的事情,与启动它们的Activity完全无关。
使用这个标志,如果正在启动的Activity的Task已经在运行的话,那么,新的Activity将不会启动;代替的,当前Task会简单的移入前台。参考FLAG_ACTIVITY_MULTIPLE_TASK标志,可以禁用这一行为。
这个标志不能用于调用方对已经启动的Activity请求结果。
FLAG_ACTIVITY_CLEAR_TOP
如果设置,并且这个Activity已经在当前的Task中运行,因此,不再是重新启动一个这个Activity的实例,而是在这个Activity上方的所有Activity都将关闭,然后这个Intent会作为一个新的Intent投递到老的Activity(现在位于顶端)中。
例如,假设一个Task中包含这些Activity:A,B,C,D。如果D调用了startActivity(),并且包含一个指向ActivityB的Intent,那么,C和D都将结束,然后B接收到这个Intent,因此,目前stack的状况是:A,B。
上例中正在运行的ActivityB既可以在onNewIntent()中接收到这个新的Intent,也可以把自己关闭然后重新启动来接收这个Intent。如果它的启动模式声明为“multiple”(默认值),并且你没有在这个Intent中设置FLAG_ACTIVITY_SINGLE_TOP标志,那么它将关闭然后重新创建;对于其它的启动模式,或者在这个Intent中设置FLAG_ACTIVITY_SINGLE_TOP标志,都将把这个Intent投递到当前这个实例的onNewIntent()中。
这个启动模式还可以与FLAG_ACTIVITY_NEW_TASK结合起来使用:用于启动一个Task中的根Activity,它会把那个Task中任何运行的实例带入前台,然后清除它直到根Activity。这非常有用,例如,当从NotificationManager处启动一个Activity。
FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
如果设置这个标志,这个activity不管是从一个新的栈启动还是从已有栈推到栈顶,它都将以thefrontdoorofthetask的方式启动。这就讲导致任何与应用相关的栈都讲重置到正常状态(不管是正在讲activity移入还是移除),如果需要,或者直接重置该栈为初始状态。
FLAG_ACTIVITY_SINGLE_TOP
如果设置,当这个Activity位于历史stack的顶端运行时,不再启动一个新的
FLAG_ACTIVITY_BROUGHT_TO_FRONT
这个标志一般不是由程序代码设置的,如在launchMode中设置singleTask模式时系统帮你设定。
FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
如果设置,这将在Task的Activitystack中设置一个还原点,当Task恢复时,需要清理Activity。也就是说,下一次Task带着FLAG_ACTIVITY_RESET_TASK_IF_NEEDED标记进入前台时(典型的操作是用户在主画面重启它),这个Activity和它之上的都将关闭,以至于用户不能再返回到它们,但是可以回到之前的Activity。
这在你的程序有分割点的时候很有用。例如,一个e-mail应用程序可能有一个操作是查看一个附件,需要启动图片浏览Activity来显示。这个Activity应该作为e-mail应用程序Task的一部分,因为这是用户在这个Task中触发的操作。然而,当用户离开这个Task,然后从主画面选择e-mailapp,我们可能希望回到查看的会话中,但不是查看图片附件,因为这让人困惑。通过在启动图片浏览时设定这个标志,浏览及其它启动的Activity在下次用户返回到mail程序时都将全部清除。
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
如果设置,新的Activity不会在最近启动的Activity的列表中保存。
FLAG_ACTIVITY_FORWARD_RESULT
如果设置,并且这个Intent用于从一个存在的Activity启动一个新的Activity,那么,这个作为答复目标的Activity将会传到这个新的Activity中。这种方式下,新的Activity可以调用setResult(int),并且这个结果值将发送给那个作为答复目标的Activity。
FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
这个标志一般不由应用程序代码设置,如果这个Activity是从历史记录里启动的(常按HOME键),那么,系统会帮你设定。
FLAG_ACTIVITY_MULTIPLE_TASK
不要使用这个标志,除非你自己实现了应用程序启动器。与FLAG_ACTIVITY_NEW_TASK结合起来使用,可以禁用把已存的Task送入前台的行为。当设置时,新的Task总是会启动来处理Intent,而不管这是是否已经有一个Task可以处理相同的事情。
由于默认的系统不包含图形Task管理功能,因此,你不应该使用这个标志,除非你提供给用户一种方式可以返回到已经启动的Task。
如果FLAG_ACTIVITY_NEW_TASK标志没有设置,这个标志被忽略。
FLAG_ACTIVITY_NO_ANIMATION
如果在Intent中设置,并传递给Context.startActivity()的话,这个标志将阻止系统进入下一个Activity时应用Acitivity迁移动画。这并不意味着动画将永不运行——如果另一个Activity在启动显示之前,没有指定这个标志,那么,动画将被应用。这个标志可以很好的用于执行一连串的操作,而动画被看作是更高一级的事件的驱动。
FLAG_ACTIVITY_NO_HISTORY
如果设置,新的Activity将不再历史stack中保留。用户一离开它,这个Activity就关闭了。这也可以通过设置noHistory特性。
FLAG_ACTIVITY_NO_USER_ACTION
如果设置,作为新启动的Activity进入前台时,这个标志将在Activity暂停之前阻止从最前方的Activity回调的onUserLeaveHint()。
典型的,一个Activity可以依赖这个回调指明显式的用户动作引起的Activity移出后台。这个回调在Activity的生命周期中标记一个合适的点,并关闭一些Notification。
如果一个Activity通过非用户驱动的事件,如来电或闹钟,启动的,这个标志也应该传递给Context.startActivity,保证暂停的Activity不认为用户已经知晓其Notification。
FLAG_ACTIVITY_PREVIOUS_IS_TOP
Ifsetandthisintentisbeingusedtolaunchanewactivityfromanexistingone,thecurrentactivitywillnotbecountedasthetopactivityfordecidingwhetherthenewintentshouldbedeliveredtothetopinsteadofstartinganewone.Thepreviousactivitywillbeusedasthetop,withtheassumptionbeingthatthecurrentactivitywillfinishitselfimmediately.
FLAG_ACTIVITY_REORDER_TO_FRONT
如果在Intent中设置,并传递给Context.startActivity(),这个标志将引发已经运行的Activity移动到历史stack的顶端。
例如,假设一个Task由四个Activity组成:A,B,C,D。如果D调用startActivity()来启动ActivityB,那么,B会移动到历史stack的顶端,现在的次序变成A,C,D,B。如果FLAG_ACTIVITY_CLEAR_TOP标志也设置的话,那么这个标志将被忽略。
9、请描述下Activity的生命周期。
答:activity的生命周期方法有:onCreate()、onStart()、onReStart()、onResume()、onPause()、onStop()、onDestory();
可见生命周期:从onStart()直到系统调用onStop()
前台生命周期:从onResume()直到系统调用onPause()
10、activity在屏幕旋转时的生命周期
答:不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次;设置Activity的android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次;设置Activity的android:configChanges="orientation|keyboardHidden"时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法
11、如何启用Service,如何停用Service。
服务的开发比较简单,如下:
第一步:继承Service类
publicclassSMSServiceextendsService{}
第二步:在AndroidManifest.xml文件中的<application>节点里对服务进行配置:<serviceandroid: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()方法启动服务时才会回调该方法。该方法在调用者与服务解除绑定时被调用
12、注册广播有几种方式,这些方式有何优缺点?请谈谈Android引入广播机制的用意。
答:首先写一个类要继承BroadcastReceiver
第一种:在清单文件中声明,添加
<receiveandroid:name=".IncomingSMSReceiver">
<intent-filter>
<actionandroid:name="android.provider.Telephony.SMS_RECEIVED")
<intent-filter>
<receiver>
第二种使用代码进行注册如:
IntentFilterfilter=newIntentFilter("android.provider.Telephony.SMS_RECEIVED");
IncomingSMSReceiverreceiver=newIncomgSMSReceiver();
registerReceiver(receiver.filter);
两种注册类型的区别是:
1)第一种不是常驻型广播,也就是说广播跟随程序的生命周期。
2)第二种是常驻型,也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行。
13、请解释下在单线程模型中Message、Handler、MessageQueue、Looper之间的关系。
答:简单的说,Handler获取当前线程中的looper对象,looper用来从存放Message的MessageQueue中取出Message,再有Handler进行Message的分发和处理.
MessageQueue(消息队列):用来存放通过Handler发布的消息,通常附属于某一个创建它的线程,可以通过Looper.myQueue()得到当前线程的消息队列
Handler:可以发布或者处理一个消息或者操作一个Runnable,通过Handler发布消息,消息将只会发送到与它关联的消息队列,然也只能处理该消息队列中的消息
Looper:是Handler和消息队列之间通讯桥梁,程序组件首先通过Handler把消息传递给Looper,Looper把消息放入队列。Looper也把消息队列里的消息广播给所有的
Handler:Handler接受到消息后调用handleMessage进行处理
Message:消息的类型,在Handler类中的handleMessage方法中得到单个的消息进行处理
在单线程模型下,为了线程通信问题,Android设计了一个MessageQueue(消息队列),线程间可以通过该MessageQueue并结合Handler和Looper组件进行信息交换。下面将对它们进行分别介绍:
1.Message
Message消息,理解为线程间交流的信息,处理数据后台线程需要更新UI,则发送Message内含一些数据给UI线程。
2.Handler
Handler处理者,是Message的主要处理者,负责Message的发送,Message内容的执行处理。后台线程就是通过传进来的Handler对象引用来sendMessage(Message)。而使用Handler,需要implement该类的handleMessage(Message)方法,它是处理这些Message的操作内容,例如UpdateUI。通常需要子类化Handler来实现handleMessage方法。
3.MessageQueue
MessageQueue消息队列,用来存放通过Handler发布的消息,按照先进先出执行。
每个messagequeue都会有一个对应的Handler。Handler会向messagequeue通过两种方法发送消息:sendMessage或post。这两种消息都会插在messagequeue队尾并按先进先出执行。但通过这两种方法发送的消息执行的方式略有不同:通过sendMessage发送的是一个message对象,会被Handler的handleMessage()函数处理;而通过post方法发送的是一个runnable对象,则会自己执行。
4.Looper
Looper是每条线程里的MessageQueue的管家。Android没有Global的MessageQueue,而Android会自动替主线程(UI线程)建立MessageQueue,但在子线程里并没有建立MessageQueue。所以调用Looper.getMainLooper()得到的主线程的Looper不为NULL,但调用Looper.myLooper()得到当前线程的Looper就有可能为NULL。对于子线程使用Looper,APIDoc提供了正确的使用方法:这个Message机制的大概流程:
1.在Looper.loop()方法运行开始后,循环地按照接收顺序取出MessageQueue里面的非NULL的Message。
2.一开始MessageQueue里面的Message都是NULL的。当Handler.sendMessage(Message)到MessageQueue,该函数里面设置了那个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对象。
14、简要解释一下activity、intent、intentfilter、service、Broadcase、BroadcaseReceiver
答:一个activity呈现了一个用户可以操作的可视化用户界面;一个service不包含可见的用户界面,而是在后台运行,可以与一个activity绑定,通过绑定暴露出来接口并与其进行通信;一个broadcastreceiver是一个接收广播消息并做出回应的component,broadcastreceiver没有界面;一个intent是一个Intent对象,它保存了消息的内容。对于activity和service来说,它指定了请求的操作名称和待操作数据的URI,Intent对象可以显式的指定一个目标component。如果这样的话,android会找到这个component(基于manifest文件中的声明)并激活它。但如果一个目标不是显式指定的,android必须找到响应intent的最佳component。它是通过将Intent对象和目标的intentfilter相比较来完成这一工作的;一个component的intentfilter告诉android该component能处理的intent。intentfilter也是在manifest文件中声明的。
15、说说mvc模式的原理,它在android中的运用,android的官方建议应用程序的开发采用mvc模式。何谓mvc?
mvc是model,view,controller的缩写,mvc包含三个部分:
模型(model)对象:是应用程序的主体部分,所有的业务逻辑都应该写在该层。
视图(view)对象:是应用程序中负责生成用户界面的部分。也是在整个mvc架构中用户唯一可以看到的一层,接收用户的输入,显示处理结果。
控制器(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里面处理,当然对业务计算等操作也是必须放在的该层的。
16、什么是ANR如何避免它?
答:ANR:ApplicationNotResponding。在Android中,活动管理器和窗口管理器这两个系统服务负责监视应用程序的响应,当用户操作的在5s内应用程序没能做出反应,BroadcastReceiver在10秒内没有执行完毕,就会出现应用程序无响应对话框,这既是ANR。
避免方法:Activity应该在它的关键生命周期方法(如onCreate()和onResume())里尽可能少的去做创建操作。潜在的耗时操作,例如网络或数据库操作,或者高耗时的计算如改变位图尺寸,应该在子线程里(或者异步方式)来完成。主线程应该为子线程提供一个Handler,以便完成时能够提交给主线程。
17、什么情况会导致ForceClose?如何避免?能否捕获导致其的异常?
答:程序出现异常,比如nullpointer。
避免:编写程序时逻辑连贯,思维缜密。能捕获异常,在logcat中能看到异常信息
18、描述一下android的系统架构
android系统架构分从下往上为linux内核层、运行库、应用程序框架层、和应用程序层。
linuxkernel:负责硬件的驱动程序、网络、电源、系统安全以及内存管理等功能。
libraries和androidruntime:libraries:即c/c++函数库部分,大多数都是开放源代码的函数库,例如webkit(引擎),该函数库负责android网页浏览器的运行,例如标准的c函数库libc、openssl、sqlite等,当然也包括支持游戏开发2dsgl和3dopengles,在多媒体方面有mediaframework框架来支持各种影音和图形文件的播放与显示,例如mpeg4、h.264、mp3、aac、amr、jpg和png等众多的多媒体文件格式。android的runtime负责解释和执行生成的dalvik格式的字节码。
applicationframework(应用软件架构),java应用程序开发人员主要是使用该层封装好的api进行快速开发。
applications:该层是java的应用程序层,android内置的googlemaps、e-mail、即时通信工具、浏览器、mp3播放器等处于该层,java开发人员开发的程序也处于该层,而且和内置的应用程序具有平等的位置,可以调用内置的应用程序,也可以替换内置的应用程序。
上面的四个层次,下层为上层服务,上层需要下层的支持,调用下层的服务,这种严格分层的方式带来的极大的稳定性、灵活性和可扩展性,使得不同层的开发人员可以按照规范专心特定层的开发。
android应用程序使用框架的api并在框架下运行,这就带来了程序开发的高度一致性,另一方面也告诉我们,要想写出优质高效的程序就必须对整个applicationframework进行非常深入的理解。精通applicationframework,你就可以真正的理解android的设计和运行机制,也就更能够驾驭整个应用层的开发。
19、请介绍下ContentProvider是如何实现数据共享的。
一个程序可以通过实现一个Contentprovider的抽象接口将自己的数据完全暴露出去,而且Contentproviders是以类似数据库中表的方式将数据暴露。Contentproviders存储和检索数据,通过它可以让所有的应用程序访问到,这也是应用程序之间唯一共享数据的方法。
要想使应用程序的数据公开化,可通过2种方法:创建一个属于你自己的Contentprovider或者将你的数据添加到一个已经存在的Contentprovider中,前提是有相同数据类型并且有写入Contentprovider的权限。
如何通过一套标准及统一的接口获取其他应用程序暴露的数据?
Android提供了ContentResolver,外界的程序可以通过ContentResolver接口访问ContentProvider提供的数据。
20、Service和Thread的区别?
答:servie是系统的组件,它由系统进程托管(servicemanager);它们之间的通信类似于client和server,是一种轻量级的ipc通信,这种通信的载体是binder,它是在linux层交换信息的一种ipc。而thread是由本应用程序托管。1).Thread:Thread是程序执行的最小单元,它是分配CPU的基本单位。可以用Thread来执行一些异步的操作。
2).Service:Service是android的一种机制,当它运行的时候如果是LocalService,那么对应的Service是运行在主进程的main线程上的。如:onCreate,onStart这些函数在被系统调用的时候都是在主进程的main线程上运行的。如果是RemoteService,那么对应的Service则是运行在独立进程的main线程上。
既然这样,那么我们为什么要用Service呢?其实这跟android的系统机制有关,我们先拿Thread来说。Thread的运行是独立于Activity的,也就是说当一个Activity被finish之后,如果你没有主动停止Thread或者Thread里的run方法没有执行完毕的话,Thread也会一直执行。因此这里会出现一个问题:当Activity被finish之后,你不再持有该Thread的引用。另一方面,你没有办法在不同的Activity中对同一Thread进行控制。
举个例子:如果你的Thread需要不停地隔一段时间就要连接服务器做某种同步的话,该Thread需要在Activity没有start的时候也在运行。这个时候当你start一个Activity就没有办法在该Activity里面控制之前创建的Thread。因此你便需要创建并启动一个Service,在Service里面创建、运行并控制该Thread,这样便解决了该问题(因为任何Activity都可以控制同一Service,而系统也只会创建一个对应Service的实例)。
因此你可以把Service想象成一种消息服务,而你可以在任何有Context的地方调用Context.startService、Context.stopService、Context.bindService,Context.unbindService,来控制它,你也可以在Service里注册BroadcastReceiver,在其他地方通过发送broadcast来控制它,当然这些都是Thread做不到的。
21、Android本身的api并未声明会抛出异常,则其在运行时有无可能抛出runtime异常,你遇到过吗?诺有的话会导致什么问题?如何解决?
答:会,比如nullpointerException。我遇到过,比如textview.setText()时,textview没有初始化。会导致程序无法正常运行出现forceclose。打开控制台查看logcat信息找出异常信息并修改程序。
22、IntentService有何优点?
答:Acitivity的进程,当处理Intent的时候,会产生一个对应的Service;Android的进程处理器现在会尽可能的不kill掉你;非常容易使用
23、如果后台的Activity由于某原因被系统回收了,如何在被系统回收之前保存当前状态?
答:重写onSaveInstanceState()方法,在此方法中保存需要保存的数据,该方法将会在activity被回收之前调用。通过重写onRestoreInstanceState()方法可以从中提取保存好的数据
24、如何将一个Activity设置成窗口的样式。
答:<activity>中配置:android:theme="@android:style/Theme.Dialog"
另外android:theme="@android:style/Theme.Translucent"是设置透明
25、如何退出Activity?如何安全退出已调用多个Activity的Application?
答:对于单一Activity的应用来说,退出很简单,直接finish()即可。当然,也可以用killProcess()和System.exit()这样的方法。
对于多个activity,1、记录打开的Activity:每打开一个Activity,就记录下来。在需要退出时,关闭每一个Activity即可。2、发送特定广播:在需要结束应用时,发送一个特定的广播,每个Activity收到广播后,关闭即可。3、递归退出:在打开新的Activity时使用startActivityForResult,然后自己加标志,在onActivityResult中处理,递归关闭。为了编程方便,最好定义一个Activity基类,处理这些共通问题。
在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、抛异常强制退出:
该方法通过抛异常,使程序ForceClose。
验证可以,但是,需要解决的问题是,如何使程序结束掉,而不弹出ForceClose的窗口。
2、记录打开的Activity:
每打开一个Activity,就记录下来。在需要退出时,关闭每一个Activity即可。
3、发送特定广播:
在需要结束应用时,发送一个特定的广播,每个Activity收到广播后,关闭即可。
4、递归退出
在打开新的Activity时使用startActivityForResult,然后自己加标志,在onActivityResult中处理,递归关闭。
除了第一个,都是想办法把每一个Activity都结束掉,间接达到目的。但是这样做同样不完美。你会发现,如果自己的应用程序对每一个Activity都设置了nosensor,在两个Activity结束的间隙,sensor可能有效了。但至少,我们的目的达到了,而且没有影响用户使用。为了编程方便,最好定义一个Activity基类,处理这些共通问题。
26、AIDL的全称是什么?如何工作?能处理哪些类型的数据?
答:全称是:AndroidInterfaceDefineLanguage
在Android中,每个应用程序都可以有自己的进程.在写UI应用的时候,经常要用到Service.在不同的进程中,怎样传递对象呢?显然,Java中不允许跨进程内存共享.因此传递对象,只能把对象拆分成操作系统能理解的简单形式,以达到跨界对象访问的目的.在J2EE中,采用RMI的方式,可以通过序列化传递对象.在Android中,则采用AIDL的方式.理论上AIDL可以传递Bundle,实际上做起来却比较麻烦。
AIDL(AndRoid接口描述语言)是一种借口描述语言;编译器可以通过aidl文件生成一段代码,通过预先定义的接口达到两个进程内部通信进程的目的.如果需要在一个Activity中,访问另一个Service中的某个对象,需要先将对象转化成AIDL可识别的参数(可能是多个参数),然后使用AIDL来传递这些参数,在消息的接收端,使用这些参数组装成自己需要的对象.
AIDL的IPC的机制和COM或CORBA类似,是基于接口的,但它是轻量级的。它使用代理类在客户端和实现层间传递值.如果要使用AIDL,需要完成2件事情:1.引入AIDL的相关类.;2.调用aidl产生的class.
AIDL的创建方法:
AIDL语法很简单,可以用来声明一个带一个或多个方法的接口,也可以传递参数和返回值。由于远程调用的需要,这些参数和返回值并不是任何类型.下面是些AIDL支持的数据类型:
1.不需要import声明的简单Java编程语言类型(int,boolean等)
2.String,CharSequence不需要特殊声明
3.List,Map和Parcelables类型,这些类型内所包含的数据成员也只能是简单数据类型,String等其他比支持的类型.
(另外:我没尝试Parcelables,在Eclipse+ADT下编译不过,或许以后会有所支持)
27、请解释下Android程序运行时权限与文件系统权限的区别。
答:运行时权限Dalvik(android授权)
文件系统linux内核授权
28、系统上安装了多种浏览器,能否指定某浏览器访问指定页面?请说明原由。
通过直接发送Uri把参数带过去,或者通过manifest里的intentfilter里的data属性
29、android系统的优势和不足
答:Android平台手机5大优势:
一、开放性
在优势方面,Android平台首先就是其开发性,开发的平台允许任何移动终端厂商加入到Android联盟中来。显著的开放性可以使其拥有更多的开发者,随着用户和应用的日益丰富,一个崭新的平台也将很快走向成熟。开放性对于Android的发展而言,有利于积累人气,这里的人气包括消费者和厂商,而对于消费者来讲,随大的受益正是丰富的软件资源。开放的平台也会带来更大竞争,如此一来,消费者将可以用更低的价位购得心仪的手机。
二、挣脱运营商的束缚
在过去很长的一段时间,特别是在欧美地区,手机应用往往受到运营商制约,使用什么功能接入什么网络,几乎都受到运营商的控制。从去年iPhone上市,用户可以更加方便地连接网络,运营商的制约减少。随着EDGE、HSDPA这些2G至3G移动网络的逐步过渡和提升,手机随意接入网络已不是运营商口中的笑谈,当你可以通过手机IM软件方便地进行即时聊天时,再回想不久前天价的彩信和图铃下载业务,是不是像噩梦一样?互联网巨头Google推动的Android终端天生就有网络特色,将让用户离互联网更近。
三、丰富的硬件选择
这一点还是与Android平台的开放性相关,由于Android的开放性,众多的厂商会推出千奇百怪,功能特色各具的多种产品。功能上的差异和特色,却不会影响到数据同步、甚至软件的兼容,好比你从诺基亚Symbian风格手机一下改用苹果iPhone,同时还可将Symbian中优秀的软件带到iPhone上使用、联系人等资料更是可以方便地转移,是不是非常方便呢?
四、不受任何限制的开发商
Android平台提供给第三方开发商一个十分宽泛、自由的环境,不会受到各种条条框框的阻扰,可想而知,会有多少新颖别致的软件会诞生。但也有其两面性,血腥、暴力、情色方面的程序和游戏如可控制正是留给Android难题之一。
五、无缝结合的Google应用
如今叱诧互联网的Google已经走过10年度历史,从搜索巨人到全面的互联网渗透,Google服务如地图、邮件、搜索等已经成为连接用户和互联网的重要纽带,而Android平台手机将无缝结合这些优秀的Google服务。
再说Android的5大不足:
一、安全和隐私
由于手机与互联网的紧密联系,个人隐私很难得到保守。除了上网过程中经意或不经意留下的个人足迹,Google这个巨人也时时站在你的身后,洞穿一切,因此,互联网的深入将会带来新一轮的隐私危机。
二、首先开卖Android手机的不是最大运营商
众所周知,T-Mobile在23日,于美国纽约发布了Android首款手机G1。但是在北美市场,最大的两家运营商乃AT&T和Verizon,而目前所知取得Android手机销售权的仅有T-Mobile和Sprint,其中T-Mobile的3G网络相对于其他三家也要逊色不少,因此,用户可以买账购买G1,能否体验到最佳的3G网络服务则要另当别论了!
三、运营商仍然能够影响到Android手机
在国内市场,不少用户对购得移动定制机不满,感觉所购的手机被人涂画了广告一般。这样的情况在国外市场同样出现。Android手机的另一发售运营商Sprint就将在其机型中内置其手机商店程序。
四、同类机型用户减少
在不少手机论坛都会有针对某一型号的子论坛,对一款手机的使用心得交流,并分享软件资源。而对于Android平台手机,由于厂商丰富,产品类型多样,这样使用同一款机型的用户越来越少,缺少统一机型的程序强化。举个稍显不当的例子,现在山寨机泛滥,品种各异,就很少有专门针对某个型号山寨机的讨论和群组,除了哪些功能异常抢眼、颇受追捧的机型以外。
五、过分依赖开发商缺少标准配置
在使用PC端的WindowsXp系统的时候,都会内置微软WindowsMediaPlayer这样一个浏览器程序,用户可以选择更多样的播放器,如Realplay或暴风影音等。但入手开始使用默认的程序同样可以应付多样的需要。在Android平台中,由于其开放性,软件更多依赖第三方厂商,比如Android系统的SDK中就没有内置音乐播放器,全部依赖第三方开发,缺少了产品的统一性。
30、Androiddvm的进程和Linux的进程,应用程序的进程是否为同一个概念
答:DVM指dalivk的虚拟机。每一个Android应用程序都在它自己的进程中运行,都拥有一个独立的Dalvik虚拟机实例。而每一个DVM都是在Linux中的一个进程,所以说可以认为是同一个概念。
31、sim卡的EF文件是什么?有何作用
答:sim卡的文件系统有自己规范,主要是为了和手机通讯,sim本身可以有自己的操作系统,EF就是作存储并和手机通讯用的
32、嵌入式操作系统内存管理有哪几种,各有何特性
页式,段式,段页,用到了MMU,虚拟空间等技术
33、什么是嵌入式实时操作系统,Android操作系统属于实时操作系统吗?
嵌入式实时操作系统是指当外界事件或数据产生时,能够接受并以足够快的速度予以处理,其处理的结果又能在规定的时间之内来控制生产过程或对处理系统作出快速响应,并控制所有实时任务协调一致运行的嵌入式操作系统。主要用于工业控制、军事设备、航空航天等领域对系统的响应时间有苛刻的要求,这就需要使用实时系统。又可分为软实时和硬实时两种,而android是基于linux内核的,因此属于软实时。
34、一条最长的短信息约占多少byte?
中文70(包括标点),英文160,160个字节。
35、有一个一维整型数组int[]data保存的是一张宽为width,高为height的图片像素值信息。请写一个算法,将该图片所有的白色不透明(0xffffffff)像素点的透明度调整为50%。
36、如何将SQLite数据库(dictionary.db文件)与apk文件一起发布
解答:可以将dictionary.db文件复制到EclipseAndroid工程中的resaw目录中。所有在resaw目录中的文件不会被压缩,这样可以直接提取该目录中的文件。可以将dictionary.db文件复制到resaw目录中
37、如何将打开resaw目录中的数据库文件?
解答:在Android中不能直接打开resaw目录中的数据库文件,而需要在程序第一次启动时将该文件复制到手机内存或SD卡的某个目录中,然后再打开该数据库文件。
复制的基本方法是使用getResources().openRawResource方法获得resaw目录中资源的InputStream对象,然后将该InputStream对象中的数据写入其他的目录中相应文件中。在AndroidSDK中可以使用SQLiteDatabase.openOrCreateDatabase方法来打开任意目录中的SQLite数据库文件。
38、DDMS和TraceView的区别?
DDMS是一个程序执行查看器,在里面可以看见线程和堆栈等信息,TraceView是程序性能分析器。
39、java中如何引用本地语言
可以用JNI(javanativeinterfacejava本地接口)接口。
40、谈谈Android的IPC(进程间通信)机制
IPC是内部进程通信的简称,是共享"命名管道"的资源。Android中的IPC机制是为了让Activity和Service之间可以随时的进行交互,故在Android中该机制,只适用于Activity和Service之间的通信,类似于远程方法调用,类似于C/S模式的访问。通过定义AIDL接口文件来定义IPC接口。Servier端实现IPC接口,Client端调用IPC接口本地代理。
41、NDK是什么
NDK是一些列工具的集合,NDK提供了一系列的工具,帮助开发者迅速的开发C/C++的动态库,并能自动将so和java应用打成apk包。
NDK集成了交叉编译器,并提供了相应的mk文件和隔离cpu、平台等的差异,开发人员只需简单的修改mk文件就可以创建出so
Java面试题
C/S与B/S区别:
1.硬件环境不同:
C/S一般建立在专用的网络上,小范围里的网络环境,局域网之间再通过专门服务器提供连接和数据交换服务.
B/S建立在广域网之上的,不必是专门的网络硬件环境,例与电话上网,租用设备.信息自己管理.有比C/S更强的适应范围,一般只要有操作系统和浏览器就行
2.对安全要求不同
C/S一般面向相对固定的用户群,对信息安全的控制能力很强.一般高度机密的信息系统采用C/S结构适宜.可以通过B/S发布部分可公开信息.
B/S建立在广域网之上,对安全的控制能力相对弱,可能面向不可知的用户。
3.对程序架构不同
C/S程序可以更加注重流程,可以对权限多层次校验,对系统运行速度可以较少考虑.
B/S对安全以及访问速度的多重的考虑,建立在需要更加优化的基础之上.比C/S有更高的要求B/S结构的程序架构是发展的趋势,从MS的.Net系列的BizTalk2000Exchange2000等,全面支持网络的构件搭建的系统.SUN和IBM推的JavaBean构件技术等,使B/S更加成熟.
4.软件重用不同
C/S程序可以不可避免的整体性考虑,构件的重用性不如在B/S要求下的构件的重用性好.
B/S对的多重结构,要求构件相对独立的功能.能够相对较好的重用.就入买来的餐桌可以再利用,而不是做在墙上的石头桌子
5.系统维护不同
C/S程序由于整体性,必须整体考察,处理出现的问题以及系统升级.升级难.可能是再做一个全新的系统
B/S构件组成,方面构件个别的更换,实现系统的无缝升级.系统维护开销减到最小.用户从网上自己下载安装就可以实现升级.
6.处理问题不同
C/S程序可以处理用户面固定,并且在相同区域,安全要求高需求,与操作系统相关.应该都是相同的系统
B/S建立在广域网上,面向不同的用户群,分散地域,这是C/S无法作到的.与操作系统平台关系最小.
7.用户接口不同
C/S多是建立的Window平台上,表现方法有限,对程序员普遍要求较高
B/S建立在浏览器上,有更加丰富和生动的表现方式与用户交流.并且大部分难度减低,减低开发成本.
8.信息流不同
C/S程序一般是典型的中央集权的机械式处理,交互性相对低
B/S信息流向可变化,B-BB-CB-G等信息、流向的变化,更像交易中心。
安卓面试题
1、什么是ANR如何避免它?
ANR定义
在Android上,如果你的应用程序有一段时间响应不够灵敏,系统会向用户
显示一个对话框,这个对话框称作应用程序无响应(ANR:ApplicationNot
Responding)对话框。用户可以选择让程序继续运行,但是,他们在使用你的应
用程序时,并不希望每次都要处理这个对话框。因此,在程序里对响应性能的设
计很重要,这样,系统不会显示ANR给用户。
如何来避免:
考虑上面的ANR定义,让我们来研究一下为什么它会在Android应用程序里发生和
如何最佳构建应用程序来避免ANR。
Android应用程序通常是运行在一个单独的线程(例如,main)里。这意味着你
的应用程序所做的事情如果在主线程里占用了太长的时间的话,就会引发ANR对
话框,因为你的应用程序并没有给自己机会来处理输入事件或者Intent广播。
因此,运行在主线程里的任何方法都尽可能少做事情。特别是,Activity应该在
它的关键生命周期方法(如onCreate()和onResume())里尽可能少的去做创建操
作。潜在的耗时操作,例如网络或数据库操作,或者高耗时的计算如改变位图尺
寸,应该在子线程里(或者以数据库操作为例,通过异步请求的方式)来完成。
然而,不是说你的主线程阻塞在那里等待子线程的完成——也不是调用
Thread.wait()或是Thread.sleep()。替代的方法是,主线程应该为子线程提供
一个Handler,以便完成时能够提交给主线程。以这种方式设计你的应用程序,
将能保证你的主线程保持对输入的响应性并能避免由于5秒输入事件的超时引发
的ANR对话框。这种做法应该在其它显示UI的线程里效仿,因为它们都受相同的
超时影响。
IntentReceiver执行时间的特殊限制意味着它应该做:在后台里做小的、琐碎的
工作如保存设定或者注册一个Notification。和在主线程里调用的其它方法一样
,应用程序应该避免在BroadcastReceiver里做耗时的操作或计算。但不再是在
子线程里做这些任务(因为BroadcastReceiver的生命周期短),替代的是,如
果响应Intent广播需要执行一个耗时的动作的话,应用程序应该启动一个
Service。顺便提及一句,你也应该避免在IntentReceiver里启动一个Activity
,因为它会创建一个新的画面,并从当前用户正在运行的程序上抢夺焦点。如果
你的应用程序在响应Intent广播时需要向用户展示什么,你应该使用
NotificationManager来实现。
一般来说,在应用程序里,100到200ms是用户能感知阻滞的时间阈值。因此,这
里有一些额外的技巧来避免ANR,并有助于让你的应用程序看起来有响应性。
如果你的应用程序为响应用户输入正在后台工作的话,可以显示工作的进度
(ProgressBar和ProgressDialog对这种情况来说很有用)。
特别是游戏,在子线程里做移动的计算。
如果你的应用程序有一个耗时的初始化过程的话,考虑可以显示一个Splash
Screen或者快速显示主画面并异步来填充这些信息。在这两种情况下,你都应该
显示正在进行的进度,以免用户认为应用程序被冻结了。
华为面试题:
一单项选择题(每题中只有一个正确答案,每题1分,共80题。)
<计算机基础>2题
01.下列一组数据中的最大数是______。(A)
A.311(8)
B.C7(16)
C.11001000(2)
D.200(10)
02.PowerPoint中,有关选定幻灯片的说法中错误的是______。(D)
A.在浏览视图中单击幻灯片,即可选定。
B.如果要选定多张不连续幻灯片,在浏览视图下按CTRL键并单击各张幻灯片。
C.如果要选定多张连续幻灯片,在浏览视图下,按下shift键并单击最后要选定的幻灯片。
D.在幻灯片视图下,也可以选定多个幻灯片。
<网络基础>13题
03.以下哪个路由表项需要由网络管理员手动配置________。(A)
A.静态路由
B.直接路由
C.动态路由
D.以上说法都不正确
04.以下命令中哪一个命令是配置Cisco1900系列交换机特权级密码________。(A)
A.enablepasswordciscolevel15
B.enablepasswordcsico
C.enablesecretcsico
D.enablepasswordlevel15
05.以下哪个命令可以保存路由器RAM中的配置文件到NVRAM中________。(C)
A.copyrunning-configtftp
B.copystartup-configtftp
C.copyrunning-configstartup-config
D.copystartup-configrunning-config
06.在掉电状态下,哪种类型的存储器不保留其内容_______?(C)
A.NVRAM
B.ROM
C.RAM
D.Flash
07.以下配置默认路由的命令正确的是:________。(A)
A.iproute0.0.0.00.0.0.0172.16.2.1
B.iproute0.0.0.0255.255.255.255172.16.2.1
C.iprouter0.0.0.00.0.0.0172.16.2.1
D.iprouter0.0.0.00.0.0.0172.16.2.1
08.以下哪种协议属于网络层协议的_______。(B)
A.HTTPS
B.ICMP
C.SSL
D.SNMP
09.目前网络传输介质中传输安全性最高的是______。(A)
A.光纤
B.同轴电缆
C.电话线
D.双绞线
10.如果两台交换机直接用双绞线相连,其中一端采用了,白橙/橙/白绿/蓝/白蓝/绿/白棕/棕的线序,另一端选择哪一种线序排列是正确的_______。(B)
A.白绿/绿/白橙/橙/白蓝/蓝/白棕/棕
B.白绿/绿/白橙/蓝/白蓝/橙/白棕/棕
C.白橙/橙/白绿/绿/白蓝/蓝/白棕/棕
D.白橙/橙/白绿/蓝/白蓝/绿/白棕/棕
11.CSMA/CD协议在站点发送数据时________。(A)
A.一直侦听总线活动。
B.仅发送数据,然后等待确认。
C.不侦听总线活动
D.当数据长度超过1000字节时需要侦听总线活动。
12.802.11g+的传输速度为:_______。(C)
A.54Mbps
B.100Mbps
C.108Mbps
D.118Mbps
13.某IP地址为160.55.115.24/20,它的子网划分出来的网络ID地址_____。(A)
A.160.55.112.0
B.160.55.115.0
C.160.55.112.24
D.以上答案都不对
14.将200.200.201.0这个网络进行子网的划分,要求尽可能划分出最多的网段,但每个网段不能少于5台计算机,该子网的子网掩码是_______。(C)
A.255.255.255.240
B.255.255.255.252
C.255.255.255.248
D.255.255.255.0
15.IP地址是一个32位的二进制数,它通常采用点分________。
A.二进制数表示
B.八进制数表示
C.十进制数表示
D.十六进制数表示
<Windows系统管理>12题
16.下列那种配置的计算机可以安装Windows2000Server:_______。(B)
A.Pentium133MHz/32M内存/10G硬盘自由空间
B.PentiumII300MHz/256M内存/10G硬盘自由空间
C.Pentium100MHz/128M内存/10G硬盘自由空间
D.PentiumII300MHz/256M内存/500M硬盘自由空间
17.在Windows2000AdvancedServer最多支持的处理器数量是______。(C)
A.2 B.4 C.8 D.16
18.在Windows2000操作系统中,登陆时使用的用户名对应的密码保存的路径______。(B)
A.C:\WINDOWS\system32\config\SAMwindows2003开始选择A.
B.C:\WINNT\system32\config\SAM
C.C:\WINDOWS\system\config\SAM
D.C:\WINNT\system\config\SAM
19.在Windows2000中,当程序因某种原因陷入死循环,下列哪一个方法能较好地结束该程序______。
A.按Ctrl+Shift+Esc键,然后选择“结束任务”结束该程序的运行
B.按Ctrl+Del键,然后选择“结束任务”结束该程序的运行
C.按Alt+Del键,然后选择“结束任务”结束该程序的运行
D.直接Reset计算机结束该程序的运行
20.Windows2003操作系统有多少个版本_______。(C)
A.2
B.3
C.4
D.5
21.如果我们将某文件夹的本地权限设为“Everyone读取”,而将该文件夹的共享权限设为“Everyone更改”。那么当某用户通过网络访问该共享文件夹时将拥有_______。(D)
A.更改权限
B.完全控制权限
C.写入权限
D.读取权限
22.下面哪个是WindowsXP操作系统的启动文件________。A.format.com
B.auto.com
C.boot.ini
D.ntbootdd.sys
23.当在Windows2000下创建分区时,FAT32分区大小的限制是_________。(C)
A.8GBB.16GBC.32GBD.64GB
24.将FAT分区转化成NTFS分区使用的命令_________。A.format
B.convert
C.fordisk
D.无法确定
25.如果RAID-0卷集由4个40GB磁盘组成,可以存储数据的最大空间为________。(D)
A.40GB
B.80GB
C.120GB
D.160GB
26.公司的一个员工被解雇了,他有权限使计算机的文件成倍增加。你也想让新雇佣的员工具有和他一样的权限,并确保被解雇的员工不能再访问和使用这些文件,应该怎么办________?A.重新命名老员工的帐户给新员工,更改密码
B.复制老员工的权限给新员工,删除老员工帐户
C.复制老员工帐户给新员工,删除老员工帐户
D.删除老员工帐户,将新员工帐户放到老员工原属的组里,并继承老员工的所有权限
27.你的计算机装的Windows2000Professional。当你运行“磁盘碎片整理”程序的时候办公室停电了。重启计算机,你收到如下的错误信息:“不能找到操作系统或操作系统已坏”你该怎么做呢________。A.用安全模式进入计算机,重新格式化硬盘
B.用调试模式进入计算机,重新格式化硬盘
C.用应急磁盘启动计算机,准备恢复主引导记录
D.用光驱启动计算机,用恢复控制台准备恢复主引导记录
<Windows服务器管理>12题
28.为了使活动目录服务和相关的客户软件运行正常,你必须安装和配置________。(D)
A.Protocol
B.Gateway
C.WINS
D.DNS
29.在WindowsServer2003服务器上配置DHCP服务时,IP地址租约默认是:________。
A.4天
B.8天
C.16天
D.20天
30.在一个域目录树中,父域与其子域具有________。(C)
A.单项不可传递信任关系
B.双向不可传递信任关系
C.双向可传递信任关系
D.以上都不正确
31.Windows2000活动目录使用________目录协议完成查询与更新。(B)
A.DNSB.LDAPC.TCP/IPD.DHCP
32.在计算机名为huayu的WindowsServer2003服务器上安装IIS后,把IWAN_huayu用户删除或改密码后________。(A)
A.动态网页和程序无法运行
B.静态网页和程序无法运行
C.任何网页和程序无法运行
D.任何网页可运行,程序无法运行
33.在计算机名为huayu的WindowsServer2003服务器上利用IIS搭建好FTP服务器后,建立用户为jacky,密码为123,如何直接用IE来访问________。(C)
A.http://jacky:123@huayu
B.ftp://123:jacky@huayu
C.ftp://jacky:123@huayu
D.http://123:jacky@huayu
34.WindowsServer2003操作系统比Windows2000Server操作系统多了下列哪项服务________。
A.NNTP
B.POP3
C.SMTP
D.FTP
35.想要完全释放计算机的IP地址在Dos提示符下输入的命令为______。(B)
A.IPCONFIG/ALL
B.IPCONFIG/RENEW
C.IPCONFIG/RELEASE
D.WINIPCFG
36.DNS服务器中,的MX记录表示______。
A.邮件记录
B.主机记录
C.资源记录
D.更新记录
37.Windows2000下诊断DNS故障时,最常用的命令是:______。
A.NETSTAT
B.NSLOOKUP
C.ROUTE
D.NBTSTAT
38.小强在公司要查询www.tsinghua.edu.cn这个DNS名称对应的IP地址时,其正确的查询过程是:______。(A)
①.查询公司默认的DNS服务器
②.查询ROOTDNS服务器
③.查询.CN域的DNS服务器
④.查询.EDU.CN域的DNS服务器
⑤.查询.TSINGHUA.EDU.CN域的DNS服务器
A.①②③④⑤
B.①③④⑤②
C.①⑤
D.⑤④③②①
39.下列对网络服务的描述哪个是错误的:_______。(C)
A.DHCP——动态主机配置协议,动态分配IP地址
B.DNS——域名服务,可将主机域名解析为IP地址
C.WINS——Windows互联网名称服务,可将主机域名解析为IP地址
D.FTP——文件传输协议,可提供文件上传、下载服务
20题
40.系统中有用户user1和user2,同属于users组。在user1用户目录下有一文件file1,它拥有644的权限,如果user2用户想修改user1用户目录下的file1文件,应拥有______权限。(B)
A.744
B.664
C.646
D.746
41.以下哪条命令可以改变文件file的所有者为Sam________?(B)
A.chmodSamfile
B.chownSamfile
C.chgrpSamfile
D.umaskSamfile
42.一个文件的权限为“rwxr—–”,那么以下哪个说法是正确的_______?(B)
A.所有用户都可以执行写操作
B.只有所有者可以执行写操作
C.所有者和所属组可以执行写操作
D.任何人都不能执行写操作
43.下面哪条命令可以把一个压缩的打包文件解压并解包_______?(D)
A.tarcvf
B.tarxvf
C.tarzcvf
D.tarzxvf
44.若要系统中每次缺省添加用户时,都自动设置用户的宿主目录为/users,需修改哪一个配置文件?(A)
A./etc/default/useradd
B./etc/login.defs
C./etc/shadow
D./etc/passwd
45.若命令mkdir具有SetUID的s权限位,问当普通用户Sam执行命令mkdir时,新建的目录所有者为哪个用户________?(C)
A.Sam
B.users
C.root
D.sys
46.当普通用户被root授予某些管理命令的使用权时,问,普通用户使用命令sudo的哪个选项可以查看他可以执行的命令_______?(A)
A.-lB.-aC.-mD.-s
47.哪条命令可以查看到系统中被挂起的进程________?(C)
A.bg
B.renice
C.jobs
D.who
48.Linux系统中的块设备文件在使用命令ls-l查询时用什么符号表示_______?(B)
A.cB.b C.lD.d
49.如果你的umask设置为022,缺省的,你创建的文件的权限为:________。(D)
A.—-w–w-
B.-w–w—-
C.r-xr-x—
D.rw-r–r–
50.在使用了shadow口令的系统中,/etc/passwd和/etc/shadow两个文件的权限正确的是:________。(C)
A.-rw-r—–,-r——–
B.-rw-r–r–,-r–r–r–
C.-rw-r–r–,-r——–
D.-rw-r–rw-,-r—–r–
51.作为一个管理员,你希望在每一个新用户的目录下放一个文件.bashrc,那么你应该在哪个目录下放这个文件,以便于新用户创建主目录时自动将这个文件复制到自己的目录下。(A)
A./etc/skel/
B./etc/default/
C./etc/defaults/
D./etc/profile.d/
52.在linux中有关IDE设备命名编号正确的有________。(D)
A.sda第一个IDE控制器,主设备
B.sdb第二个IDE控制器,次设备
C.hdb第二个IDE控制器,主设备
D.hda第一个IDE控制器,主设备
53.以下哪种不是LINUX的SHELL类型________。(C)
A.bashB.kshC.rshD.csh
54.为保证在启动服务器时自动启动DHCP进程,应对________文件进行编辑。(B)
A./etc/rc.d/rc.inet2
B./etc/rc.d/rc.inet1
C./etc/dhcpd.conf
D./etc/rc.d/rc.S
55.要配置NFS服务器,在服务器端主要配置________文件。(C)
A./etc/rc.d/rc.inet1
B./etc/rc.d/rc.M
C./etc/exports
D./etc/rc.d/rc.S
56.Samba服务器的进程由________两部分组成。(B)
A.named和sendmail
B.smbd和nmbd
C.bootp和dhcpd
D.httpd和squid
57.对于系统中的进程named(进程号2567),可以通过命令________强行结束。(D)
A.servicenamedstop
B./etc/rc.d/init.dnamedstop
C.kill-9named
D.kill-92567
58.如果想配置一台匿名FTP服务器,应修改________文件。(C)
A./etc/gateway
B./etc/ftpservers
C./etc/ftpusers
D./etc/inetd.conf
59.下面能够正确启动sendmail的是________。(C)
A.servicesendmailstart
B.servicexinetdstart
C.在保证dns正确运行的情况下,servicesendmailstart;servicexinetdstart
D.不需要dns,直接servicesendmailstart;servicexinetdstart
<SQLServer>10题
60.若用如下的SQL语句创建了一个表S:CREATETABLES(SIDCHAR(6)NOTNULL,SNAMECHAR(8)NOTNULL,SEXCHAR(2),AGEINTEGER)今向S表插入如下行时,________可以被插入。(B)
A.(‘991001’,‘李明芳’,女,‘23’)
B.(‘990746’,’张为’,NULL,NULL)
C.(,‘陈道一’,‘男’,32)
D.(‘992345’,NULL,‘女’,25)
61.从货物定单数据表(order)中查询出其中定单金额(order_price)在1000和5000之间的定单的详细信息,并按照定单金额(order_price)降序排列。正确的语句是_________。(B)
A.Select*fromorderwhere[order_price]between1000and5000
orderby[order_price]ASC
B.Select*fromorderwhere[order_price]between1000and5000
orderby[order_price]DESC
C.Select*fromorderwhere1000<[order_price]<5000orderby[order_price]ASC
D.Select*fromorderwhere1000<[order_price]<5000orderby[order_price]DESC
62.建立数据库时,将年龄字段值限制在12~14之间的这种约束属于_______。(A)
A.实体完整性约束
B.域完整性约束
C.参照完整性约束
D.视图完整性约束
63.下列有关SQLServer2000中,master数据库的说法不正确的是________。(D)
A.用户数据库可以重命名,master数据库不能重命名
B.master数据库记录SQLServer的所有系统信息
C.master数据库在安装SQLServer的过程中自动安装
D.不可以重建master数据库
64.对数据库的修改操作要遵循的一个原则是:要么操作全部完成,要么不进行操作。这个原则可以认为是事务的___C_____特性。()
A.一致性B.持久性C.原子性D.隔离性
65.查询city列的值为空的记录,在where子句中的条件应写为________。(C)
A.ity=null
B.city='null'
C.cityisnull
D.cityis'null'
66.在SQLSERVER中,下列哪些语句属于给局部变量赋值的语句________。(B)
A.DECLAREB.SETC.USED.GET
67.A表有25条记录,B表有8条记录,执行语句
SELECTA.columnl,B.columnl
FROMALEFFJOINB
WHEREA.column2=B.column2
返回的结果集中的记录数为________。(C)
A.25B.8C.33D.200
68.count与count(*)的区别是________?(D)
A.无区别
B.count是聚合函数,count(*)不是聚合函数
C.count统计空格而COUNT(×)不统计
D.count(*)统计NULL值,而COUNT不统计
69.________包含了一组数据库操作命令,并且所有的命令作为一个整体一起向系统提交或撤消操作请求。(A)
A.事务B.更新C.插入D.以上都不是
11题
70.下面关于表格说法正确的是________。()
A.表格的背景色就是单元格的背景色
B.单元格之间的间距是在标签里设置的
C.
标签代表是列,标签代表的是行
D.表单可以用表格进行排版
71.下面对于表单的标签错误的是________。()
A.
标签是放在
窗体顶端
窗体底端
标签之间的
B.所有的表单标签必须是放在
标签里面
C.可以设置文本框的大小和输入的内容长度
D.
窗体顶端
中的action属性设置的是对传递表单数据处理的脚本的名
72.下面对于html语言写法不正确的是________。(Ds)
A.联系我们
B.联系我们
C.联系我们
D.联系我们
73.frameset的含义是________。(D)
A.表单
B.表格
C.链接
D.框架集
74.如果想获得细的表格边框线的效果,可以_________。(D)
A.可以将table标签中的border属性设置为1
B.可以将table标签中的border属性设置为0
C.手写代码是写不出的
D.可以通过设置表格的背景色与单元格的背景色不同,并且对order,cellspacing,cellpadding的属性值进行控制得到
75.以下HTML代码中,________是将词语“RunAwayBride”显示为Verdana字体并且字号为5号的正确代码。(B)
A.RunAwayBride
B.RunAwayBride
C.“RunAwayBride”
D.
76.在标签中,下列________属性用于给参数传递内容。(B)
A.Address
B.Value
C.Amount
D.Method
77.标记中的SIZE属性的缺省值是________。(B)
A.2
B.3
C.4
D.5
78.使用物理字体标记实现粗斜体的ABC的写法是:________。(A)
A.ABC
B.ABC
C.ABC
D.ABC
79.标记中#取值范围是从1到________。(B)
A.5
B.6
C.7
D.8
80.标记名称由一个字母开始,后面由_______构成,长度限制是_______个字符以内。(A)
A.字母、数字、西文句号、连字符/72
B.字母、数字、西文句号、连字符、空格/36
C.字母、数字、西文句号、空格/64
D.字母、数字、西文句号、连字符、中文字符/48
二多项选择题(每题中至少有两个正确答案,少选、多选、错选均不得分,每题1分,共20分)
81.下列命令中,哪些命令可以使路由器进入线路配置模式________?(BD)
A.vty0
B.linevty04
C.console0
D.lineconsole0
82.在哪两个设备之间可以实现全双工操作________?(AB)
A.交换机到主机
B.交换机到交换机
C.hub到hub
D.交换机到hub
83.以下命令中哪些命令可以看到路由器IOS的信息________。(BC)
A.showrunning-config
B.showflash
C.showversion
D.showstartup-config
84.TCP/IP参考模型中没有________。(CD)
A.网络层
B.传输层
C.会话层
D.表示层
85.下列哪些操作系统可以直接升级到Windows2000Server:______。(AC)
A.WindowsNTServer3.51
B.Windows98
C.WindowsNTServer4.0
D.WindowsNTWorkstation4.0
86.下列对Windows2003域控制器的描述哪些是正确的:_______。(BD)
A.域控制器中存储域的部分目录信息
B.域控制器中存储域的完整目录信息
C.一个域中只能有一台域控制器
D.一个域中可以有多台域控制器
87.在Windows2000Server的内建组中成员可以创建新用户________。A.Users
B.BackupOperators
C.PowerUsers
D.Administrators
88.下列对DNS记录的描述哪些是正确的:_______。(ABC)
A.A记录将主机名映射为IP地址
B.MX记录标识域的邮件交换服务
C.PTR记录将IP地址指向主机名
D.NS记录规定主机的别名
89.要提供DHCP服务,DHCP服务器必需具备哪些条件:________。(ABD)
A.具有静态配置的IP地址
B.具有作用范围的有效IP地址范围
C.配置有缺省网关
D.配置有子网掩码
90.使用分布式文件系统的好处有:________。(ABCD)
A.易于访问文件
B.增加文件访问性
C.服务器负载均衡
D.统一设定文件权限
91.HTML是一个纯文本文档,但是与普通的纯文本文档相比,HTML文档具有以下特点_____(ABCD)
A.结构化
B.超文本
C.与平台无关
D.简单,易维护
92.以下哪些是动态网页的后缀______(AD)
A.*.asp
B.*.txt
C.*.php
D.*.cgi
93.假设当前屏幕分别率为1024×768,定义一个居中的占屏幕一半大小的表格的语句是______。(ABCD)
A.
|
B.
|
C.
|
D.
|
94.下是SQLServer2000数据库文件的有________。(AC)
A.mdf文件
B.mdb文件
C.ldf文件
D.frm文件
95.关于对SQLServer数据库表的重命名,以下的说话正确的是________。(AB)
A.可以在企业管理器中修改表的名称
B.可以在查询分析器中使用T-SQL为表重明名
C.SQLServer2000中,必须执行拷贝粘贴操作才能进行表的结构复制
D.SQLServer2000中,不允许进行表的重命名
96.在Linux操作系统中的/etc/passwd文件包括的基本选项有________。(ABCD)
A.用户ID
B.加密的密码值
C.用户登录Shell
D.用户登录目录
97.启用配额的命令是________。(AB)
A.Usrquota
B.Grpquota
C.Rootquota
D.Userquota
98.配置DNS服务器时,三个最基本的文件是________。(ABC)
A./etc/named.conf(主配置文件)
B./var/named/localhost.zone(正向解析库文件)
C./var/named/named.local(反向解析库文件)
D./etc/reslov.conf(客户端文件)
99.有一台Web服务器(默认端口开启),IP地址为192.168.99.99,通过eth1连接到Linux防火墙,防火墙通过eth0与互联网相连,现在要设置的规则是,允许来自eth0的数据包访问web服务器,下面的配置正确的是:________。(CD)
A.iptabels–AINPUT–ptcp–d192.168.99.99–dport80–ieth0–jACCEPT
B.iptabels–AOUTPUT–ptcp–d192.168.99.99–dport80–oeth0–jACCEPT
C.iptabels–AFORWARD–ptcp–d192.168.99.99–dport80–ieth0–jACCEPT
D.iptabels–AFORWARD–ptcp–d192.168.99.99–dportwww–ieth0–jACCEPT
100./etc/samba/smb.conf主要包括哪几部分________。(ABD)
A.global(全局)参数
B.directoryshares(目录共享)
C.fileshares(文件共享)
D.printershares(打印共享)
窗体底端
Android的消息机制(一)
android 有一种叫消息队列的说法,这里我们可以这样理解:假如一个隧道就是一个消息队列,那么里面的每一部汽车就是一个一个消息,这里我们先忽略掉超车等种种因素,只那么先进隧道的车将会先出,这个机制跟我们android 的消息机制是一样的。
一、角色描述
1.Looper:(相当于隧道)一个线程可以产生一个Looper对象,由它来管理此线程里的Message Queue(车队,消息隧道)。
2.Handler:你可以构造Handler对象来与Looper沟通,以便push新消息到Message Queue里;或者接收Looper(从Message Queue取出)所送来的消息。
3. Message Queue(消息队列):用来存放线程放入的消息。
4.线程:UI thread通常就是main thread,而Android启动程序时会替它建立一个Message Queue。
每一个线程里可含有一个Looper对象以及一个MessageQueue数据结构。在你的应用程序里,可以定义Handler的子类别来接收Looper所送出的消息。
在你的Android程序里,新诞生一个线程,或执行(Thread)时,并不会自动建立其Message Loop。
Android里并没有Global的Message Queue数据结构,例如,不同APK里的对象不能透过Massage Queue来交换讯息(Message)。
例如:线程A的Handler对象可以传递消息给别的线程,让别的线程B或C等能送消息来给线程A(存于A的Message Queue里)。
线程A的Message Queue里的讯息,只有线程A所属的对象可以处理。
使用Looper.myLooper可以取得当前线程的Looper对象。
使用mHandler = new EevntHandler(Looper.myLooper());可用来构造当前线程的Handler对象;其中,EevntHandler是自已实现的Handler的子类别。
使用mHandler = new EevntHandler(Looper.getMainLooper());可诞生用来处理main线程的Handler对象;其中,EevntHandler是自已实现的Handler的子类别。
这样描述可能太抽像,下面举几个实际的例子来说明:
二、举例
1.同线程内不同组件间的消息传递
Looper类用来管理特定线程内对象之间的消息交换(Message Exchange)。你的应用程序可以产生许多个线程。而一个线程可以有许多个组件,这些组件之间常常需要互相交换讯息。如果有这种需要,您可以替线程构造一个Looper对象,来担任讯息交换的管理工作。Looper对象会建立一个MessageQueue数据结构来存放各对象传来的消息(包括UI事件或System事件等)。如下图:
每一个线程里可含有一个Looper对象以及一个MessageQueue数据结构。在你的应用程序里,可以定义Handler的子类别来接收Looper所送出的消息。
同线程不同组件之间的消息传递:
publicclassActivity1extendsActivityimplementsOnClickListener{
Buttonbutton=null;
TextViewtext=null;
@Override
protectedvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity1);
button= (Button)findViewById(R.id.btn);
button.setOnClickListener(this);
text= (TextView)findViewById(R.id.content);
}
publicvoidonClick(View v) {
switch(v.getId()) {
caseR.id.btn:
Looper looper = Looper.myLooper();//取得当前线程里的looper
MyHandler mHandler =newMyHandler(looper);//构造一个handler使之可与looper通信
//buton等组件可以由mHandler将消息传给looper后,再放入messageQueue中,同时mHandler也可以接受来自looper消息
mHandler.removeMessages(0);
String msgStr ="主线程不同组件通信:消息来自button";
Message m = mHandler.obtainMessage(1, 1, 1, msgStr);//构造要传递的消息
mHandler.sendMessage(m);//发送消息:系统会自动调用handleMessage方法来处理消息
break;
}
}
privateclassMyHandlerextendsHandler{
publicMyHandler(Looper looper){
super(looper);
}
@Override
publicvoidhandleMessage(Message msg) {//处理消息
text.setText(msg.obj.toString());
}
}
}
说明:
此程序启动时,当前线程(即主线程, main thread)已诞生了一个Looper对象,并且有了一个MessageQueue数据结构。
looper = Looper.myLooper ();
调用Looper类别的静态myLooper()函数,以取得目前线程里的Looper对象.
mHandler = new MyHandler (looper);
构造一个MyHandler对象来与Looper沟通。Activity等对象可以藉由MyHandler对象来将消息传给Looper,然后放入MessageQueue里;MyHandler对象也扮演Listener的角色,可接收Looper对象所送来的消息。
Message m = mHandler.obtainMessage(1, 1, 1, obj);
先构造一个Message对象,并将数据存入对象里。
mHandler.sendMessage(m);
就透过mHandler对象而将消息m传给Looper,然后放入MessageQueue里。
此时,Looper对象看到MessageQueue里有消息m,就将它广播出去,mHandler对象接到此讯息时,会呼叫其handleMessage()函数来处理,于是输出"This my message!"于画面上,
Android消息处理机制(二)
角色综述(回顾):
(1)UI thread通常就是main thread,而Android启动程序时会替它建立一个MessageQueue。
(2)当然需要一个Looper对象,来管理该MessageQueue。
(3)我们可以构造Handler对象来push新消息到Message Queue里;或者接收Looper(从Message Queue取出)所送来的消息。
(4)线程A的Handler对象可以传递给别的线程,让别的线程B或C等能送讯息来给线程A(存于A的Message Queue里)。
(5)线程A的Message Queue里的消息,只有线程A所属的对象可以处理。
子线程传递消息给主线程
publicclassActivity2extendsActivityimplementsOnClickListener{
Buttonbutton=null;
TextViewtext=null;
MyHandlermHandler=null;
Threadthread;
@Override
protectedvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity1);
button= (Button)findViewById(R.id.btn);
button.setOnClickListener(this);
text= (TextView)findViewById(R.id.content);
}
publicvoidonClick(View v) {
switch(v.getId()) {
caseR.id.btn:
thread=newMyThread();
thread.start();
break;
}
}
privateclassMyHandlerextendsHandler{
publicMyHandler(Looper looper){
super(looper);
}
@Override
publicvoidhandleMessage(Message msg) {//处理消息
text.setText(msg.obj.toString());
}
}
privateclassMyThreadextendsThread{
@Override
publicvoidrun() {
Looper curLooper = Looper.myLooper();
Looper mainLooper = Looper.getMainLooper();
String msg ;
if(curLooper==null){
mHandler=newMyHandler(mainLooper);
msg ="curLooper is null";
}else{
mHandler=newMyHandler(curLooper);
msg ="This is curLooper";
}
mHandler.removeMessages(0);
Message m =mHandler.obtainMessage(1, 1, 1, msg);
mHandler.sendMessage(m);
}
}
}
说明:
Android会自动替主线程建立Message Queue。在这个子线程里并没有建立Message Queue。所以,myLooper值为null,而mainLooper则指向主线程里的Looper。于是,执行到:
mHandler = new MyHandler (mainLooper);
此mHandler属于主线程。
mHandler.sendMessage(m);
就将m消息存入到主线程的Message Queue里。mainLooper看到Message Queue里有讯息,就会作出处理,于是由主线程执行到mHandler的handleMessage()来处理消息。
用Android线程间通信的Message机制
在Android 下面也有多线程 的概念,在C/C++中,子线程可以是一个函数 ,一般都是一个带有循环的函数,来处理某些数据 ,优先线程只是一个复杂的运算过程,所以可能不需要while循环,运算完成,函数结束,线程就销毁。对于那些需要控制的线程,一般我们都是和互斥锁相互关联,从而来控制线程的进度,一般我们创建子线程,一种线程是很常见的,那就是带有消息循环的线程。
消息循环是一个很有用的线程方式,曾经自己用C在Linux下面实现一个消息循环的机制 ,往消息队列里添加数据,然后异步的等待消息的返回。当消息队列为空的时候就会挂起线程,等待新的消息的加入。这是一个很通用的机制。
在 Android,这里的线程分为有消息循环的线程和没有消息循环的线程,有消息循环的线程一般都会有一个Looper,这个事android的新概念。我 们的主线程(UI线程)就是一个消息循环的线程。针对这种消息循环的机制,我们引入一个新的机制Handle,我们有消息循环,就要往消息循环里面发送相 应的消息,自定义 消息一般都会有自己对应的处理,消息的发送和清除,消息的的处理,把这些都封装在Handle里面,注意Handle只是针对那些有Looper的线程,不管是UI线程还是子线程,只要你有Looper,我就可以往你的消息队列里面添加东西,并做相应的处理。
但是这里还有一点,就是只要是关于UI相关的东西,就不能放在子线程中,因为子线程是不能操作UI的,只能进行数据、系统 等其他非UI的操作。
那么什么情况下面我们的子线程才能看做是一个有Looper的线程呢?我们如何得到它Looper的句柄呢?
Looper.myLooper();获得当前的Looper
Looper.getMainLooper () 获得UI线程的Lopper
我们看看Handle的初始化函数,如果没有参数,那么他就默认使用的是当前的Looper,如果有Looper参数,就是用对应的线程的Looper。
如 果一个线程中调用Looper.prepare(),那么系统就会自动的为该线程建立一个消息队列,然后调用 Looper.loop();之后就进入了消息循环,这个之后就可以发消息、取消息、和处理消息。这个如何发送消息和如何处理消息可以再其他的线程中通过 Handle来做,但前提是我们的Hanle知道这个子线程的Looper,但是你如果不是在子线程运行 Looper.myLooper(),一般是得不到子线程的looper的。
public void run() {
synchronized (mLock) {
Looper.prepare();
//do something
}
Looper.loop();
}
所以很多人都是这样做的:我直接在子线程中新建handle,然后在子线程中发送消息,这样的话就失去了我们多线程的意义了。
class myThread extends Thread{
private EHandler mHandler ;
public void run() {
Looper myLooper, mainLooper;
myLooper = Looper.myLooper ();
mainLooper = Looper.getMainLooper ();
String obj;
if (myLooper == null ){
mHandler = new EHandler(mainLooper);
obj = "current thread has no looper!" ;
}
else {
mHandler = new EHandler(myLooper);
obj = "This is from current thread." ;
}
mHandler .removeMessages(0);
Message m = mHandler .obtainMessage(1, 1, 1, obj);
mHandler .sendMessage(m);
}
}
可以让其他的线程来控制我们的handle,可以把 private EHandler mHandler ;放在外面,这样我们的发消息和处理消息都可以在外面来定义,这样增加程序 代码 的美观,结构更加清晰。
对如任何的Handle,里面必须要重载一个函数
public void handleMessage(Message msg)
这个函数就是我们的消息处理,如何处理,这里完全取决于你,然后通过 obtainMessage和 sendMessage等来生成和发送消息, removeMessages(0)来清除消息队列。Google 真是太智慧了,这种框架 的产生,我们写代码更加轻松了。
有的时候,我们的子线程想去改变UI了,这个时候千万不要再子线程中去修改,获得UI线程的Looper,然后发送消息即可。
我们看看Goole Music App的源代码 。
在MediaPlaybackActivity.java 中,我们可以看一下再OnCreate中的有这样的两句:
mAlbumArtWorker = new Worker("album art worker");
mAlbumArtHandler = new AlbumArtHandler(mAlbumArtWorker.getLooper());
很 明显这两句,是构建了一个子线程。并且这个子线程还是Looper的子线程,这里很牛逼的使用了 mAlbumArtWorker.getLooper()这个函数,因为我们知道,我们能够得到子线程的Looper的途径只有一个:就是在子线程中调用 Looper.myLooper (),并且这个函数还要在我们perpare之后调用才能得到正确的Looper,但是他这里用了一个这样的什么东东 getLooper,不知道它是如何实现的?
这里有一个大概的思路,我们在子线程的的prepare之后调用 myLooper ()这个方法,然后保存在一个成员变量中,这个getLooper就返回这个东西,但是这里会碰到多线程的一个很突出的问题,同步。我们在父线程中调用 mAlbumArtWorker.getLooper(),但是想要这个返回正确的looper就必须要求我们的子线程运行了prepare,但是这个东 西实在子线程运行的,我们如何保证呢?
我们看Google是如何实现的?
private class Worker implements Runnable {
private final Object mLock = new Object();
private Looper mLooper;
/**
* Creates a worker thread with the given name. The thread
* then runs a [email=%7B@link]{@link[/email] android.os.Looper}.
* @param name A name for the new thread
*/
Worker(String name) {
Thread t = new Thread(null, this, name);
t.setPriority(Thread.MIN_PRIORITY);
t.start();
synchronized (mLock) {
while (mLooper == null) {
try {
mLock.wait();
} catch (InterruptedException ex) {
}
}
}
}
public Looper getLooper() {
return mLooper;
}
public void run() {
synchronized (mLock) {
Looper.prepare();
mLooper = Looper.myLooper();
mLock.notifyAll();
}
Looper.loop();
}
public void quit() {
mLooper.quit();
}
}
我 们知道,一个线程类的构造函数是在主线程中完成的,所以在我们的 Worker的构造函数中我们创佳一个线程,然后让这个线程运行,这一这个线程的创建是指定一个 Runnabl,这里就是我们的Worker本身,在主线程调用 t.start();,这后,我们子线程已经创建,并且开始执行work的run方法。然后下面的代码很艺术:
synchronized (mLock) {
while (mLooper == null) {
try {
mLock.wait();
} catch (InterruptedException ex) {
}
}
}
我们开始等待我们的子线程给mLooper赋值,如果不赋值我们就继续等,然后我们的子线程在运行run方法之后,在给 mLooper赋值之后,通知worker够着函数中的wait,然后我们的构造函数才能完成,所以我们说:
mAlbumArtWorker = new Worker("album art worker");
这句本身就是阻塞的,它创建了一个子线程,开启了子线程,并且等待子线程给mLooper赋值,赋值完成之后,这个函数才返回,这样才能保证我们的子线程的Looper的获取 绝对是正确的,这个构思很有创意。值得借鉴
Android中Handler的使用方法——在子线程中更新界面
本文主要介绍Android的Handler的使用方法。Handler可以发送Messsage和Runnable对象到与其相关联的线程的消息队列。每个Handler对象与创建它的线程相关联,并且每个Handler对象只能与一个线程相关联。
1. Handler一般有两种用途:1)执行计划任务,你可以再预定的实现执行某些任务,可以模拟定时器。2)线程间通信。在Android的应用启动时,会 创建一个主线程,主线程会创建一个消息队列来处理各种消息。当你创建子线程时,你可以再你的子线程中拿到父线程中创建的Handler对象,就可以通过该 对象向父线程的消息队列发送消息了。由于Android要求在UI线程中更新界面,因此,可以通过该方法在其它线程中更新界面。
◆ 通过Runnable在子线程中更新界面的例子
1.○ 在onCreate中创建Handler
public class HandlerTestApp extends Activity {
Handler mHandler;
TextView mText;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mHandler = new Handler();//创建Handler
mText = (TextView) findViewById(R.id.text0);//一个TextView
}
○ 构建Runnable对象,在runnable中更新界面,此处,我们修改了TextView的文字.此处需要说明的是,Runnable对象可以再主线程中创建,也可以再子线程中创建。我们此处是在子线程中创建的。
Runnable mRunnable0 = new Runnable()
{
@Override
public void run() {
mText.setText("This is Update from ohter thread, Mouse DOWN");
}
};
? ○ 创建子线程,在线程的run函数中,我们向主线程的消息队列发送了一个runnable来更新界面。
private void updateUIByRunnable(){
new Thread()
{
//Message msg = mHandler.obtainMessage();
public void run()
{
//mText.setText("This is Update from ohter thread, Mouse DOWN");//这句将抛出异常
mHandler.post(mRunnable0);
}
}.start();
}
◆ 用Message在子线程中来更新界面
1. 用Message更新界面与Runnable更新界面类似,只是需要修改几个地方。
○ 实现自己的Handler,对消息进行处理
private classMyHandlerextends Handler
{
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch(msg.what)
{
caseUPDATE://在收到消息时,对界面进行更新
mText.setText("This update by message");
break;
}
}
}
○ 在新的线程中发送消息
private void updateByMessage()
{
//匿名对象
new Thread()
{
public void run()
{
//mText.setText("This is Update from ohter thread, Mouse DOWN");
//UPDATE是一个自己定义的整数,代表了消息ID
Message msg = mHandler.obtainMessage(UPDATE);
mHandler.sendMessage(msg);
}
}.start();
}
更多相关文章
- 开发Android应用 提升性能的小技巧
- Android即时消息介绍
- Android(安卓)核心分析(13) -----Android(安卓)GWES之Android窗
- Android线程学习
- 图解Android(安卓)- System Service 概论 和 Android(安卓)GUI
- 图解Android(安卓)- Android(安卓)GUI 系统 (5) - Android的Even
- Android-线程笔记
- Android进程与线程基本知识
- Android,谁动了我的内存(1)