首页 > 程序开发 > 移动开发 > Android >

java面试题 android面试题 ( 三 )

2016-07-20

41如何退出Activity?如何安全退出已调用多个Activity的Application。对于单一Activity的应用来说,退出很简单,直接finish()即可。当然,也可以用killProcess()和System exit()这样的方法。

41如何退出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基类,处理这些共通问题。

42.ListView切换奇偶行背景色

ListView中有时候有这样的需求,当选中某项listView的时候,需求是改变listiew的背景颜色,如果用resource文件会有缓存问题,背景显示错误,那么直接用16进制表示颜色即可。如0xFF7AACC6. 注意表示透明度的需要写上,否则显示不正确

ListView源码中两个设置背景方法的不同点:

1.@RemotableViewMethod

2.public void setBackgroundResource(int resid) {

3.if (resid != 0 && resid == mBackgroundResource) {

4.return;

5.}

6.Drawable d= null;

7.if (resid != 0) {

8.d = mResources.getDrawable(resid);

9.}

10.setBackground(d);

11.mBackgroundResource = resid;

12.}

上面使用资源文件设置背景颜色

14.@RemotableViewMethod

15.public void setBackgroundColor(int color) {

16.if (mBackground instanceof ColorDrawable) {

17.((ColorDrawable) mBackground).setColor(color);

18.} else {

19.setBackground(new ColorDrawable(color));

20.}

21.}

上面是使用16进制数设置背景颜色,

42, 谈谈你对BroadCastRceiver的理解?

广播接收者,android四大组件之一,也是唯一一个能动态注册的组件。

1)广播接收者是一个专注于接收广播通知信息,并做出对应处理的组件。很多广播是源自于系统──比如,通知时区改变、电池电量低、拍摄了一张照片或者用户改变了语言选项。应用程序也可以进行广播──比如说,通知其它应用程序一些数据下载完成并处于可用状态。

2)应用程序可以拥有任意数量的广播接收者以对所有它感兴趣的通知信息予以响应。所有的接收器均继承自BroadcastReceiver基类。

3)广播接收者没有用户界面。然而,它们可以启动一个activity来响应它们收到的信息,或者用NotificationManager来通知用户。通知可以用很多种方式来吸引用户的注意力──闪动背灯、震动、播放声音等等。一般来说是在状态栏上放一个持久的图标,用户可以打开它并获取消息。

43, 广播的生命周期?

广播的生命周期是非常短的,当发送之后intent会到AndroidManifest.xml文件中找是不是有匹配的action,如果有就会调用Receiver ,然后获得Receiver 对象,再执行onReceive方法,这时候Receiver对象就没有用了,当我们再次点击按钮的时候就会重新获得对象,这就是BroadcastReceiver的生命周期.

在BroadcastReceiver里不能做一些比较耗时的操作,否侧会弹出ANR(Application No

Response)的对话框.

如果需要完成一项比较耗时的工作,应该通过发送Intent给Service,由Service来完成.这里不能使用子线程来解决,因为BroadcastReceiver的生命周期很短,子线程可能还没有结束,BroadcastReceiver就先结束了.BroadcastReceiver一旦结束,此时BroadcastReceiver的所在进程很容易在系统需要内存时被优先杀死,因为它属于空进程(没有任何活动组件的进程).如果它的宿主进程被杀死,那么正在工作的子线程也会被杀死.所以采用子线程来解决是不可靠的.

44. 注册广播有几种方式,这些方式有什么特点和区别?

两种方式,首先这两种方式都要先写继承自broadcastreceive的类

答: 第一种:在清单文件中声明,添加

第二种使用代码进行注册如:

IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");

IncomingSMSReceiver receiver = new IncomgSMSReceiver();

registerReceiver(receiver,filter);

两种注册类型的区别是:

1)第二种不是常驻型广播,也就是说广播跟随程序的生命周期。

2)第一种是常驻型,也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行。

45.广播的发送方式有哪些

sendBroadcast(),sendOrderedBroadcast()和sendStickyBroadcast()三种

sendBroadcast()这个方法的广播是能够发送给所有广播接收者,按照注册的先后顺序,如果你这个时候设置了广播接收者的优先级,优先级如果恰好与注册顺序相同,则不会有任何问题,如果顺序不一样,会出leaked IntentReceiver 这样的异常,并且在前面的广播接收者不能调用abortBroadcast()方法将其终止,如果调用会出BroadcastReceiver trying to return result during a non-ordered broadcast的异常,当然,先接收到广播的receiver可以修改广播数据。

