(一)Android面试题(一)Activity、Intent
Android四大组件分别是哪些?各自有什么作用和特点?
答:
活动(Activity):Activity是Android程序与用户交互的窗口,是Android构造中最基本的一种,它需要为保持各界面的状态,做很多持久化的事情,妥善管理生命周期以及一些跳转逻辑。
服务(Service):后台服务于Activity,封装有一个完整的功能逻辑实现,接受上层指令,完成相关的事务,定义好需要接受的Intent提供同步和异步接口。
内容提供者(Content Provider):是Android提供的第三方应用数据的访问方案,可以派生Content Provider类,对外提供数据,可以像数据库一样进行选择排序,屏蔽内部数据的存储细节,向外提供统一的接口模型,大大简化上层应用,对数据的整合提供了更方便的途径。
广播接收器(BroadCast Receiver):接受一种或者多种Intent作触发时间,接受相关消息,做一些简单处理,转换成一条Notification,统一了Android的事件广播模型。(如接受系统通知,向通知栏发送消息)Activity的生命周期函数有哪些?点击HOME键、BACK键等操作时,生命周期函数如何迁移?
答:
onCreate // 创建Act实例时调用。通常进行一些数据的初始化,比如获取控件、申请数组或集合的内存、变量赋值
onRestart // Act停留在onStop但是没有onDestory
onStart // 该方法在onCreate或者onRestart之后调用,调用之后,Act进入可视生命周期
onResume // onStart之后调用,调用该方法后Act进入活动(运行、前台)状态,可以和用户进行交互,比如响应用户的输入、点击、触摸等操作
onPause // 在onResume之后,调用该方法,此Act就不能继续和用户交互,用户自定义的一些数据可以在此方法中进行保存
onStop // onPause之后进行调用,一旦调用onStop,Act就退出了可视状态,但是Act实例并没有销毁
onDestroy // 此方法是在销毁Act的时候调用,一旦调用表明该Act实例的生命周期就结束了,通常会在此方法做一些释放资源的操作,比如将引用变量值置为nullActivity的四种加载(启动)模式分别是?各自有什么特点?
答:
standard:特点是每一次启动该Act时,会重建一个新的该Act实例
singleTop:特点是每一次该Act时,检查栈顶是否存在该Act的实例
存在:则直接重用该Act实例
不存在:则需要新建一个该Act的实例
singleTask:特点是每一次启动该Act时,需要在栈中去检查栈中是否存在该Act的实例
存在:
在栈顶:直接复用该Act的实例
不在栈顶:首先要把其上的Act实例移除掉,使该Act的实例回到栈顶去,然后再复用该Act的实例
不存在:新建一个该Act的实例
singleInstance:看进程中是否有该Act实例
存在:直接从该独享栈中取出该Act的实例复用
不存在:新建一个栈,然后新建一个该Act的实例,放入该栈中
注意:如果把程序入口MainAct的Act设置为singleInstance时,通过该Act启动了别的Act(SecondAct),再由其他 (SecondAct)启动ThirdAct,在ThirdAct中启动MainAct,由MainAct再去启动SecondAct时,不会产生第四个实例只是把MainAct所在的栈切换到SecondAct所在的栈,把栈顶的Act实例展示出来Activity意外退出时,如何进行数据保存和恢复?
答:
开发者提前可以复写onSaveInstanceState方法,创建一个Bundle类型的参数,把数据存储在这个Bundle对象中,这样即使Activity意外退出,Activity被系统摧毁,当重新启动这个Activity而调用onCreate方法时,上述Bundle对象会作为参数传递给onCreate方法,开发者可以从Bundle对象中取出保存的数据,利用这些数据将Activity恢复到被摧毁之前的状态。Intent是什么?有什么用处?
答:
Intent(意图):作用是调用某个组件去做一个事情,它既能充当桥梁的角色,也能传递数据。Intent如何传值?Bundle是什么,有什么用?
答:Intent的传值:通过Intent类提供的setData和putExtra方法传递。
Bundle(捆):
两个Activity之间的通讯可以通过bundle类来实现,把要传递的数据通过key-value的形式加入数据,另外一个Activity里面取出数据时,用key找出对应的valueonCreate(Bundle savedInstanceState)中savedInstanceState有什么用,什么情况下为null?
答:
savedInstanceState:是用来保存实例状态的。在Activity中有一个onSaveInstanceStata方法,可以用来存放数据,避免Activity意外退出时保存需要的数据,通过onCreate中savedInstanceState取出保存的数据,默认不重写时为null如何实现使用Intent来传递自定义对象?
答:
序列化要传递的自定义的对象,再通过Bundle来传值。
(序列化:将对象的状态转换为可保持或传输的格式的过程)
与序列化相对的是反序列化,它将流转换为对象。
通过序列化和反序列化就可以实现存储和传输数据。
(二)Android面试题(二)OOM、ANR
什么是OOM?如何避免OOM?
OOM概念:内存溢出(OutOfMemor),内存占有量超过了JVM分配的最大内存。
避免OOM:
<1.避免对activity的超过生命周期的引用(尽量使用application代替activity)。
因为程序一般是由很多个Activity构成的,从一个Activity跳转了以后,
系统就有可能回收这个Activity的各种内存占用。可是此时如果你的一些不可回收变量(比如静态变量)保持了对此Activity对象的引用,
那么GC就不会对此Activity进行回收,无故占用了大量的内存。这种情况最好的办法就是用application代替activity。
用Context.getApplicationContext() 或者 Activity.getApplication()可以很方便的得到application对象。
<2.在展示高分辨率图片时,先将图片进行压缩到与空间大小相近。
<3.及时释放不使用的Bitmap,动态回收内存,方法:bitmap.recycle()。
<4.对适配器视图进行优化处理,避免过多加载数据和对象的生成。什么是ANR?产生ANR的原因是什么?如何避免ANR的发生?
ANR概念:
应用程序无响应(application not response)。
原因:
主线程中做了非常耗时的操作。
解决办法:
<1.运行在主线程里的任何方法都尽可能少做事情,尽量用Handler来处理UIthread和别的thread之间的交互;
<2.应用程序应该避免在BroadcastReceiver里做耗时的操作或计算;
<3.避免在Intent Receiver里启动一个Activity,因为它会创建一个新的画面,并从当前用户正在运行的程序上抢夺焦点;
<4.在主线程中更新UI。
(三)Android面试题(三)四大组件
什么是Service?Service和Activity有什么区别?
答:Service是提供服务的代码,这些代码最终体现为一个个的接口函数,所以,Service就是实现一组函数的对象,通常也称为组件。
区别:
①从设计的角度来讲:
Android的Activity的设计与Web页面非常类似,从页面的跳转通过连接,以及从页面的定位通过URL,从每个页面的独立封装等方面都可以看出来,它主要负责与用户进行交互。
Service则是在后台运行,默默地为用户提供功能,进行调度和统筹,如果一棵树的地上部分是Activity的话,它庞大的根须就是Service。Android的服务组件没有运行在独立的进程或线程中,它和其他的组件一样也在应用的主线程中运行,如果服务组件执行比较耗时的操作就会导致主线程阻塞或者假死,从而无法响应用户的操作。
②从使用的角度来讲:
Service不仅可以给Activity建立双向连接,为Activity提供数据和功能支持,也可以单向接受Intent的请求,进行数据的分析处理和功能调度。
③从扮演的角色来讲:
Activity的功能比较单一,主要就是显示应用所具有的一些功能,帮助用户与应用进行交互,像一个人的脸。而Service可能扮演功能调度者也能扮演功能提供者,从触发器收集信息进行分析和处理,然后更新界面,修改数据或进行其他操作时是一个功能调度者,从输入法的选择考虑Service扮演的就是一个功能提供者。View组件是Android中用户能够实实在在看到的部分,如按钮,输入框等就是继承自这个类,View只有装入Activity这样的容器中才有意义,而反过来
Activity装入了这些View后才能够成功完成与用户交互的任务,但是Service不需要这些花哨的东西,只需要默默地等待事件发生或者听候差遣。Service的两种使用方式分别是什么?它们的生命周期分别怎样迁移?
答:
方式1:通过startService,Service会经历onCreate->onStart,stopService的时候直接onDestroy
方式二:通过bindService,Service只会运行onCreate,这个时候TestServiceHolder和TestService绑定在一起,TestServiceHolder退出了,Srevice就会调用onUnbind->onDestroyed什么是AIDL?AIDL的作用是什么?它的基本使用流程是怎么样的?
答:AIDL是一种android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口
作用:
1、多个应用程序之间建立共同的服务机制;
2、通过AIDL在不同应用程序之间达到数据的共享和数据相互操作;
3、主要是用于多应用之间的数据交互(而 在单个应用内或者说该应用如果不需要和其它第三方应用进行交互则不需要实现aidl接口);
流程:
1、编写aidl文件
2、编写自己的Service
3、在自己的Service的onBind方法中,将aidl文件生成的类中的Stud的子类返回(需要继承Stud重写接口方法)
4、在AndroidManifest.xml中配置你的Service类,示例 注意:service android:name="com.aidl.SerachService"中,android:name属性必须填写你的Service的名字,包括包名,不能写aidl生成的类的名字,因为那不是个Servic
5、编写调用aidl服务的客户端
6、把之前编写的aidl文件(注意不是生成的java文件)和它的包目录拷贝到客户端的src目录中
7、在需要的地方用一下方法绑定,new Intent构造器中的action填写的就是之前<action android:name="com.aidl.ISerachService" />中的android:name的字符串什么是BroadcastReceiver?它有什么作用?
答:BroadcastReceiver是Android四大组件之一,本质是一种 全局的监听器,用于监听系统全局的广播消息。因此它可以非常方便的实现不同组件之间的通信。
作用:通过该机制,使得消息能在各个组件间、各个进程间传递,起到邮递员的作用。什么是有序广播?有序广播有什么特点?什么是系统广播?
有序广播:是通过Context.sendOrderedBroadcast来发送。所有的receiver依次执行。
有序广播特点即从优先级别最高的广播接收器开始接收,接收完了如果没有丢弃,就下传给下一个次高优先级别的广播接 收器进行处理,依次类推,直到最后。
系统广播:当系统发生事件时,就会发送出广播,通过广播中的关键字段,系统将寻找所有关注这个广播的应用,并触发他们注册的Receiver什么是粘性广播?它跟普通广播有什么区别?
定义:没有注册的接收者,在后来注册后也能收到广播,进程间通信
当发布该广播后它还驻留在周围,它可以让其他接收者迅速的检索到数据,通过一个方法的(动态注册接收者方法)返回值 这个返回值就是意图
粘性广播的特点是Intent会一直保留到广播事件结束,而这种广播也没有所谓的10秒限制,10秒限制是指普通的广播如果onReceive方法执行时间太长,超过10秒的时候系统会将这个广播置为可以干掉的candidate,一旦系统资源不够的时候,就会干掉这个广播而让它不执行。什么是ContentProvider?如何自定义一个ContentProvider?
ContentProvider(内容提供者)是Android中的四大组件之一。主要用于对外共享数据,也就是通过ContentProvider把应用中的数据共享给其他应用访问,其他应用可以通过ContentProvider对指定应用中的数据进行操作。
1)ContentProvider为存储和获取数据提供了统一的接口。ContentProvide对数据进行封装,不用关心数据存储的细节。使用表的形式来组织数据。
2)使用ContentProvider可以在不同的应用程序之间共享数据。
总的来说使用ContentProvider对外共享数据的好处是统一了数据的访问方式。
自定义ContentProvider:
编写一个类,必须继承自ContentProvider类;
实现ContentProvider类中的所有的抽象方法;
onCreate();getType();query();Insert();update();delete();等方法
在清单文件中声明注册ContentProvider
<provider android:name=".MyWordsprovider"
android:authorities="heying.provider.wordsconetenprovider"
android:exported="true"
/>
将Uri提供出去你使用过哪些系统的ContentProvider?
媒体库、通讯录等
(四)Android面试题(四)数据保存和网络
常用的数据持久化(长久保存数据)方式有哪些?
答:
1、SharedPreference,共享参数形式,一种以Key-Value的键值对形式保存数据的方式,Android内置的,一般应用的配置信息 ,推荐使用此种方式保存,不能存文件也不适合。其存储的位置在/data/data/packageName/shared_prefs文件夹下面。
2、Internal Storage:把数据存储到手机内部的存储空间,主要用来保存私有数据/data/data/packageName/files文件夹下 面
3、External Storage:把数据存储到手机的外部存储SD卡中,主要用来保存非私有和大型数据,它有应用程序专用的文件夹 ,也有所有程序公用的文件夹(这个文件夹不会随着应用程序的卸载而卸载),需要赋予应用程序访问Sdcard的权限,Android的权限 控制尤为重点,在Android程序中,如果需要做一些越界的操作,均需要对其进行授权才可以访问。在AndroidManifest.xml中添加代码 :<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
4、SQLite Databases:以表格形式存储信息的一个轻量级的小型数据库
5、Network Connection:将数据存储到网络服务器上
6、ContentProvider:他提供一种方式实现两个不同应用程序之间的通讯ShareedPrefrence的读写数据的基本方法?
答:它保存的数据主要是简单类型的Key-value对。并且Value部分只能是一些基本数据类型:boolean、float、int、long、String等 。
1、得到SharedPreference对象的方法有:
a、Context类中的getSharedPreference(String name,int mode)方法,name :存储的文件名,如果不存在会自动创建一个 mode:访问模式,一般有两个参数MODE_PRIVTE(私有,只有当前应用程序才能进行读写)和MODE_MULTI_PROCESS(多个进程对同一个文件进行读写)
b、Activity类中的getSharedPreference(int mode)方法,自动将当前活动的类名作为文件名
c、PreferenceManager类的getDefaultSharedPreferences(Context context)方法,这是一个静态方法,接收Context参数,会自动将应用程序的包名作为前缀去命名文件
2、读常用方法:
a、boolean contains(String Key):判断SharedPreferences是否包含特定Key的数据
b、abstract Map<String,?> getAll():获取SharedPreferences数据里全部的Key-Value对。
c、 boolean getXxx(String key,Xxx defValue):获取SharedPreferences数据里指定Key对应的value。如果该Key不存在,返回默认值defValue。
3、写常用方法(通过SharedPreferences的内部接口Editor实现,edit()方法即可得到Editor对象)
a、abstract SharedPreferences.Editor clear():清空SharedPreferences里所有的数据
b、abstract SharedPreferences.Editor putXxx(String key,xxx value):向SharedPreferences中插入指定的Key-Value对。
c、abstract SharedPreferences.Editor remove(String key):从SharedPreferences中移除指定Key的数据。
d、boolean commit():当Editor编辑完成后,调用该方法提交修改,切记不可忘记调用此方法,否则不能储存数据SQLite的基本语句:建表、增删改查分别是怎么样的?
答:
建表:
CREATE TABLE tableName(column1 INTEGER PRIMARY KEY AUTOINCREMENT,column2 VARCHAR(num),.....);
添加:
INSERT INTO tableName values(value1,value2);添加所有字段
INSERT INTO tableName(column1,column2) values(value1,value2);添加字段column1和字段column2
删除:
DELETE TABLE tableName 删除全部
DELETE form tableName WHERE column2 = vaule2按条件查询(字段column2的值为vaule2的这一行,如果value2为字符串则需要用单引号括起来)
更新:
UPDATE tableName SET column1 = value1, column2 = value2,...;所有数据都这样更新
UPDATE tableName SET column1 = value1, column2 = value2 WHERE column3 = value3;更新column3 = value3这一行的column1 和column2的值
查询:
SELECT * FROM tableName;查询所有的数据
SELECT column1,column3 FROM tableName; 查询所有数据,但是只显示column1,column3这两个字段的所有值
SELECT * FROM tableName WHERE column2 > someValue;查询column2字段的值大于someValue的所有字段
SELECT * FROM tableName WHERE column1 = value1 ORDER BY column2 ASC;按条件查询结果以column2 的升序排列
SELECT * FROM tableName WHERE column1 = value1 ORDER BY column2 DESC;按条件查询结果以column2 的降序排列
SELECT * FROM tableName WHERE column2 LIKE '%key%' ORDER BY column2 ASC;// 模糊查找SQLiteOpenHelper的作用是什么?
答:SQLiteOpenHelper主要是用来创建数据库和表格,以及为数据库升级的作用。在Android系统中,既然可以通过Context类的 openOrCreateDatabase()函数打开或创建SQLite数据库,并且可以通过其返回值(即SQLiteDatabase对像)调用execSQL()函数对数据 库做任何的操作(CRUD),那么还需要SQLiteOpenHelper这个类有什么意义呢?
例如:
db = openOrCreateDatabase(DB_NAME, this.MODE_PRIVATE, null);
db.execSQL("DROP TABLE IF EXISTS students");
db.execSQL("CREATE TABLE IF NOT EXISTS students (_id INTEGER PRIMARY KEY AUTOINCREMENT, name, age INTEGER)");
实际上,直接操作数据库的语句和其他的语句混在一起,不利于程序的模块化。而SQLiteOpenHelper是一个抽象类,通过它的名字可以 看出来,是一个帮我们打开数据库的小助手:
1、当new SQLiteOpenHelper子类对象时,就会通过其构造函数创建数据库文件(当然如果数据库如果存在,就不用创建了, 并且自动调用onCreate(SQLiteDatabase db)创建数据表;
2、当要对数据库读操作时,只需调用其子类的getReadableDatabase()返回SQLiteDatabase实例,通过该实例来执行SQL语句 ;
3、当要对数据库写操作时,只需调用其子类的getWritableDatabase()返回SQLiteDatabase实例,通过该实例来执行SQL语句 ;
4、当通过构造函数传进来的数据库版本高于之前的版本时,系统会调用onUpgrade()函数来更新数据库。
于是,对APP而言,就屏蔽了数据库创建的过程,将数据表的创建独立出来了。
SQLiteOpenHelper只是一个数据库管理的帮助类,让使用者不直接操作数据库而是通过操作这个类的对象来实现各种数据库操作。这个 类就是给数据库操作搭了个架子,使用者根据需求去填充那些架子。什么是回调CallBack,回调的作用是什么?常见的回调使用场景?
答:把接口方法的定义和调用给封装起来,然后在回调接口中的回调方法中进行具体的操作
作用:
1、可以节省时间,充分利用了资源
2、让工具类的使用变得简单易用。用户不需要关心接口方法的定义以及调用,只需要关注方法的具体实现功能即可。
使用场景:
1、事件监听器,这其实就是回调最常见的应用场景之一
2、生命周期函数
3、当方法的具体实现不确定的时候可以设置回调函数让清楚的人自己去实现,而我们只是提供一个实现的接口出去,而其它的别人不需要知道的东西都封存起来,这也体现了封装和面向对象的思想,你问我问题,而我想到了答案告诉你,至于 你拿到答案后干什么,我怎么想到的答案都不需要对方知道TCP和UDP的区别是什么?
答:
TCP :传输控制协议。
a、面向连接,靠三次握手来完成
b、速度相对较慢,因为连接的过程会耗时间和资源
c、可靠的协议,数据不会丢失
d、数据大小没有限制
e、耗用系统资源相对较多
UDP :用户数据报文协议
a、面向无连接的
b、高效的、速度快
c、不可靠的协议,容易丢失数据
d、数据包大小有限制,小于64K
e、耗用系统资源相对较少Http的get和post方法的区别什么?
答:get方法:
原理上:
主要用来获取或者查询资源信息,是安全的和幂等的。就是说不修改信息
表面上:
a、GET请求的数据会附在URL之后(就是把数据放在HTTP协议头中),以?分割URL和传输数据,参数之间以&相连
b、GET方式提交的数据较小(浏览器和操作系统对URL长度的限定),一般1024字节
c、GET的安全性相对较弱,可能会造成信息泄露(信息会明文出现在URL上,其他人可能会通过浏览器的缓存查看到历史记录,从而得到信息)
d、服务器端用Request.QueryString获取变量的值
e、GET请求用起来比比较方便
post方法:
原理上:
根据Http规范,POST表示可能修改服务器上资源的请求
表面上:
a、POST请求把要提交的数据放在HTTP包的包体中。
b、POST可以提交较大量的数据(受到服务器的处理程序的处理能力限制)
c、POST安全性较高(数据不会明文出现在URL上)。
d、服务器端用Request.Form获取提交的数据。
e、用起来相对麻烦一点
(五)Android面试题(五)常见的异步方式
常见的实现异步的方式有哪些?
AsyncTask、Thread+Handler常见的耗时操作如何处理?
常见的耗时操作有:网络请求、数据库操作、比较复杂的运算,使用AsyncTask或Thread+Handler进行异步处理子线程更新UI的基本方法有哪些?
a. Thread + Handler的方式
在非UI线程中执行耗时操作(网络请求、数据库操作、比较复杂的运算),在需要将操作的进度或者结果更新到UI上时,
就发送消息并携带数据,最终由Handler的handleMessage来处理(注意:Handler对象必须是创建在UI线程中)
b. Activity提供的一个简便的方式来更新UI
runOnUiThread(Runnable r);
内部做了判断当前的活动线程是否是UI线程
是:直接调用run方法
否:将Runnable给post到UI线程对应的消息队列
c. Handler里边也提供简便的更新UI的方式
handler.post(Runnable r);
内部其实调用了发送消息的方法,最终也是把Runnable对象给放到了UI线程中执行Handler、Looper、Message、MessageQueue是什么?它们之间有什么关联?
Handler:基本功能两个,发送和处理消息
发消息:sendXXXX方法
a. 如果不需要通过消息来传递具体的数据,可以发送空消息
sendEmptyMessage(what);即时消息,立即发送
sendEmptyMessageDelayed(what,time);发送一个延迟消息,在从当前计时到指定时间长度后发送
sendEmptyMessageAtTime(what, atTime);发送一个定时的消息,在指定时刻发出
b. 如果需要在线程间传递一些具体的数据,需要发送带有具体消息对象的消息
消息对象的获取:
Message msg = new Message(); // 每一次都新创建一个消息对象
Message msg = handler.obtainMessage();// 每次调用时会去检查消息池中是否有可复用的消息。有则复用,无则创建。
Message msg = Message.obtain(); // 每次调用时会去检查消息池中是否有可复用的消息。有则复用,无则创建。
c. Message都有哪些传递数据的方式:
what:int,用于区分消息从哪里发出
arg1:int,可以携带一个int数据
arg2:int,也可以携带一个int数据
obj:Object,可以携带任何的对象
d. 带数据的消息发送也可以有即时、延迟、定时
处理消息:handleMessage里边实现接收到消息之后需要实现的操作,需要注意的是该方法是覆盖父类Handler的
Message:消息对象,用来传递具体的数据的。
MessageQueue:消息队列,是一种数据结构,特点是符合FIFO,先进先出,由一个或多个消息对象构成的一个队列
Looper:循环的意思,作用就是管理消息队列,比如说从队列中取出消息交给对应的Handler进行处理AsyncTask中几个回调方法运行在哪个线程、DoInBackGround执行在哪个线程?
4个回调方法,其中三个运行在主线程(初始化,UI更新,进度条更新),DoInBackGround运行在子线程runOnUiThread为什么可以用来更新UI?
该方法内部做了判断当前线程是否为UI线程的操作
不是UI线程则将该action添加到mHandler所在的UI线程的消息队列中
是UI线程,则直接执行使用Handler+Thread的方式在子线程更新UI时,Handler对象可以在子线程中创建吗?
不能,只能在主线程创建,再传到子线程中
- Handler的post方法为什么可以用来更新UI?
该方法内部实际上是发送一个延迟的消息给该线程的Handler处理,该方法内部将消息对象加入了消息队列,
最终也是把Runnable对象给放到了UI线程中执行
如果是更新UI,则这个Handler对象必须创建在UI线程中
(六)Android面试题(六)JSON、XML、MediaPlay生命周期
JSON中有几种数据类型,解析对应数据类型分别用哪个类?
四种类型:
第一种类型是标量(scalar),也就是一个单独的字符串(string)或数字(numbers),
比如"北京"这个单独的词。
第二种类型是序列(sequence),也就是若干个相关的数据按照一定顺序并列在一起,
又叫做数组(array)或列表(List),比如"北京,上海"。对应JSONAray;
第三种类型是映射(mapping),也就是一个名/值对(Name/value),即数据有一个名称,
还有一个与之相对应的值,这又称作散列(hash)或字典(dictionary)。对应String;
第四种,类似于Java中的类,对应JSONObject。有哪些方式可以做JSON数据的解析?
两种解析方式:
1)JSON普通解析方式,运用
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;对象来解析;
2)运用gson-2.1.jar包下的Gson类和与之Json数据相对应的Translate类来解析:创建Gson对象,调用它的fromjson方法有哪些方式可以做XML数据解析?
DOM在处理XML文件时,将XML文件解析成树状结构并放入内存中进行处理。
SAX则是以事件作为解析XML文件的模式,它将XML文件转化成一系列的事件,由不同的事件处理器来决定如何处理。
XML文件较大时,选择SAX技术是比较合理的。
XML pull通过循环驱动事件来解析:判断事件的类型,获取事件中的内容
对于XML文档较大但只需要文档的一部分时,XML Pull解析器则是更为有效的方法。请阐述一种XML解析方式的基本流程。
1. 获取解析器对象XmlPullParser对象parser
2. 可以给parser对象设置输入的编码方式
3. 循环驱动事件进行解析
事件分为4类:
a. 开始文档:XmlPullParser.START_DOCUMENT值为0
b. 结束文档:XmlPullParser.END_DOCUMENT值为1
c. 开始标签:XmlPullParser.START_TAG值为2
d. 结束标签:XmlPullParser.END_TAG值为3
一个事件处理完毕之后,需要提供parser的next方法去驱动下一个事件自定义View有哪几种方式?
自绘控件、组合控件、以及继承控件。MediaPlayer的生命周期是怎样的?
1.Idle 状,2.End 状态,3.Initialized 状态,4.Prepared 状态,5.Preparing 状态,6.Started 状态,7.Paused 状态,8.Stop 状态,9.PlaybackCompleted状态,10.Error状态请阐述图片加载的基本流程及优化方案。
通过HttpURLConnection c_onn = (HttpURLConnection) url.openConnection()
取得图片链接,通过InputStream in = conn.getInputStream()取得图片图片io流
取得Bitmap图片。
通过LuraCache来优化图片缓存