前言
根据笔者自己的阅读以及项目经验总结而言,不同于网上的copy来copy去。
转载请注明出处 http://www.baidujava.com/android-interview/
Handler
在子线程里面创建 Handler 对象会抛出异常Can't create handler inside thread that has not called Looper.prepare()
。
但是加上Looper.prepare();
不会抛出异常, 这个因为 Handler 对应一个 Looper,一个 Looper 对应一个线程。
|
|
用 ThreadLocal 保存 Looper 对象ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
通过Looper.prepare()来创建Looper对象(消息队列封装在Looper对象中),并且保存在sThreadLoal中,然后通过Looper.loop()来执行消息循环,这两步通常是成对出现的!!
xml解析
个人理解:
Dom把xml全部加载,比较耗内存。
Sax是事件驱动,但是不支持随机读取,不能只处理部分元素。
Pull是Sax的改进,可以提前结束读取,Sax不能提前结束。
基本的解析方式包含两种,一种是事件驱动的(代表SAX),另一种方式是基于文档结构(代表DOM)。其他的只不过语法不一样而已。
Dom 方式解析xml,比较简单,并可以访问兄弟元素,但是需要将整个xml文档加载到内存中,对于android设备来说,不推荐使用dom的方式解析xml。
|
|
sax和pull都是基于事件驱动的xml解析器,在解析xml时并不会加载整个的xml文档,占用内存较少,因此在android开发中建议使用sax或者pull来解析xml文档。
SAX,全称Simple API for XML,既是一种接口,也是一种软件包。它是一种XML解析的替代方法。SAX不同于DOM解析,它逐行扫描文档,一边扫描一边解析。由于应用程序只是在读取数据时检查数据,因此不需要将数据存储在内存中,这对于大型文档的解析是个巨大优势。
继承 extends DefaultHandler 需要复写下面几个方法。这几个方法是回调方法,解析时,若发生事件(文档开头结尾 元素开头结尾)的话会被调用这些回调方法。
- startDocument() and endDocument() – Method called at the start and end of an XML document.
- startElement() and endElement() – Method called at the start and end of a document element.
- characters() – Method called with the text contents in between the start and end tags of an XML document element.
pull和sax的区别
Pull解析器和SAX解析器虽有区别但也有相似性。他们的区别为:SAX解析器的工作方式是自动将事件推入注册的事件处理器进行处理,因此你不能控制事件的处理主动结束;
而Pull解析器的工作方式为允许你的应用程序代码主动从解析器中获取事件,正因为是主动获取事件,因此可以在满足了需要的条件后不再获取事件,结束解析。这是他们主要的区别。
Android 系统架构
- Linux 内核层,为 Android 设备提供了底层的驱动,如蓝牙驱动、照相机驱动等等
- 系统运行库层,这些曾通过一些 C/C++ 库为 Android 系统提供了主要的特性支持,如 SQlite 提宫数据库,Webkit 提高了浏览器内核
需要注意的是这一层也有 Android 运行时候需要的核心库
Android 运行时库包括了 Dalvik 虚拟机 - 应用框架层,这一层提供了编写 App 时候需要用到的 Api
- 应用层,所有安装在手机上的 App 都属于这一层,包括短信、QQ 等
四大组件
activity和service默认是运行在应用进程的主线程中,四大组件默认都是和activity运行在同一个主线程中的
- Activity 活动
- Service 服务
Service的Oncreate()方法只有第一次执行,而OnStartCommand()每次启动服务都会调用 - Broadcast 广播接收器
最常用的广播就是android.provider.Telephony.SMS_RECEIVED
|
|
- ContentProvider 内容提供者
注意如果自己定义一个ContentProvider暴露为其他 App 使用,通常用SQLite或者文件实现,也可以用 Json 或者 Xml 实现等等。
4大组件都需要在 xml 文件里注册,注意它们是平级的关系。
存储化技术
- 文件存储 存储一些图片、视频、doc 等等,保密性不强
- SharedPreference 多用于存储用户配置、密码等等
也可在里面存储视频当前播放的位置,按home键返回后重新从当前位置读取 - 数据库 Sqlite 存储一些格式复杂的数据,比如短信中 联系人和对应的短信记录
文件的操作模式
- MODE_APPEND 追加内容
- MODE_PRIVATE 覆盖文件中的内容
MODE_WORLD_READABLE已经在4.2废弃MODE_WORLD_WRITEABLE已经在4.2废弃
打开文件示例代码
|
|
读取文件 代码示例
|
|
TestUtils
|
|
这儿的 isEmpty 方法可以判断 x 为 null 或者长度为 0
SQlite
使用adb shell
中的sqlite3
打开数据库
getWritableDatabase VS getReadableDatabase
getWritableDatabase
和 getReadableDatabase
取得的实例对数据库进行读和写的功能,不是像字面意思上一个读写权限和只读权限
两者的区别在于
- getWritableDatabase取得的实例是以读写的方式打开数据库,如果打开的数据库磁盘满了,此时只能读不能写,此时调用了getWritableDatabase的实例,那么将会发生错误(异常)
- getReadableDatabase取得的实例是先调用getWritableDatabase以读写的方式打开数据库,如果数据库的磁盘满了,此时返回打开失败,继而用getReadableDatabase的实例以只读的方式去打开数据库
intent-filter
intent-filter 可以动态注册也可以静态注册
下面是静态注册的代码,直接写在xml文件里1234567891011121314<application><activity name=""/><receiver android:name=".MyBroadcastReceiver"><!-- intent过滤器,指定可以匹配哪些intent, 一般需要定义action 可以是自定义的也可是系统的 --><intent-filter><action android:name="com.app.bc.test"/></intent-filter></receiver></application>//// java code 这儿的intent也叫隐式intentIntent intent = new Intent(“com.app.bc.test”);sendBroadcast(intent);//发送广播事件
动态注册
|
|
- 静态注册:在AndroidManifest.xml注册,android不能自动销毁广播接收器,也就是说当应用程序关闭后,还是会接收广播。
- 动态注册:在代码中通过registerReceiver()手工注册.当程序关闭时,该接收器也会随之销毁。当然,也可手工调用unregisterReceiver()进行销毁。
显示intent 和隐式intent
显示
|
|
隐式,它会自动寻找能处理 intent-filter 里面设置了处理该的 action 的Activity。
比如有手机装了多个浏览器,使用隐式intent会弹出让用户选择哪个浏览器。
Timer 和 Alarm
Timer 不适用需要长期在后台运行的定时任务,长时间不操作,CPU会睡眠状态,这会影响Timer的定时任务无法执行
Alarm 机制具有唤醒CPU的功能
工具方法
訪問Url,利用get請求,請返回的數據轉化為字符串
怎么更新UI
注意不能使用子线程更新 UI,可以用 Handler 或者 Activity.runOnUiThread
public final void runOnUiThread (Runnable action)
Added in API level 1
Runs the specified action on the UI thread. If the current thread is the UI thread, then the action is executed immediately. If the current thread is not the UI thread, the action is posted to the event queue of the UI thread.
Parameters
action the action to run on the UI thread
Adapter 4个重写方法
BaseAdapter基本结构
- public int getCount() :适配器中数据集中 数据的个数,即ListView需要显示的数据个数
- public Object getItem(int position) : 获取数据集中与指定索引对应的数据项
- public long getItemId(int position) : 获取指定行对应的ID
- public View getView(int position, View convertView, ViewGroup parent) :获取每一个Item的显示内容
|
|
在使用BaseAdapter时,我们需要自己创建一个类继承BaseAdapter,然后Eclipse会提醒我们实现上述四个方法,当给ListView设置了我们自己写的Adapter后,ListView内部会调用上述四个方法。
参考文章
ListView using BaseAdapter – Android http://www.pcsalt.com/android/listview-using-baseadapter-android/