sendOrderedBroadcast()方法顾名思义就是priority的属性能起作用,并且在队列前面的receiver可以随时终止广播的发送。还有这个api能指定final的receiver,这个receiver是最后一个接收广播时间的receiver,并且一定会接收到广播事件,是不能被前面的receiver拦截的。实际做实验的情况是这样的,假设我有3个receiver依序排列,并且sendOrderedBroadcast()方法指定了一个finalReceiver,那么intent传递给这4个Receiver的顺序为Receiver1-->finalReceiver-->Receiver2-->finalReceiver-->Receiver3-->finalReceiver。这个特性可以用来统计系统中能监听某种广播的Receiver的数目。

sendStickyBroadcast()字面意思是发送粘性的广播,使用这个api需要权限android.Manifest.permission.BROADCAST_STICKY,粘性广播的特点是Intent会一直保留到广播事件结束,而这种广播也没有所谓的10秒限制,10秒限制是指普通的广播如果onReceive方法执行时间太长,超过10秒的时候系统会将这个广播置为可以干掉的candidate,一旦系统资源不够的时候,就会干掉这个广播而让它不执行。

注: (下面是广播接收者的生命周期以及一些细节部分:

1.广播接收者的生命周期是非常短暂的,在接收到广播的时候创建,onReceive()方法结束之后销毁

2.广播接收者中不要做一些耗时的工作,否则会弹出Application No Response错误对话框

3.最好也不要在广播接收者中创建子线程做耗时的工作,因为广播接收者被销毁后进程就成为了空进程,很容易被系统杀掉

4.耗时的较长的工作最好放在服务中完成)

46, 广播分几种?他们有什么区别?

广播被分为两种不同的类型:“普通广播(Normal broadcasts)”和“有序广播(Ordered broadcasts)”。普通广播是完全异步的,可以在同一时刻(逻辑上)被所有接收者接收到,消息传递的效率比较高,但缺点是:接收者不能将处理结果传递给下一个接收者,并且无法终止广播Intent的传播。

然而有序广播是按照接收者声明的优先级别,被接收者依次接收广播。如:A的级别高于B,B的级别高于C,那么,广播先传给A,再传给B,最后传给C 。优先级别声明在 intent-filter 元素的 android:priority 属性中,数越大优先级别越高,取值范围:-1000到1000,优先级别也可以调用IntentFilter对象的setPriority()进行设置 。有序广播的接收者可以终止广播Intent的传播,广播Intent的传播一旦终止,后面的接收者就无法接收到广播。

另外,有序广播的接收者可以将数据传递给下一个接收者,如:A得到广播后,可以往它的结果对象中存入数据,当广播传给B时,B可以从A的结果对象中得到A存入的数据。

47、如何使用SharedPreferences存储数据,保存的目录?
首先说明SharedPreferences存储方式,它是 Android提供的用来存储一些简单配置信息的一种机制,例如:登录用户的用户名与密码。其采用了Map数据结构来存储数据,以键值的方式存储,可以简单的读取与写入,具体实例如下:
void ReadSharedPreferences(){
String strName,strPassword;
SharedPreferences user = getSharedPreferences(“user_info”,0);
strName = user.getString(“NAME”,””);
strPassword = user getString(“PASSWORD”,””);
}
void WriteSharedPreferences(String strName,String strPassword){
SharedPreferences user = getSharedPreferences(“user_info”,0);
uer.edit();
user.putString(“NAME”, strName);
user.putString(“PASSWORD” ,strPassword);
user.commit();
}
数据读取与写入的方法都非常简单,只是在写入的时候有些区别:先调用edit()使其处于编辑状态,然后才能修改数据,最后使用commit()提交修改的数据。实际上SharedPreferences是采用了XML格式将数据存储到设备中,在DDMS中的File Explorer中的/data/data//shares_prefs下。+
48、Android中的五种存储方式及其应用场景
1)SharedPreferences
存储路径:(data/data/packagename/shares_prefs), 轻量级存储,以键值对的形式存储在xml中,一般用来保存应用中的设置属性
2)文件存储 SD卡存储多媒体文件, 文件缓存
3) Sqlite数据库 存储路径:(data/data/packagename/databases), 一种嵌入式数据库,支持sql语言,存储大量结构性数据
4)ContentProvider 进程(应用程序)间数据共享,数据源可以是sqlite,也可以是xml,相关类: ContentResolver(内容解析器), ContentObserver(数据 观察者)
5) 网络存储 天气数据的xml,json格式等等,通过HttpUrlConnection,HttpClient,或者SOAP协议获取数据
49、android客户端如何实现自动登录
通过SharedPreferences存储用户名,密码,当存储不为空时实现自动登录功能
50、外部存储设备保存文件的步骤(注意一定得配权限)
// 如果手机上插入了SD卡,并且应用程序具有访问SD卡的权限
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
File sdCardDir = Environment.getExternalStorageDirectory();
File targetFile = new File(sdCardDir.getCanonicalPath()
+ FILE_NAME);
// 为了防止追加值,一开始创建的时候就将原来的文件删除
targetFile.delete();
// 以指定文件创建 RandAccessFile对象------------------rw是指文件的可读可写
RandomAccessFile raf = new RandomAccessFile(targetFile, "rw");
// 将文件记录指针移动到最后,继续附加值
raf.seek(targetFile.length());
// 输出文件内容
raf.write(content.getBytes());
// 关闭RandomAccessFile
raf.close();
51、外部存储external storage和内部存储internalstorage之间的区别和他们的默认根目录的位置

