Android面试复习(Android篇二)

来源:互联网 发布:成都犀牛软件培训班 编辑:程序博客网 时间:2024/06/10 20:34

1.广播

1.1注册广播的两种方式

  • 动态注册让它继承自BroadcastReceiver,并重写父类的onReceive()方法即可。动态注册广播接收器一定要取消注册才可以。且必须要在程序启动之后才能接收到广播,灵活性比较好
  • 静态注册可以使用户不用启动程序即可接受广播。

1.2广播的类型

  • 标准广播:能够被其他应用程序接收到,且同时到达多个广播接收器
  • 有序广播:能够被其他应用程序接收到,按照设置的优先级前面的广播可以将后面的广播截断。

1.3本地广播

本地广播使用LocalBroadcastManager对广播进行管理,使得在这个机制下发出的广播只能在应用程序内部传递,并且广播接收器也只能接收来自内部的广播。

2数据存储方案

2.1数据存储类型

  • 文件存储:不对存储的内容进行任何格式化的处理,只适合于一些简单的文本文件或者二进制文件
  • SharedPreferences存储:使用键值对的方式存储数据并且可以支持多种不同的数据类型存储。l例如存储的是整型,那么读取出来的也是整型
  • SQlite数据库存储:是Android内置的关系型数据库,可以使用其来进行比较复杂的关系进行存储

数据库的操作:创建和升级,增删改查。
2.1.1 创建表和索引
  为了创建表和索引,需要调用 SQLiteDatabase 的 execSQL() 方法来执行 DDL 语句。如果没有异常,这个方法没有返回值。    例如,你可以执行如下代码:
db.execSQL("CREATE TABLE user(_id INTEGER PRIMARY KEY
AUTOINCREMENT, username TEXT, password TEXT);");

  这条语句会创建一个名为 user的表,表有一个列名为 _id,并且是主键,这列的值是会自动增长的整数。另外还有两列:username( 字符 ) 和 password( 字符 )。 SQLite 会自动为主键列创建索引。   通常情况下,第一次创建数据库时创建了表和索引。要 删除表和索引,需要使用 execSQL() 方法调用 DROP INDEX 和 DROP TABLE 语句。
2.1.2 添加数据 
有两种方法可以给表添加数据。
使用 execSQL() 方法执行 INSERT, UPDATE, DELETE 等语句来更新表的数据。
execSQL() 方法适用于所有不返回结果的 SQL 语句。例如:
String sql = "insert into user(username,password) values ('finch','123456');//插入操作的SQL语句
db.execSQL(sql);//执行SQL语句

使用 SQLiteDatabase 对象的 insert()。
ContentValues cv = new ContentValues();
cv.put("username","finch");//添加用户名
cv.put("password","123456"); //添加密码
db.insert("user",null,cv);//执行插入操作

2.1.3 更新数据(修改)
使用SQLiteDatabase 对象的 update()方法。
ContentValues cv = new ContentValues();
cv.put("password","654321");//添加要更改的字段及内容
String whereClause = "username=?";//修改条件
String[] whereArgs = {"finch"};//修改条件的参数
db.update("user",cv,whereClause,whereArgs);//执行修改

该方法有四个参数:    表名;   列名和值的 ContentValues 对象;    可选的 WHERE 条件;    可选的填充 WHERE 语句的字符串,这些字符串会替换 WHERE 条件中的“?”标记,update() 根据条件,更新指定列的值. 
使用execSQL方式的实现
String sql = "update [user] set password = '654321' where username="finch";//修改的SQL语句
db.execSQL(sql);//执行修改

2.1.4 删除数据
①使用SQLiteDatabase 对象的delete()方法。
String whereClause = "username=?";//删除的条件
String[] whereArgs = {"finch"};//删除的条件参数
db.delete("user",whereClause,whereArgs);//执行删除

②使用execSQL方式的实现
String sql = "delete from user where username="finch";//删除操作的SQL语句
db.execSQL(sql);//执行删除操作

