面试题
2015-12-01 17:31
525 查看
#Java#
StringBuffer和StringBuilder:
1. 二者方法基本相同;
2. StringBuffer线程安全,StringBuilder更快;
Vector和ArrayList:
1. ArrayList在内存不够时默认是扩展50% + 1个,Vector是默认扩展1倍。
2. Vector提供indexOf(obj, start)接口,ArrayList没有。
3. Vector线程安全,但是大多数情况下不使用Vector,因为线程安全需要更大的系统开销。
HashTable和HashMap:
1. HashTable有序,HashMap无序;
2. HashTable线程安全;
3. HashTable不支持KV为NULL,HashMap支持KV为NULL;
4. HashTable中hash数组默认大小是11,增加的方式是 old*2+1。HashMap中hash数组的默认大小是16,而且一定是2的指数。
5. 哈希值的使用不同,HashTable直接使用对象的hashCode,而HashMap重新计算hash值,而且用与代替求模;
Thread和Runnable区别:
1. Runnable可多继承、重复启动;
2. Thread是其子类,会开启新线程;
各种引用:
1. 强引用:不会被GC回收;
2. WeakReference:置为null(不存在强引用)即可被GC回收,常用于存储元数据;
3. SoftReference:置为null也不会被立即回收(除非系统内存不够),常用作缓存;
4. PhantomReference:其get方法永远返回null,常用于跟踪引用对象何时被加入ReferenceQueue。
线程Sleep和wait区别:
1. 来自不同的类,分别是Thread和Object;
2. sleep没有释放锁,而wait释放了锁,使得其他线程可以使用同步控制块或者方法;
3. wait、notify和notifyAll只能在同步控制方法(块)使用,sleep可在任何地方;
4. sleep必须捕获异常,而wait、notify和notifyAll不需要捕获异常;
线程同步(volatile+synchronized+wait()+notify()+notifyAll()):
1. volatile修饰变量,不会造成阻塞,适用于读操作比写操作频繁得多的情况;
2. 普通synchronized方法的锁是所在类的实例,只有当类为单例时才能保证绝对同步;
3. static synchronized方法的锁是类,绝对同步;
4. synchronized(lock)块的锁是lock对象,如果是synchronized(this),则只有当类为单例时才能保证绝对同步;
5. notify()唤醒阻塞队列中的第一个对象,notifyAll()唤醒所有;
volatile vs synchronized:
http://www.javaperformancetuning.com/news/qotm051.shtml
多线程下载文件及断点续传(HttpURLConnection+RandomAccessFile):
1. 初始化文件及其长度:
int fileSize = HttpURLConnection.getContentLength();
RandomAccessFile file = new RandomAccessFile(fileName, "rw”);
file.setLength(filesize);
2. 根据文件长度和线程数目确定每个线程下载的起始位置:
HttpURLConnection.setRequestProperty("Range", “bytes=startPosition-endPosition”);
3. 记录所有Thread的已下载长度,便于下次继续下载,并实时更新;
4. 从指定位置写入:
file.seek(startPosition);
#Android基础#
App、Process、Task、Activity关系:
1. 一般一个APP(即一个包名)对应一个Process(一个虚拟机),某些Process是App的容器,也可能多个App共享一个Process;
2. Task是一个Activity的栈,可能来源于多个App;
3. 四大组件和Application都可在Manifest中指定process包名和mutiprocess属性;
4. 如果A应用调用了B应用的组件,则会启动B的进程,但仍然只有一个Task,因为默认处于同一个stack;
5.一个应用的组件可以被多个不同应用调用,所以可以跑在多个进程中;
6.通过shareuserID可以将多个apk,跑在同一个进程中。
http://blog.csdn.net/guolin_blog/article/details/41087993
Activity/Service生命周期:
1. Service不需要onResume()/onPause()/onStop();
2. startService(): 如果为创建则调用onCreate(),否则onStart(),除非调用stopService()否则一直运行;
3. bindService(): 如果未创建则调用onCreate(),否则onBind(),并返回Ibinder接口,常用于通信;
Service与Activity通信:
1. Activity调用bindService,并实现ServiceConnection接口;
2. Service实现IBinder内部类,调用serviceBinder的transact方法传递数据;
如何启动其他应用:
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setComponent(new ComponentName(packageName, className));
而这个className可以通过PackageManager查询Intent得到;
Activity的LaunchMode:
1. standard: 不复用,始终创建新实例放到栈顶;
2. singleTop: 只复用位于栈顶的Activity;
3. singleTask: 复用同一栈中的Activity,将其顶部的所有Activity出栈,并将其置于栈顶;
4. singleInstance: 始终复用,而且是放到另外一个单独的栈中,因此不会使其他Activity出栈;
5. 如果Activity声明为singleInstance,则重复start会调用onNewIntent(),而不是onCreate();
自定义组件:
1. onMeasure() ;确定宽高(UNSPECIFIED,EXACTLY,AT_MOST);
2. onLayout();确定位置(mLeft,mTop,mLeft,mBottom);
3. onDraw() ;只重绘添加了DRAWN标志位的View;
http://blog.csdn.net/qinjuning/article/details/8051811 http://blog.csdn.net/qinjuning/article/details/8074262 http://blog.csdn.net/qinjuning/article/details/7110211
View与SurfaceView:
1. View的显示绘制与事件处理处于同一线程,所以只能在主线程操作UI;
2. SurfaceView中通过SurfaceHolder得到Canvas对象后可以在新线程中绘制,适合快速实时渲染:
SurfaceHolder holder=this.getHolder();
holder.addCallback(new SurfaceHolder.Callback(){
@Override
public void surfaceCreated(SurfaceHolder holder) {
new Thread(){
@Override
public void run(){
Canvas canvas=holder.lockCanvas();// 也可以只重绘某个区域:lockCanvas(Rect)
// Draw something on canvas
holder.unlockCanvasAndPost(canvas);
}
}.start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {}
});
3. SurfaceHolder的setType函数来设置绘制的类型:
SURFACE_TYPE_NORMAL:用RAM缓存原生数据的普通Surface;
SURFACE_TYPE_HARDWARE:适用于DMA(Direct memory access )引擎和硬件加速的Surface;
SURFACE_TYPE_GPU:适用于GPU加速的Surface;
SURFACE_TYPE_PUSH_BUFFERS:表明该Surface不包含原生数据,Surface用到的数据由其他对象提供,
在Camera图像预览中就使用该类型的Surface,有Camera负责提供给预览Surface数据,这样图像预览会比较流畅。
如果设置这种类型则就不能调用lockCanvas来获取Canvas对象了。
SparseArray:
1. 用于替换HashMap<Integer,Object>;
2. 内部采用非递归实现二分查找,而且不会像HashMap一样产生对键值对的封装数据结构,基本上是以时间换空间(put和get慢,但是节省存储开销);
3. 内部还有个DELETE字段,便于remove后下次再重新put;
文件:
1. 读取IOStream:
context.openFileInput(name)
context.openFileOutput(name, mode)
2. 四种mode: MODE_APPEND、MODE_PRIVATE、MODE_WORLD_READABLE、MODE_WORLD_WRITABLE;
SharedPreferences:
1. 读取数据:
SharedPreferences sharedPreferences = activity.getPreferences(mode);
SharedPreferences sharedPreferences = context.getSharedPreferences("config", mode);
2. 四种mode: MODE_MULTI_PROCESS、MODE_PRIVATE、MODE_WORLD_READABLE、MODE_WORLD_WRITABLE;
3.修改数据:
Editor editor = sharedPreferences.edit();
editor.putString("key", "value");
editor.commit();
4. 监听数据:
sharedPreferences.registerOnSharedPreferenceChangeListener(new OnSharedPreferenceChangeListener(){
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {}
});
5. 读取其他应用数据:
Context otherAppContext = context.createPackageContext(otherAppPackageName, Context.CONTEXT_IGNORE_SECURITY);
SharedPreferences sharedPreferences = otherAppContext.getSharedPreferences("config", Context.MODE_WORLD_READABLE);
然后还需要在配置文件中声明android:sharedUserId;
ContentProvider:
public static final Uri URI = Uri.parse("content://com.xxx.provider/peoples");
private static final int ITEM = 1, ITEM_ID = 2;
private static final UriMatcher mather = new UriMatcher(UriMatcher.NO_MATCH);
static{
mather.addURI(URI.getAuthority(), "peoples", ITEM);
mather.addURI(URI.getAuthority(), "peoples/#", ITEM_ID);
}
@Override
public String getType(Uri uri){
switch (mather.match(uri)){
case ITEM:
return "vnd.android.cursor.dir/peoplelist";
case ITEM_ID:
return "vnd.android.cursor.item/peopleitem";
default:
throw new IllegalArgumentException("uri Illegal" + uri);
}
}
ContentProvider权限控制:
1. 在Manifest中控制读写权限:android:readPermission(读)、android:writePermission(写)、android:permission(读写);
2. 控制URI路径权限:
<path-permission android:pathPrefix="/hello" android:readPermission="READ_HELLO_CONTENTPROVIDER" />
3. 通过Intent传递URI权限:
Intent intent = new Intent(this,ReadProvider.class);
intent.setClassName("com.example.propermissiongrant", "com.example.propermissiongrant.MainActivity");
intent.setData(Uri.parse("content://cn.wei.flowingflying.propermission.PrivProvider/world/1"));
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);
http://blog.csdn.net/flowingflying/article/details/17412609
SQLite:
1. 数据库结构变动:
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion < ver) {
db.execSQL("ALTER TABLE table ADD COLUMN column INTEGER");
}
}
2. 事务处理:
db.beginTransaction();
db.beginTransactionWithListener(new SQLiteTransactionListener(){
@Override
public void onBegin() {}
@Override
public void onCommit() {}
@Override
public void onRollback() {}
});
int res=db.update(table, values, whereClause, whereArgs);
if(res>-1){
db.setTransactionSuccessful(); //如果不设置,后面将会滚
}
db.endTransaction();
AsyncTask
1. 内部采用ThreadPoolExecutor+LinkedBlockingQueue+Handler实现;
2. execute方法只能在UI线程执行,且只能执行一次。
Handler+Looper+Message+MessageQueue
1. Handler的obtainMessage方法效率更高。
2. Message内部有个消息池,最大值50,采用链表存储。
3. MessageQueue内部init/destroy/poll/wake等均为native实现。
4. Thread默认是没有相关联的Looper的,可通过prepare()和loop()创建。
5. 一个Handler只关联一个Thread及其MessageQueue。
Serializable与Parcelable:
1. Serializable源于JDK,是为了方便文件操作、数据库、网络流对象序列化;
2. Parcelable源于Android SDK,是为了在组件中传递数据,序列化效率较高、内存开销小,但不适合数据持久化存储;
3. Serializable一般不需要自己写实现,不保存静态变量,可以使用Transient关键字对部分字段不进行序列化,也可以覆盖writeObject、readObject方法以实现序列化过程自定义;
4. Parcelable需要实现writeToParcel、describeContents函数以及静态的CREATOR变量,实际上就是将如何打包和解包的工作自己来定义,而序列化的这些操作完全由底层实现。
CursorAdapter:
1. 继承自BaseAdapter,实现了getView(),但是添加了newView()和bindView()抽象方法,其中前者只回调一次,后者会多次回调;
2. Cursor必须包含列_id;
HttpClient(Apache)和UrlConnection(JDK):
1. HttpClient支持所有method和header;
2. HttpClient支持持久连接和自动重定向;
3. HttpClient仅支持HTTP的协议;
http://www.cnblogs.com/devinzhang/archive/2012/01/17/2325092.html
进程间通信:
1. 通过Intent调用;
2. 通过ContentProvider提供通用接口;
3. 通过Broadcast通知;
4. 通过AIDL暴露接口;
线程间通信:
1. Message: 消息,包含ID和数据;
2. Handler: 负责发送和处理Message(比如更新UI);
3. Looper: 负责抽取Message,主线程有默认的Looper,子线程需要调用Looper.prepare和Looper.loop();
4. MessageQueue: 负责以队列方式(FIFO)管理Message;
5. Thread: 负责调度整个消息循环,几消息循环的执行场所;
6. 一个Thread对应一个Looper和一个MessageQueue,但可对应多个Handler;
7. 不确定当前线程时,尽量调用view.post(Runnable), 还可以调用Activity的runOnUiThread(Runnable);
Touch事件传递,多个容器组件事件冲突问题:
1. dispatchTouchEvent(MotionEvent ev) 分发
2. onInterceptTouchEvent(MotionEvent ev) 拦截
3. onTouchEvent(MotionEvent ev) 处理
http://www.cnblogs.com/sunzn/archive/2013/05/10/3064129.html
硬件加速:
1. 3.0以上开始支持;
2. 分application/activity/window/view四个级别;
3. 自定义View时有些方法不支持硬件加速或者开启后效果有差异;
http://blog.csdn.net/song_shi_chao/article/details/7453778 http://blog.csdn.net/gemmem/article/details/7715837
单元测试:
http://www.cnblogs.com/jackxlee/archive/2011/10/21/2220315.html
#Android新API#
Loader/AsyncTaskLoader/CursorLoader(3.0新特性):
1. 实现LoaderManager.LoaderCallBack中的回调方法即可;
2. AsyncTaskLoader继承AsyncTask实现异步任务;
3. 内部通过ContentObserver实现数据变动监听并通知回调;
4. 内部通过在activity的onStart()方法中判断loader状态,防止重复启动;
#Android实际问题#
捕获全局异常:
UncaughtExceptionHandler,重写uncaughtException(Thread thread, final Throwable ex);
监听短信收发:
1. BroadcastReceiver:简单,但只能监听收到短信;
2. ContentOberver:监听短信数据库,不过4.4开始出于安全考虑只有系统短信APP才有这个权限;
http://www.blogjava.net/anymobile/articles/328396.html
布局优化:
1.使用LinearLayout时结合layout:weight,尽量不要写死;单要结合RelativeLayout使用,因为前者用多了会大大增加布局层数,影响布局效率;
2.AdapterView里面使用ViewHolder重用布局,但如果不是每个ITEM布局都相同,最好使用多个布局,而不是通过setVisibility实现,否则会影响性能(虽然不用measure但是会占用内存,而且findViewById也会调用耗时)。
内存优化:
1. 不要在Activity内滥用static变量;
2. 不要在主线程做耗时操作(网络请求、文件和数据库操作等),也不要在子线程更新UI,可以使用Handler或者AsyncTask;
3. decode图片的时候,结合BitmapFactory.Options,先将inJustDecodeBounds设为true,decode之后通过outWidth和outHeight计算inSampleSize,然后将inJustDecodeBounds设为false,并再次decode。
4. Bitmap注意回收: if(bitmap!=null&&!bitmap.isRecycled()){bitmap.recycle();}
5. 执行跨Activity的后台异步任务时,context尽量传applicationContext,而不是activity,否则会因为被引用而造成Activity内的对象在任务执行完之前都不能被释放;
轮询的实现:
1. Service+Thread: 休眠后线程容易挂起或被用户杀掉;
2. Service+AlarmManager+Thread: 调用AlarmManager的setRepeating()开始轮询,调用cancel()方法停止轮询;
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/0401/1609.html
其他问题:
1. 多重嵌套Fragment如何有效的同步更新UI?
可在需要同步更新的所有Fragment的onResume()方法注册相同的BroadcastReceiver,然后在onPause()取消注册;当需要同步更新UI时发送广播,这样还能防止去更新已被回收的Fragment而引发的异常。
#软件工程与架构设计#
设计模式:
1. 创建范例(如何创建实例):工厂、单例、建造者等;
2. 结构范例(类和对象复合关系):适配器、代理、组合、桥接等;
3. 行为范例(对象之间如何通讯):观察者、命令、迭代器等;
架构设计:
1. 如何设计网络请求与响应框架;
2. 如何设计图片加载和缓存框架;
StringBuffer和StringBuilder:
1. 二者方法基本相同;
2. StringBuffer线程安全,StringBuilder更快;
Vector和ArrayList:
1. ArrayList在内存不够时默认是扩展50% + 1个,Vector是默认扩展1倍。
2. Vector提供indexOf(obj, start)接口,ArrayList没有。
3. Vector线程安全,但是大多数情况下不使用Vector,因为线程安全需要更大的系统开销。
HashTable和HashMap:
1. HashTable有序,HashMap无序;
2. HashTable线程安全;
3. HashTable不支持KV为NULL,HashMap支持KV为NULL;
4. HashTable中hash数组默认大小是11,增加的方式是 old*2+1。HashMap中hash数组的默认大小是16,而且一定是2的指数。
5. 哈希值的使用不同,HashTable直接使用对象的hashCode,而HashMap重新计算hash值,而且用与代替求模;
Thread和Runnable区别:
1. Runnable可多继承、重复启动;
2. Thread是其子类,会开启新线程;
各种引用:
1. 强引用:不会被GC回收;
2. WeakReference:置为null(不存在强引用)即可被GC回收,常用于存储元数据;
3. SoftReference:置为null也不会被立即回收(除非系统内存不够),常用作缓存;
4. PhantomReference:其get方法永远返回null,常用于跟踪引用对象何时被加入ReferenceQueue。
线程Sleep和wait区别:
1. 来自不同的类,分别是Thread和Object;
2. sleep没有释放锁,而wait释放了锁,使得其他线程可以使用同步控制块或者方法;
3. wait、notify和notifyAll只能在同步控制方法(块)使用,sleep可在任何地方;
4. sleep必须捕获异常,而wait、notify和notifyAll不需要捕获异常;
线程同步(volatile+synchronized+wait()+notify()+notifyAll()):
1. volatile修饰变量,不会造成阻塞,适用于读操作比写操作频繁得多的情况;
2. 普通synchronized方法的锁是所在类的实例,只有当类为单例时才能保证绝对同步;
3. static synchronized方法的锁是类,绝对同步;
4. synchronized(lock)块的锁是lock对象,如果是synchronized(this),则只有当类为单例时才能保证绝对同步;
5. notify()唤醒阻塞队列中的第一个对象,notifyAll()唤醒所有;
volatile vs synchronized:
http://www.javaperformancetuning.com/news/qotm051.shtml
多线程下载文件及断点续传(HttpURLConnection+RandomAccessFile):
1. 初始化文件及其长度:
int fileSize = HttpURLConnection.getContentLength();
RandomAccessFile file = new RandomAccessFile(fileName, "rw”);
file.setLength(filesize);
2. 根据文件长度和线程数目确定每个线程下载的起始位置:
HttpURLConnection.setRequestProperty("Range", “bytes=startPosition-endPosition”);
3. 记录所有Thread的已下载长度,便于下次继续下载,并实时更新;
4. 从指定位置写入:
file.seek(startPosition);
#Android基础#
App、Process、Task、Activity关系:
1. 一般一个APP(即一个包名)对应一个Process(一个虚拟机),某些Process是App的容器,也可能多个App共享一个Process;
2. Task是一个Activity的栈,可能来源于多个App;
3. 四大组件和Application都可在Manifest中指定process包名和mutiprocess属性;
4. 如果A应用调用了B应用的组件,则会启动B的进程,但仍然只有一个Task,因为默认处于同一个stack;
5.一个应用的组件可以被多个不同应用调用,所以可以跑在多个进程中;
6.通过shareuserID可以将多个apk,跑在同一个进程中。
http://blog.csdn.net/guolin_blog/article/details/41087993
Activity/Service生命周期:
1. Service不需要onResume()/onPause()/onStop();
2. startService(): 如果为创建则调用onCreate(),否则onStart(),除非调用stopService()否则一直运行;
3. bindService(): 如果未创建则调用onCreate(),否则onBind(),并返回Ibinder接口,常用于通信;
Service与Activity通信:
1. Activity调用bindService,并实现ServiceConnection接口;
2. Service实现IBinder内部类,调用serviceBinder的transact方法传递数据;
如何启动其他应用:
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setComponent(new ComponentName(packageName, className));
而这个className可以通过PackageManager查询Intent得到;
Activity的LaunchMode:
1. standard: 不复用,始终创建新实例放到栈顶;
2. singleTop: 只复用位于栈顶的Activity;
3. singleTask: 复用同一栈中的Activity,将其顶部的所有Activity出栈,并将其置于栈顶;
4. singleInstance: 始终复用,而且是放到另外一个单独的栈中,因此不会使其他Activity出栈;
5. 如果Activity声明为singleInstance,则重复start会调用onNewIntent(),而不是onCreate();
自定义组件:
1. onMeasure() ;确定宽高(UNSPECIFIED,EXACTLY,AT_MOST);
2. onLayout();确定位置(mLeft,mTop,mLeft,mBottom);
3. onDraw() ;只重绘添加了DRAWN标志位的View;
http://blog.csdn.net/qinjuning/article/details/8051811 http://blog.csdn.net/qinjuning/article/details/8074262 http://blog.csdn.net/qinjuning/article/details/7110211
View与SurfaceView:
1. View的显示绘制与事件处理处于同一线程,所以只能在主线程操作UI;
2. SurfaceView中通过SurfaceHolder得到Canvas对象后可以在新线程中绘制,适合快速实时渲染:
SurfaceHolder holder=this.getHolder();
holder.addCallback(new SurfaceHolder.Callback(){
@Override
public void surfaceCreated(SurfaceHolder holder) {
new Thread(){
@Override
public void run(){
Canvas canvas=holder.lockCanvas();// 也可以只重绘某个区域:lockCanvas(Rect)
// Draw something on canvas
holder.unlockCanvasAndPost(canvas);
}
}.start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {}
});
3. SurfaceHolder的setType函数来设置绘制的类型:
SURFACE_TYPE_NORMAL:用RAM缓存原生数据的普通Surface;
SURFACE_TYPE_HARDWARE:适用于DMA(Direct memory access )引擎和硬件加速的Surface;
SURFACE_TYPE_GPU:适用于GPU加速的Surface;
SURFACE_TYPE_PUSH_BUFFERS:表明该Surface不包含原生数据,Surface用到的数据由其他对象提供,
在Camera图像预览中就使用该类型的Surface,有Camera负责提供给预览Surface数据,这样图像预览会比较流畅。
如果设置这种类型则就不能调用lockCanvas来获取Canvas对象了。
SparseArray:
1. 用于替换HashMap<Integer,Object>;
2. 内部采用非递归实现二分查找,而且不会像HashMap一样产生对键值对的封装数据结构,基本上是以时间换空间(put和get慢,但是节省存储开销);
3. 内部还有个DELETE字段,便于remove后下次再重新put;
文件:
1. 读取IOStream:
context.openFileInput(name)
context.openFileOutput(name, mode)
2. 四种mode: MODE_APPEND、MODE_PRIVATE、MODE_WORLD_READABLE、MODE_WORLD_WRITABLE;
SharedPreferences:
1. 读取数据:
SharedPreferences sharedPreferences = activity.getPreferences(mode);
SharedPreferences sharedPreferences = context.getSharedPreferences("config", mode);
2. 四种mode: MODE_MULTI_PROCESS、MODE_PRIVATE、MODE_WORLD_READABLE、MODE_WORLD_WRITABLE;
3.修改数据:
Editor editor = sharedPreferences.edit();
editor.putString("key", "value");
editor.commit();
4. 监听数据:
sharedPreferences.registerOnSharedPreferenceChangeListener(new OnSharedPreferenceChangeListener(){
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {}
});
5. 读取其他应用数据:
Context otherAppContext = context.createPackageContext(otherAppPackageName, Context.CONTEXT_IGNORE_SECURITY);
SharedPreferences sharedPreferences = otherAppContext.getSharedPreferences("config", Context.MODE_WORLD_READABLE);
然后还需要在配置文件中声明android:sharedUserId;
ContentProvider:
public static final Uri URI = Uri.parse("content://com.xxx.provider/peoples");
private static final int ITEM = 1, ITEM_ID = 2;
private static final UriMatcher mather = new UriMatcher(UriMatcher.NO_MATCH);
static{
mather.addURI(URI.getAuthority(), "peoples", ITEM);
mather.addURI(URI.getAuthority(), "peoples/#", ITEM_ID);
}
@Override
public String getType(Uri uri){
switch (mather.match(uri)){
case ITEM:
return "vnd.android.cursor.dir/peoplelist";
case ITEM_ID:
return "vnd.android.cursor.item/peopleitem";
default:
throw new IllegalArgumentException("uri Illegal" + uri);
}
}
ContentProvider权限控制:
1. 在Manifest中控制读写权限:android:readPermission(读)、android:writePermission(写)、android:permission(读写);
2. 控制URI路径权限:
<path-permission android:pathPrefix="/hello" android:readPermission="READ_HELLO_CONTENTPROVIDER" />
3. 通过Intent传递URI权限:
Intent intent = new Intent(this,ReadProvider.class);
intent.setClassName("com.example.propermissiongrant", "com.example.propermissiongrant.MainActivity");
intent.setData(Uri.parse("content://cn.wei.flowingflying.propermission.PrivProvider/world/1"));
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);
http://blog.csdn.net/flowingflying/article/details/17412609
SQLite:
1. 数据库结构变动:
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion < ver) {
db.execSQL("ALTER TABLE table ADD COLUMN column INTEGER");
}
}
2. 事务处理:
db.beginTransaction();
db.beginTransactionWithListener(new SQLiteTransactionListener(){
@Override
public void onBegin() {}
@Override
public void onCommit() {}
@Override
public void onRollback() {}
});
int res=db.update(table, values, whereClause, whereArgs);
if(res>-1){
db.setTransactionSuccessful(); //如果不设置,后面将会滚
}
db.endTransaction();
AsyncTask
1. 内部采用ThreadPoolExecutor+LinkedBlockingQueue+Handler实现;
2. execute方法只能在UI线程执行,且只能执行一次。
Handler+Looper+Message+MessageQueue
1. Handler的obtainMessage方法效率更高。
2. Message内部有个消息池,最大值50,采用链表存储。
3. MessageQueue内部init/destroy/poll/wake等均为native实现。
4. Thread默认是没有相关联的Looper的,可通过prepare()和loop()创建。
5. 一个Handler只关联一个Thread及其MessageQueue。
Serializable与Parcelable:
1. Serializable源于JDK,是为了方便文件操作、数据库、网络流对象序列化;
2. Parcelable源于Android SDK,是为了在组件中传递数据,序列化效率较高、内存开销小,但不适合数据持久化存储;
3. Serializable一般不需要自己写实现,不保存静态变量,可以使用Transient关键字对部分字段不进行序列化,也可以覆盖writeObject、readObject方法以实现序列化过程自定义;
4. Parcelable需要实现writeToParcel、describeContents函数以及静态的CREATOR变量,实际上就是将如何打包和解包的工作自己来定义,而序列化的这些操作完全由底层实现。
CursorAdapter:
1. 继承自BaseAdapter,实现了getView(),但是添加了newView()和bindView()抽象方法,其中前者只回调一次,后者会多次回调;
2. Cursor必须包含列_id;
HttpClient(Apache)和UrlConnection(JDK):
1. HttpClient支持所有method和header;
2. HttpClient支持持久连接和自动重定向;
3. HttpClient仅支持HTTP的协议;
http://www.cnblogs.com/devinzhang/archive/2012/01/17/2325092.html
进程间通信:
1. 通过Intent调用;
2. 通过ContentProvider提供通用接口;
3. 通过Broadcast通知;
4. 通过AIDL暴露接口;
线程间通信:
1. Message: 消息,包含ID和数据;
2. Handler: 负责发送和处理Message(比如更新UI);
3. Looper: 负责抽取Message,主线程有默认的Looper,子线程需要调用Looper.prepare和Looper.loop();
4. MessageQueue: 负责以队列方式(FIFO)管理Message;
5. Thread: 负责调度整个消息循环,几消息循环的执行场所;
6. 一个Thread对应一个Looper和一个MessageQueue,但可对应多个Handler;
7. 不确定当前线程时,尽量调用view.post(Runnable), 还可以调用Activity的runOnUiThread(Runnable);
Touch事件传递,多个容器组件事件冲突问题:
1. dispatchTouchEvent(MotionEvent ev) 分发
2. onInterceptTouchEvent(MotionEvent ev) 拦截
3. onTouchEvent(MotionEvent ev) 处理
http://www.cnblogs.com/sunzn/archive/2013/05/10/3064129.html
硬件加速:
1. 3.0以上开始支持;
2. 分application/activity/window/view四个级别;
3. 自定义View时有些方法不支持硬件加速或者开启后效果有差异;
http://blog.csdn.net/song_shi_chao/article/details/7453778 http://blog.csdn.net/gemmem/article/details/7715837
单元测试:
http://www.cnblogs.com/jackxlee/archive/2011/10/21/2220315.html
#Android新API#
Loader/AsyncTaskLoader/CursorLoader(3.0新特性):
1. 实现LoaderManager.LoaderCallBack中的回调方法即可;
2. AsyncTaskLoader继承AsyncTask实现异步任务;
3. 内部通过ContentObserver实现数据变动监听并通知回调;
4. 内部通过在activity的onStart()方法中判断loader状态,防止重复启动;
#Android实际问题#
捕获全局异常:
UncaughtExceptionHandler,重写uncaughtException(Thread thread, final Throwable ex);
监听短信收发:
1. BroadcastReceiver:简单,但只能监听收到短信;
2. ContentOberver:监听短信数据库,不过4.4开始出于安全考虑只有系统短信APP才有这个权限;
http://www.blogjava.net/anymobile/articles/328396.html
布局优化:
1.使用LinearLayout时结合layout:weight,尽量不要写死;单要结合RelativeLayout使用,因为前者用多了会大大增加布局层数,影响布局效率;
2.AdapterView里面使用ViewHolder重用布局,但如果不是每个ITEM布局都相同,最好使用多个布局,而不是通过setVisibility实现,否则会影响性能(虽然不用measure但是会占用内存,而且findViewById也会调用耗时)。
内存优化:
1. 不要在Activity内滥用static变量;
2. 不要在主线程做耗时操作(网络请求、文件和数据库操作等),也不要在子线程更新UI,可以使用Handler或者AsyncTask;
3. decode图片的时候,结合BitmapFactory.Options,先将inJustDecodeBounds设为true,decode之后通过outWidth和outHeight计算inSampleSize,然后将inJustDecodeBounds设为false,并再次decode。
4. Bitmap注意回收: if(bitmap!=null&&!bitmap.isRecycled()){bitmap.recycle();}
5. 执行跨Activity的后台异步任务时,context尽量传applicationContext,而不是activity,否则会因为被引用而造成Activity内的对象在任务执行完之前都不能被释放;
轮询的实现:
1. Service+Thread: 休眠后线程容易挂起或被用户杀掉;
2. Service+AlarmManager+Thread: 调用AlarmManager的setRepeating()开始轮询,调用cancel()方法停止轮询;
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/0401/1609.html
其他问题:
1. 多重嵌套Fragment如何有效的同步更新UI?
可在需要同步更新的所有Fragment的onResume()方法注册相同的BroadcastReceiver,然后在onPause()取消注册;当需要同步更新UI时发送广播,这样还能防止去更新已被回收的Fragment而引发的异常。
#软件工程与架构设计#
设计模式:
1. 创建范例(如何创建实例):工厂、单例、建造者等;
2. 结构范例(类和对象复合关系):适配器、代理、组合、桥接等;
3. 行为范例(对象之间如何通讯):观察者、命令、迭代器等;
架构设计:
1. 如何设计网络请求与响应框架;
2. 如何设计图片加载和缓存框架;
相关文章推荐
- 进程与线程的区别(面试高频问题)
- 解析程序员在公司去留的那些原因
- 职业建议
- 坚持就是胜利—兄弟连IT教育
- 每个程序员都应该知道的 15 个最佳 PHP 库
- 从.net转型,聊聊最近一些面试,薪资和想法
- 摆摊卖人贴--for BAT &FLAG
- 面试算法——2.双栈实现队列
- 前端面试题目搜集
- 前端面试题目搜集
- 黑马程序员-Java的数组(由基本类型构成)和算法
- 黑马程序员-Java的面向对象(对象、类和封装)
- 黑马程序员-Java的基础(语义、语法和函数)
- java 中遇见的面试题。
- 我同学的易宝支付面试经历
- 黑马程序员—Java基础—类的加载和反射
- 面试题-常用的排序方法大全
- 牛客堂刷题(常见面试题精讲)之随机概率
- 面试题-判断IP是法合法
- 黑马程序员——Java类变量和成员变量初始化过程