1.内部存储:

注意内部存储不是内存。内部存储位于系统中很特殊的一个位置,如果你想将文件存储于内部存储中,那么文件默认只能被你的应用访问到,且一个应用所创建的所有文件都在和应用包名相同的目录下。也就是说应用创建于内部存储的文件,与这个应用是关联起来的。当一个应用卸载之后,内部存储中的这些文件也被删除。从技术上来讲如果你在创建内部存储文件的时候将文件属性设置成可读,其他app能够访问自己应用的数据,前提是他知道你这个应用的包名,如果一个文件的属性是私有(private),那么即使知道包名其他应用也无法访问。内部存储空间十分有限,因而显得可贵,另外,它也是系统本身和系统应用程序主要的数据存储所在地,一旦内部存储空间耗尽,手机也就无法使用了。所以对于内部存储空间,我们要尽量避免使用。Shared Preferences和SQLite数据库都是存储在内部存储空间上的。内部存储一般用Context来获取和操作。

getFilesDir()获取你app的内部存储空间,相当于你的应用在内部存储上的根目录。

如果是要创建一个文件,如下

1
File file = newFile(context.getFilesDir(), filename);
2.外部存储

最容易混淆的是外部存储,如果说pc上也要区分出外部存储和内部存储的话,那么自带的硬盘算是内部存储,U盘或者移动硬盘算是外部存储,因此我们很容易带着这样的理解去看待安卓手机,认为机身固有存储是内部存储,而扩展的T卡是外部存储。比如我们任务16GB版本的Nexus 4有16G的内部存储,普通消费者可以这样理解,但是安卓的编程中不能,这16GB仍然是外部存储。

所有的安卓设备都有外部存储和内部存储,这两个名称来源于安卓的早期设备,那个时候的设备内部存储确实是固定的,而外部存储确实是可以像U盘一样移动的。但是在后来的设备中,很多中高端机器都将自己的机身存储扩展到了8G以上,他们将存储在概念上分成了"内部internal" 和"外部external" 两部分,但其实都在手机内部。所以不管安卓手机是否有可移动的sdcard,他们总是有外部存储和内部存储。最关键的是,我们都是通过相同的api来访问可移动的sdcard或者手机自带的存储(外部存储)。

外部存储虽然概念上有点复杂,但也很好区分,你把手机连接电脑,能被电脑识别的部分就一定是外部存储。

内部:写入到/data/data/com.xxx.xxx/files目录下,com.xxx.xxx为应用程序包名

外部:/mnt/sdcard/Android/data/包名/filescom.xxx.xxx为应用程序包名