2.1.5 查询数据
* 使用 rawQuery() 直接调用 SELECT 语句
Cursor c = db.rawQuery("select * from user where username=?",new Stirng[]{"finch"});
if(cursor.moveToFirst()) {
String password = c.getString(c.getColumnIndex("password"));
}

  返回值是一个 cursor 对象,这个对象的方法可以迭代查询结果。 如果查询是动态的,使用这个方法就会非常复杂。例如,当你需要查询的列在程序编译的时候不能确定,这时候使用 query() 方法会方便很多。
* 通过query实现查询
  query() 方法用 SELECT 语句段构建查询。   SELECT 语句内容作为 query() 方法的参数,比如:要查询的表名,要获取的字段名,WHERE 条件,包含可选的位置参数,去替代 WHERE 条件中位置参数的值,GROUP BY 条件,HAVING 条件。   除了表名,其他参数可以是 null。所以代码可写成:
Cursor c = db.query("user",null,null,null,null,null,null);//查询并获得游标
if(c.moveToFirst()){//判断游标是否为空
for(int i=0;i<c.getCount();i++){ 
c.move(i);//移动到指定记录
String username = c.getString(c.getColumnIndex("username");
String password = c.getString(c.getColumnIndex("password"));
}
}

2.1.6 使用游标
  不管你如何执行查询,都会返回一个 Cursor,这是 Android 的 SQLite 数据库游标,使用游标,你可以:  
通过使用 getCount() 方法得到结果集中有多少记录; 
通过 moveToFirst(), moveToNext(), 和 isAfterLast() 方法遍历所有记录;
通过 getColumnNames() 得到字段名;
通过 getColumnIndex() 转换成字段号;
通过 getString(),getInt() 等方法得到给定字段当前记录的值;
通过 requery() 方法重新执行查询得到游标;
通过 close() 方法释放游标资源;
例如,下面代码遍历 user表:
Cursor result=db.rawQuery("SELECT _id, username, password FROM user");
result.moveToFirst();
while (!result.isAfterLast()) {
int id=result.getInt(0);
String name=result.getString(1);
String password =result.getString(2);
// do something useful with these
result.moveToNext();
}
result.close()

事务:事务的特性是保证让一系列的操作要么全部完成要么一个都完不成。首先开启事务,然后在异常捕获的代码快中去执行具体的操作,但所有操作都完成的时候表示事务已经执行成功了。
ACID事务 :指数据库事务正确执行的四个基本要素的缩写。包含:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。一个支持事务(Transaction)的数据库,必需要具有这四种特性,否则在事务过程(Transaction processing)当中无法保证数据的正确性,交易过程极可能达不到交易方的要求。

数据库的升级:可以使用判断当前数据库版本的方式,若是无就创建两个,若是有第一版则只更新第二版的内容不用将第一版的内容全部删掉再重写。

内容提供器

内容提供器:主要用于在不同程序间的实现数据共享功能,允许一个程序访问另一个程序的数据并且保证被访问数据的安全性。

读取其他程序中的程序:使用ContentResolverlei类,有增删改查等等方式,但和数据库不同的是,这里不指定表名而是指定一个Uri参数。Uri参数由权限加路径组成。权限一般采用程序宝名来命名。com.example.app.provider就可以,路径为table完整的Uri参数content://com.example.app.provider/table1.

创建自己的内容提供器
1. 使用ContentProvider类重写其中的六个方法onCreate(),query(),insert(),update(),delete(),getType().
2. 使用UriMacher这个类实现匹配内容Uri的功能,

getType()方法是每个内容提供器都必须提供的一个方法,用于获取Uri对象所对应的MIME类型,

3.服务

3.1多线程

可以继承Thread类,也可以实现Runable接口来定义一个线程或者使用匿名类的方式。

new Thread(new Runable(){
@Override
public run(){
}).start();

3.2在子线程更新UI

Android不允许在子线程中更新UI操作,但提供了一套异步消息处理机制解决了在子线程中更新UI操作的问题。

3.3异步消息处理机制

  1. Message: 在线程之间传递的消息,可以在内部之间携带少量信息,用于在不同程序之间交换数据。
  2. Handler: 用于发送和处理消息。
  3. MessageQueue: 消息队列,用于存放所有通过Handler发送的消息。
  4. Looper: 消息队列的管家,调用loop()方法,就会进入到一个无限循环当中只要发现MessageQueue有消就会将它取出发送到handleMessage()中去。

子线程更新UI流程:在主进程创建一个Handler对象,并重写handleMessage()方法,然后当子进程需要进行UI操作时就创建一个Message对象,并且通过Handler将信息发送出去。之后消息被添加到MessageQueue队列中等待操作,而Looper一直尝试从MessageQueue取出消息分发会HandleMessage()方法中,由于Handle是在主线程中创建的所以此时handleMessage()方法也会在主线程中运行。

3.4AsyncTask

AsyncTask是一个抽象类,必须创建一个一个子类去继承它,在继承时可以为AsyncTask类指定三个泛型参数。
1. Params: 执行AsyncTask所需要传入的参数,可用于在后台任务中使用。
2. Progress:在页面上显示的进度
3. Result: 任务执行完如果需要对结果进行返回就指定泛型作为返回类型。

重写AsyncTask的几个方法才能完成对任务的的定制。
1. onPreExecute(): 用于界面上的一些初始化操作,比如显示一个进度条等。
2. doInBackground(params):这个方法中的所有代码都会在子线程中运行,同样不能进行UI操作,如果需要更新UI则用publishProgress(Progress…)来完成。
3. onProgressUpdate(Progress..): 当在后台调用了publishProgress(Progress..)方法后,在这个方法中就可以对UI进行操作。
4. onPostExecute(Result).当后台任务执行完毕并通过return 进行返回时,返回的数据会作为参数传递到该方法中,可以利用该参数进行一些UI操作,例如关闭掉进度条等。

3.5服务

定义一个服务

 public class MyService extends Service{@Overridepublic IBinder onBind(Intent intent){return null;}}

如需要在服务中去处理一些事情则需要重写Service的另外一些方法
onCreate(),onStartCommand(),onDestroy().
使用Intent来启动和停止服务。

活动和服务进行通信
新建一个类让他继承Binder,然后在类的内部提供相应的方法,在Service创建该类的实例并且在onBind()方法中返回这个类的实例。然后在活动中就可以调用该类所提供的方法。

服务的生命周期:分两种,一种启动服务,一种绑定服务。但相互有影响。
服务的生命周期

服务的更多使用技巧
1. 防止服务因为内存问题等被回收掉可以使用前台服务。
2.如果直接在服务中执行一些耗时操作,很容易出现ANR(appliacation not responding)因此要使用服务的多线程编程技术,但防止程序员忘开线程或者忘记销毁,可以使用IntentService。
3. IntentSevice: 新建一个MyIntentService继承IntentService类,然后提供一个无参的构造函数,在内部调用父类的有参构造函数,实现onHandleIntent(),这个抽象方法,这个方法就是在子进程中运行,并且执行完后自动停止,重新onDestroy()方法。

3.6网络

Android发送Http请求方式:
1. HttpURLConnection
2. HttpClient

数据格式:
1. XML:可扩展标记语言
2. JSON:数据交换格式
3. XML与JSON的对比
两者都是文本表示的数据格式,可以跨平台、跨系统交换数据。XML适合标记文档,但是JSON是数据交互的理想格式。
两者最大的不同在于,XML是一个完整的标记语言,而JSON不是。XML利用标记语言的特性提供了绝佳的延展性(如XPath),在数据存储,扩展及高级检索方面优势明显,而JSON则由于比XML更加小巧,以及浏览器的内建快速解析支持,使得其更适用于网络数据传输领域。
就可读性而言,两者都具备很好的可读性,但XML文档的可读性更高。
就数据表示和传输性能而言,JSON明显比XML简洁,格式简单,占用带宽少。

LBS

获取自己的经纬度:在onCreate()方法获取LocationManager的实例,然后是哟个getPrvovider()获取位置提供器,使用getLastKnowLocation()方法获取到当前记录位置细腻使用showlocation即可。
反向地理编码:GeoCoder和GeoCoding API不过需要连接网络,我们选择的是不连网的GeoCoding
百度地图API。

传感器

获取SensorManager的实例,然后指定传感器的类型,使用SensorEventListener进行监听。

发送短信

smsManager

播放音频

mediaPlayer

原创粉丝点击