1、sqlite的用处及用法, 哪里用过?以及怎么提高sqlite的效率
轻量级嵌入型数据库,经常用于嵌入型操作系统,如android中,可以用户对对象性数据的描述并存储。事务。一致性、原子性、隔离性、持续性
2、如何建一个“aaa.db”数据库,如何建一个user表;写出增删改查语句
①.建立一个类继承SQLiteHelper,重写SQLiteHelp方法,创建库:
public SQLiteHelp(Context context) {
super(context, "user.db", null, 1);
// TODO Auto-generated constructor stub
}
②.重写onCreate方法
@Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
db.execSQL("create table user(id integer primary key autoincrement,name varchar(20),age varchar(20))");
}
③增删改查:。。。
3、请介绍下ContentProvider是如何实现数据共享的。
一个程序可以通过实现一个Content provider的抽象接口将自己的数据完全暴露出去,而且Content providers是以类似数据库中表的方式将数据暴露。Content providers存储和检索数据,通过它可以让所有的应用程序访问到,这也是应用程序之间唯一共享数据的方法。
要想使应用程序的数据公开化,可通过2种方法:创建一个属于你自己的Content provider或者将你的数据添加到一个已经存在的Content provider中,前提是有相同数据类型并且有写入Content provider的权限。
如何通过一套标准及统一的接口获取其他应用程序暴露的数据
Android提供了ContentResolver,外界的程序可以通过ContentResolver接口访问ContentProvider提供的数据。
4. 如何将SQLite数据库(dictionary.db文件)与apk文件一起发布
解答:可以将dictionary.db文件复制到Eclipse Android工程中的res aw目录中。所有在res raw目录中的文件不会被压缩,这样可以直接提取该目录中的文件。可以将dictionary.db文件复制到res aw目录中
5. 如何将打开res raw目录中的数据库文件
解答:在Android中不能直接打开res raw目录中的数据库文件,而需要在程序第一次启动时将该文件复制到手机内存或SD卡的某个目录中,然后再打开该数据库文件。
复制的基本方法是使用getResources().openRawResource方法获得res raw目录中资源的 InputStream对象,然后将该InputStream对象中的数据写入其他的目录中相应文件中。在Android SDK中可以使用SQLiteDatabase.openOrCreateDatabase方法来打开任意目录中的SQLite数据库文件。
1. 说说HttpClient的通信过程
1)生成请求对象(HttpGet get,HttpPost post)
2)生成客户端对象 HttpClient client
3)执行请求接收相应 HttpResponse response = client.execute(post)
HttpEntity entity = response.getEntity()
2.(Json(有数据类型)与xml(没有)的区别?)
移动互联数据交互格式有XML和JSON
1)JSON和XML的数据可读性基本相同
2)JSON和XML同样拥有丰富的解析手段
3)JSON相对于XML来讲,数据的体积小
4)JSON与JavaScript的交互更加方便
5)JSON对数据的描述性比XML较差
3. XML解析有哪几种?各自优缺点,官方推荐使用哪种
基本的解析方式有三种: DOM,SAX,Pull
1)dom解析解析器读入整个文档,然后构建一个驻留内存的树结构,然后代码就可以使用 DOM 接口来操作这个树结构的优点是对文档增删改查比较方便,缺点占用内存比较大。
2)sax解析基于事件驱动型,优点占用内存少,解析速度快,缺点是只适合做文档的读取,不适合做文档的增删改查。
3)pull解析同样基于事件驱动型,android 官方API提供,可随时终止,调用next() 方法提取它们(主动提取事件)
4. sax解析代码
首先SAXParserFactory来创建一个SAXParserFactory实例
SAXParserFactory factory = SAXParserFactory.newInstance();
根据SAXParserFactory实例来创建SAXParser
SAXParser产生SAXReader
XMLReader reader = factory.newSAXParser().getXMLReader();
XMLReader 加载XML,然后解析XML,在解析的过程中触发相对于接口中的事件处理程序
5. Android缓存机制(sharePrefrence、Sd卡、数据库SQLite)
答: 客户端缓存机制是android应用开发中非常重要的一项工作,使用缓存机制不仅仅可以为用户节省3G流量,同时在用户体验方面也是非常好的选择,比如有些新闻客户端支持离线模式,也是通过缓存机制实现的.缓存机制分为两部分,一部分是文字缓存,另一部分是多媒体文件缓存.
文字缓存有两种实现:
1)可以将与服务器交互得到的json数据或者xml数据存入sd卡中,并在数据库添加该数据的记录.添加数据库记录时,提供两个关键字段,一个是请求的URL,另一个则是本地保存后的文件地址,每次加载数据之前都会根据URL在数据库中检索
2)将JSON数据解析后装入List对象中,然后遍历List,将数据统统写入相应的数据库表结构中,以后每次向服务器发起请求之前可以先在数据库中检索,如果有直接返回.
多媒体文件缓存:主要指图片缓存
图片的缓存可以根据当前日期,时间为名字缓存到SD卡中的指定图片缓存目录,同时数据库中做相应记录,记录办法可以采用两个关键字段控制,一个字段是该图片的URL地址,另一个字段是该图片的本机地址.取图片时根据URL在数据中检索,如果没有则连接服务器下载,下载之后再服务器中作出相应记录
缓存文件删除策略:
1) 每一个模块在每次客户端自动或者用户手动更新的时候删除相应模块的缓存文件,并重新下载新的缓存文件.
2)在设置界面中提供删除缓存的功能,点击后删除本机所有缓存.
相关文章
最新文章
热点推荐