安卓面试题
Android interview questions
作者:韩梦飞沙
2017年7月3日,14:52:44
-
1. 要做一个尽可能流畅的ListView,你平时在工作中如何进行优化的?
①Item布局,层级越少越好,使用hierarchyview工具查看优化。
②复用convertView
③使用ViewHolder
④item中有图片时,异步加载
⑤快速滑动时,不加载图片
⑥item中有图片时,应对图片进行适当压缩
⑦实现数据的分页加载
-
2.
对于android 的安全问题,你知道多少
①错误导出组件
② 参数校验不严
③WebView引入各种安全问题,webview中的js注入
④不混淆、不防二次打包
⑤明文存储关键信息
⑦ 错误使用HTTPS
⑧山寨加密方法
⑨滥用权限、内存泄露、使用debug签名
-
3.
如何缩减APK包大小?
代码
保持良好的编程习惯,不要重复或者不用的代码,谨慎添加libs,移除使用不到的libs。
使用proguard混淆代码,它会对不用的代码做优化,并且混淆后也能够减少安装包的大小。
native code的部分,大多数情况下只需要支持armabi与x86的架构即可。如果非必须,可以考虑拿掉x86的部分。
资源
使用Lint工具查找没有使用到的资源。去除不使用的图片,String,XML等等。
assets目录下的资源请确保没有用不上的文件。
生成APK的时候,aapt工具本身会对png做优化,但是在此之前还可以使用其他工具如tinypng对图片进行进一步的压缩预处理。
jpeg还是png,根据需要做选择,在某些时候jpeg可以减少图片的体积。 对于9.png的图片,可拉伸区域尽量切小,另外可以通过使用9.png拉伸达到大图效果的时候尽量不要使用整张大图。
策略
有选择性的提供hdpi,xhdpi,xxhdpi的图片资源。建议优先提供xhdpi的图片,对于mdpi,ldpi与xxxhdpi根据需要提供有差异的部分即可。
尽可能的重用已有的图片资源。例如对称的图片,只需要提供一张,另外一张图片可以通过代码旋转的方式实现。
能用代码绘制实现的功能,尽量不要使用大量的图片。例如减少使用多张图片组成animate-list的AnimationDrawable,这种方式提供了多张图片很占空间。
-
4. Android与服务器交互的方式中的对称加密和非对称加密是什么?
对称加密,就是加密和解密数据都是使用同一个key,这方面的算法有DES。
非对称加密,加密和解密是使用不同的key。发送数据之前要先和服务端约定生成公钥和私钥,使用公钥加密的数据可以用私钥解密,反之。这方面的算法
5,设备横竖屏切换的时候,接下来会发生什么?
1、不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次
2、设置Activity的android:configChanges=”orientation”时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次
3、设置Activity的android:configChanges=”orientation|keyboardHidden”时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法
6.Android启动Service的两种方式是什么? 它们的适用情况是什么?
如果后台服务开始后基本可以独立运行的话,可以用startService。音乐播放器就可以这样用。它们会一直运行直到你调用 stopSelf或者stopService。你可以通过发送Intent或者接收Intent来与正在运行的后台服务通信,但大部分时间,你只是启动服务并让它独立运行。如果你需要与后台服务通过一个持续的连接来比较频繁地通信,建议使用bind()。比如你需要定位服务不停地把更新后的地理位置传给UI。Binder比Intent开发起来复杂一些,但如果真的需要,你也只能使用它。
startService:生命周期与调用者不同。启动后若调用者未调用stopService而直接退出,Service仍会运行
bindService:生命周期与调用者绑定,调用者一旦退出,Service就会调用unBind->onDestroy
7.谈谈你对Android中Context的理解?
Context:包含上下文信息(外部值) 的一个参数. Android 中的 Context 分三种,Application Context ,Activity Context ,Service Context.
它描述的是一个应用程序环境的信息,通过它我们可以获取应用程序的资源和类,也包括一些应用级别操作,例如:启动一个Activity,发送广播,接受Intent信息等
8.Service的onCreate回调在UI线程中吗?
Service生命周期的各个回调和其他的应用组件一样,是跑在主线程中,会影响到你的UI操作或者阻塞主线程中的其他事情
9.请介绍下AsyncTask的内部实现,适用的场景是?
AsyncTask内部也是Handler机制来完成的,只不过Android提供了执行框架来提供线程池来执行相应地任务,因为线程池的大小问题,所以AsyncTask只应该用来执行耗时时间较短的任务,比如HTTP请求,大规模的下载和数据库的更改不适用于AsyncTask,因为会导致线程池堵塞,没有线程来执行其他的任务,导致的情形是会发生AsyncTask根本执行不了的问题。
10.谈谈你对binder机制的理解?
binder是一种IPC机制,进程间通讯的一种工具.
Java层可以利用aidl工具来实现相应的接口.
11.Android中进程间通信有哪些实现方式?
Intent,Binder(AIDL),Messenger,BroadcastReceiver
12.介绍下实现一个自定义view的基本流程
1、自定义View的属性 编写attr.xml文件
2、在layout布局文件中引用,同时引用命名空间
3、在View的构造方法中获得我们自定义的属性 ,在自定义控件中进行读取(构造方法拿到attr.xml文件值)
4、重写onMesure
5、重写onDraw
13.Android中touch事件的传递机制是怎样的?
1.Touch事件传递的相关API有dispatchTouchEvent、onTouchEvent、onInterceptTouchEvent
2.Touch事件相关的类有View、ViewGroup、Activity
3.Touch事件会被封装成MotionEvent对象,该对象封装了手势按下、移动、松开等动作
4.Touch事件通常从Activity#dispatchTouchEvent发出,只要没有被消费,会一直往下传递,到最底层的View。
5.如果Touch事件传递到的每个View都不消费事件,那么Touch事件会反向向上传递,最终交由Activity#onTouchEvent处理.
6.onInterceptTouchEvent为ViewGroup特有,可以拦截事件.
7.Down事件到来时,如果一个View没有消费该事件,那么后续的MOVE/UP事件都不会再给它
14.Android多线程的实现方式有哪些?
Thread & AsyncTask
Thread 可以与Loop 和 Handler 共用建立消息处理队列
AsyncTask 可以作为线程池并行处理多任务
15.Android开发中何时使用多进程?使用多进程的好处是什么?
要想知道如何使用多进程,先要知道Android里的多进程概念。一般情况下,一个应用程序就是一个进程,这个进程名称就是应用程序包名。我们知道进程是系统分配资源和调度的基本单位,所以每个进程都有自己独立的资源和内存空间,别的进程是不能任意访问其他进程的内存和资源的。
那如何让自己的应用拥有多个进程?
很简单,我们的四大组件在AndroidManifest文件中注册的时候,有个属性是android:process,1.这里可以指定组件的所处的进程。默认就是应用的主进程。指定为别的进程之后,系统在启动这个组件的时候,就先创建(如果还没创建的话)这个进程,然后再创建该组件。你可以重载Application类的onCreate方法,打印出它的进程名称,就可以清楚的看见了。再设置android:process属性时候,有个地方需要注意:如果是android:process=”:deamon”,以:开头的名字,则表示这是一个应用程序的私有进程,否则它是一个全局进程。私有进程的进程名称是会在冒号前自动加上包名,而全局进程则不会。一般我们都是有私有进程,很少使用全局进程。他们的具体区别不知道有没有谁能补充一下。
2.使用多进程显而易见的好处就是分担主进程的内存压力。我们的应用越做越大,内存越来越多,将一些独立的组件放到不同的进程,它就不占用主进程的内存空间了。当然还有其他好处,有心人会发现Android后台进程里有很多应用是多个进程的,因为它们要常驻后台,特别是即时通讯或者社交应用,不过现在多进程已经被用烂了。典型用法是在启动一个不可见的轻量级私有进程,在后台收发消息,或者做一些耗时的事情,或者开机启动这个进程,然后做监听等。还有就是防止主进程被杀守护进程,守护进程和主进程之间相互监视,有一方被杀就重新启动它。应该还有还有其他好处,这里就不多说了。
3.坏处的话,多占用了系统的空间,大家都这么用的话系统内存很容易占满而导致卡顿。消耗用户的电量。应用程序架构会变复杂,应为要处理多进程之间的通信。这里又是另外一个问题了。
16.ANR是什么?怎样避免和解决ANR?
ANR:Application Not Responding,即应用无响应
ANR一般有三种类型:
1:KeyDispatchTimeout(5 seconds) –主要类型
按键或触摸事件在特定时间内无响应
2:BroadcastTimeout(10
seconds)
BroadcastReceiver在特定时间内无法处理完成
3:ServiceTimeout(20
seconds) –小概率类型
Service在特定的时间内无法处理完成
超时的原因一般有两种:
(1)当前的事件没有机会得到处理(UI线程正在处理前一个事件没有及时完成或者looper被某种原因阻塞住)
(2)当前的事件正在处理,但没有及时完成
UI线程尽量只做跟UI相关的工作,耗时的工作(数据库操作,I/O,连接网络或者其他可能阻碍UI线程的操作)放入单独的线程处理,尽量用Handler来处理UI thread和thread之间的交互。
UI线程主要包括如下:
Activity:onCreate(), onResume(), onDestroy(), onKeyDown(), onClick()
AsyncTask: onPreExecute(), onProgressUpdate(), onPostExecute(), onCancel()
Mainthread handler: handleMessage(), post(runnable r)
other
17.Android下解决滑动冲突的常见思路是什么?
相关的滑动组件 重写onInterceptTouchEvent,然后判断根据xy值,来决定是否要拦截当前操作
18.如何把一个应用设置为系统应用?
成为系统应用,首先要在 对应设备的 Android 源码 SDK 下编译,编译好之后:
此 Android 设备是 Debug 版本,并且已经 root,直接将此 apk 用 adb 工具 push 到 system/app 或 system/priv-app 下即可。
如果非 root 设备,需要编译后重新烧写设备镜像即可。
有些权限(如 WRITE_SECURE_SETTINGS ),是不开放给第三方应用的,只能在对应设备源码中编译然后作为系统 app 使用。
19、Android内存泄露研究
Android内存泄漏指的是进程中某些对象(垃圾对象)已经没有使用价值了,但是它们却可以直接或间接地引用到gc roots导致无法被GC回收。无用的对象占据着内存空间,使得实际可使用内存变小,形象地说法就是内存泄漏了。
场景
类的静态变量持有大数据对象
静态变量长期维持到大数据对象的引用,阻止垃圾回收。
非静态内部类的静态实例
非静态内部类会维持一个到外部类实例的引用,如果非静态内部类的实例是静态的,就会间接长期维持着外部类的引用,阻止被回收掉。
资源对象未关闭
资源性对象如Cursor、File、Socket,应该在使用后及时关闭。未在finally中关闭,会导致异常情况下资源对象未被释放的隐患。
注册对象未反注册
未反注册会导致观察者列表里维持着对象的引用,阻止垃圾回收。
Handler临时性内存泄露
Handler通过发送Message与主线程交互,Message发出之后是存储在MessageQueue中的,有些Message也不是马上就被处理的。在Message中存在一个 target,是Handler的一个引用,如果Message在Queue中存在的时间越长,就会导致Handler无法被回收。如果Handler是非静态的,则会导致Activity或者Service不会被回收。
由于AsyncTask内部也是Handler机制,同样存在内存泄漏的风险。
此种内存泄露,一般是临时性的。
20.内存泄露检测有什么好方法?
检测:
1、DDMS Heap发现内存泄露
dataObject totalSize的大小,是否稳定在一个范围内,如果操作程序,不断增加,说明内存泄露
2、使用Heap Tool进行内存快照前后对比
BlankActivity手动触发GC进行前后对比,对象是否被及时回收
定位:
1、MAT插件打开.hprof具体定位内存泄露:
查看histogram项,选中某一个对象,查看它的GC引用链,因为存在GC引用链的,说明无法回收
2、AndroidStudio的Allocation Tracker:
观测到期间的内存分配,哪些对象被创建,什么时候创建,从而准确定位
一、Android的四大组件
1.Android的四大组件
Activity的主要作用是展示一个界面并和用户交互,它扮演的是一种前台界面的角色。
Service是一种计算型组件,用于在后台执行一系列计算任务,但因为其本身还是运行在主线程中的,因此耗时的后台计算仍然需要在单独的线程中去完成。
BroadcastReceiver是一种消息型组件,用于在不同的组件乃至不同的应用之间传递消息。广播注册有两种方式,动态注册通过Context.registerReceiver()来实现,必须要应用启动才能注册;静态注册则在AndroidManifest文件中进行,应用安装时会被系统解析,不需要启动应用就可接收广播。
ContentProvider是一种共享型组件,用于向其他组件乃至其他应用共享数据。
2.Activity的四种启动模式:standard、singleTop、singleTask和singleInstance
1. standard 标准模式。每次启动一个Activity都会重新创建一个新的实例,不管这个实例是否已经存在;
2. singleTop 栈顶复用模式。如果新Activity已经位于任务栈的栈顶,那么此Activity不会被重新创建,会调用Activity的onNewIntent方法,onCreate和onStart并不会被调用。(常用于应用的搜索页面)
3. singleTask 栈内复用模式。只要该Activity在一个栈中有实例存在,就会把它上面的Activity都清除掉,让它置于栈顶,因为singleTask默认是具有clearTop的效果,最后onNewIntent会被回调。如果不存在就创建一个新的Activity,压入栈中。(常用于应用的首页MainAcitivity)
4. singleInstance:单实例模式,这是一种加强的singleTask模式,它除了具有singleTask模式的所有特性外,还加强一点,那就是具有此种模式的Activity只能单独地位于一个任务栈中。
任务栈是一种 “后进先出”的栈结构。
3.小知识点
1. 当前Activity的onPause方法执行结束后才会执行下一个Activity的onCreate方法,所以在onPause方法中不适合做耗时较长的工作,这会影响到页面之间的跳转效率;也就意味者,我们应当尽量在onStop方法中做操作,从而使得新Activity尽快的显示出来并切换到前台。
2. 新Activity是透明主题时,旧Activity不会走onStop;
3. 系统只有在Activity异常终止的时候才会调用onSavedInstanceState和onRestoreInstanceState来储存和恢复数据,其他情况不会触发这个过程。
4. 避免屏幕旋转时Activity重启生命周期,可以在AndroidManifest.xml中对应Activity标签声明时加上“android:configChanges=”orientation|screenSize””即可;
二、IPC机制
1、如何实现多进程?
给四大组件(Activity、Service、Receiver、ContentProvider)在AndroidManifest.xml中指定”android:process”属性可以在应用内实现多进程,如果进程名以”:”开头,说明该进程属于私有进程,其他应用的组件不可以和它跑在同一个进程中,如果经常名不以”:”开头,则属于全局进程,其它应用通过ShareUID方式可以和它跑在同一个进程中。
2.两个序列化类Parcelable和Serializable的区别:
Serializable是Java中的序列化接口,其使用起来简单但是开销很大,序列化和反序列化过程需要大量的I/O操作。而Parcelable是Android中的序列化方式,因此更适合于用在Android平台上,它的缺点就是使用起来稍微麻烦点,但是它的效率很高。Parceable主要用在内存序列化上,通过Parcelable将对象序列化到存储设备中或者将对象序列化后通过网络传输也都是可以的,但是这个过程会稍显复杂,此种情况建议使用Serializable。
三、View机制
1.View事件分发过程
事件的分发过程由三个很重要的方法来共同完成:dispatchTouchEvent、onInterceptTouchEvent和onTouchEvent:
1. dispatchTouchEvent:用来进行事件的分发,如果事件能够传递给当前View,那么此方法一定会被调用,返回结果受当前View的onTouchEvent和View的dispatchTouchEvent方法的影响,表示是否当消耗当前事件;
2. onInterceptTouchEvent:用来判断是否拦截某个事件,如果当前View拦截了某个事件,那么在同一个事件序列当中,此方法不会被再次调用,返回结果表示是否拦截当前事件;
3. onTouchEvent:在dispatchTouchEvent方法中调用,用来处理点击事件,返回结果表示是否消耗当前事件,如果不消耗,则在同一个事件序列中,当前View无法再次接收到事件。
一些结论:拦截的一定是事件序列;不消耗ACTION_DOWN,则事件序列都会由其父元素处理;只消耗ACTION_DOWN事件,该事件会消失,消失的事件最终会交给Activity来处理;requestDisallowInterceptTouchEvent方法可以在子元素中干预父元素的事件分发过程,除了ACTION_DOWN;
2.三种方式来实现View的滑动和对比
1. 通过View本身提供的scrollTo/scrollBy方法来实现滑动;操作简单,适合对View内容的滑动;
2. 通过动画给View施加平移效果来实现滑动;操作简单,适用于没有交互的View和实现复杂的动画效果;
3. 通过改变View的LayoutParams使得View重新布局从而实现滑动;改变布局参数操作稍微复杂,适用于有交互的View;
3.View的工作原理
View的绘制流程是从ViewRoot的performTraversals方法开始的,它经过measure、layout和draw三个过程才能最终将一个View绘制出来,其中measure用来测量View的宽和高,layout用来确定View在父容器中的放置位置,而draw则负责将View绘制在屏幕上。
4.setContentView()方法的由来
DecorView作为*View,一般情况下它内部包含一个竖直方向的LinearLayout,在这个LinearLayout里面有上下两个部分(具体情况和Android版本及主体有关),上面的是标题栏,下面的是内容栏。在Activity中通过setContentView所设置的布局文件其实就是被加到内容栏之中的,而内容栏的id是content,在代码中可以通过ViewGroup content = findViewById(R.android.id.content)来得到content对应的layout;
这就是为什么Acticity的Oncreate中的setContentView()方法得来的原因,而不是叫setView()。
四、Handler和MessageQueue、Looper的关系以及原理
1.MessageQueue的工作原理:主要方法为enqueueMessage和next
- enqueueMessag主要就是一个单链表的插入操作
- next方法是一个无限循环,如果消息队列中没有消息,next方法就阻塞,有新消息到来时,next方法会返回这条消息并将其从单链表中删除
2.Looper的工作原理:
- prepare方法,为当前没有Looper的线程创建Looper。
- prepareMainLooper和getMainLooper方法用于创建和获取ActivityThread的Looper。
- quit和quitSafely方法,前者立即退出,后者只是设定一个标记,当消息队列中的所有消息处理完毕后会才安全退出。子线程中创建的Looper建议不需要的时候都要手动终止。 d. loop方法,死循环,阻塞获取msg并丢给msg.target.dispatchMessage方法去处理,这里的target就是handler。
3.Handler的工作原理:
- 无论sendMessage还是post最终都是调用的sendMessageAtTime方法。
- 发送消息其实就是把一条消息通过MessageQueue的enqueueMessage方法加入消息队列,Looper收到消息就会调用handler的dispatchMessage方法
- 当我们直接Handler h = new Handler()时,本质调用的是Handler(Callback callback,
Boolean async)构造方法,这个方法里会调用Looper.myLooper()方法,这个方法其实就是返回的ThreadLocal里保存的当前线程的Looper,这也就解释了为什么我们在主线程中这样new Handler没有问题,而在子线程中这样会抛出异常,因为子线程中并没有Looper,所以必须先调用Looper.prepare,但是ActivityThread会在初始化的时候创建主线程也就是UI线程的Looper,所以我们在Activity中直接new Handler是没有问题的。
五、AsyncTask和线程池
1.AsyncTask的注意事项
AsyncTask的类必须在主线程加载,Android4.1及以上已经被系统自动完成了;
AsyncTask对象必须在主线程创建;
execute方法需要在UI线程调用;
一个AsyncTask对象只能调用一次;
Android1.6之前串行执行,Android1.6采用线程池并行处理任务,Android3.0开始,采用一个线程执行任务,但也可以通过executeOnExecutor方法来并行执行任务。
2.常见的4个线程池类型
- FixedThreadPool:线程数量固定的线程池,当所有线程都处于活动状态时,新任务会处于等待状态,只有核心线程并且不会回收(无超时机制),能快速的响应外界请求。
- CachedThreadPool:线程数量不定的线程池,最大线程数为Integer.MAX_VALUE(相当于任意大),当所有线程都处于活动状态时,会创建新线程来处理任务;线程池的空闲进程超时时长为60秒,超过就会被回收;任何任务都会被立即执行,适合执行大量的耗时较少的任务。
- ScheduledThreadPool:核心线程数量固定,非核心线程数量无限制,非核心线程闲置时会被立刻回收,用于执行定时任务和具有固定周期的重复任务。
- SingleThreadExecutor:只有一个核心线程,所有任务都在这个线程中串行执行,不需要处理线程同步问题
1、请你自我介绍一下你自己?
回答提示:一般人回答这个问题过于平常,只说姓名、年龄、爱好、工作经验,这些在简历上都有。其实,企业最希望知道的是求职者能否胜任工作,包括:最强的技能、最深入研究的知识领域、个性中最积极的部分、做过的最成功的事,主要的成就等,这些都可以和学习无关,也可以和学习有关,但要突出积极的个性和做事的能力,说得合情合理企业才会相信。
2、你对加班的看法?
回答提示:事实上做为一枚程序猿,加班熬夜是我们的标配,比较少的公司会有不加班的现象,因为你不知道什么时候你的程序就是那么不听话的崩溃了,这时你就得第一时间去处理好bug,紧急的修复并上线。
回答样本:如果是工作需要我会义不容辞加班,我现在单身,没有任何家庭负担,可以全身心的投入工作。但同时,我也会提高工作效率,减少不必要的加班。
3、你觉得你个性上最大的优点是什么?
回答提示:沉着冷静、条理清楚、立场坚定、顽强向上、乐于助人和关心他人、适应能力和幽默感、乐观和友爱。
4、说说你最大的缺点?
回答提示:这个问题企业问的概率很大,通常不希望听到直接回答的缺点是什么等,如果求职者说自己小心眼、爱忌妒人、非常懒、脾气大、工作效率低,企业肯定不会录用你。绝对不要自作聪明地回答“我最大的缺点是过于追求完美”,有的人以为这样回答会显得自己比较出色,但事实上,他已经岌岌可危了。业喜欢求职者从自己的优点说起,中间加一些小缺点,最后再把问题转回到优点上,突出优点的部分,企业喜欢聪明的求职者。
5、你对薪资的要求?
回答提示:如果你对薪酬的要求太低,那显然贬低自己的能力;如果你对薪酬的要求太高,那又会显得你分量过重,公司受用不起。一些雇主通常都事先对求聘的职位定下开支预算,因而他们第一次提出的价钱往往是他们所能给予的最高价钱,他们问你只不过想证实一下这笔钱是否足以引起你对该工作的兴趣。如果你自己必须说出具体数目,请不要说一个宽泛的范围,那样你将只能得到最低限度的数字。最好给出一个具体的数字,这样表明你已经对当今的人才市场作了调查,知道像自己这样学历的雇员有什么样的价值。
回答样本一:我对工资没有硬性要求,我相信贵公司在处理我的问题上会友善合理。我注重的是找对工作机会,所以只要条件公平,我则不会计较太多。
回答样本二:我受过系统的软件编程的训练,不需要进行大量的培训,而且我本人也对编程特别感兴趣。因此,我希望公司能根据我的情况和市场标准的水平,给我合理的薪水。
实战面试谈薪水
在面试时和公司谈薪资,有几点是要注意的:
•不要在一面、二面、三面等等过程中主动打探薪水、福利等,一般这会给对方留下比较差的印象,认为你只在乎钱。
•在确认公司准备聘用你之前不要谈钱,因为只有公司决定聘用你的时候,才是合适的时机。
•不要先开口谈钱,如果公司决定聘用你,那他们肯定会在做出决定后和你谈薪水。
•确定谁是要和你谈薪水的那个人,有时是 HR ,有时是副总、总监之类的,你无需询问,也会有机会知道的。如果是 HR 来和你谈薪水,她们多半是从技术线拿到了一个范围,然后会先压低了来和你谈,要做好心理准备,适当坚持一个比 HR 提出的更高的薪水。如果是技术线上的领导直接和你谈,我想你先要对面试的过程有个总结,了解这个人对你的印象,他是对你有强烈的兴趣,还是觉得你差强人意。如果是后者,你坚持高于对方给出的薪水,很可能没戏。无论哪种,你都要对这个职位表示出足够的兴趣来,同时也要表明你在意的不是薪水本身,而是薪水是否能与你的能力、你可以对公司带来的价值相匹配。
•被问及期望的薪水这类问题时,不要说具体的数字,如果一定要说,说一个范围。
•不要透露你现在的薪水,因为公司往往会根据你现在的薪水来给你定价。
•如果实在躲不过,一定要说现在的薪水,切忌撒圆不了的谎,虚报一大截子并不是明智的做法。 HR 们远比你想象的有能力,她们很可能和你之前所在公司的 HR 或某些人认识,能在做背景调查时问到你的薪水。
•如果对方拿你现在的薪水说事儿(碰巧你现在薪水较低),你应该表明你现在的薪水与能力严重错位,是不合理的,体现不了你的价值
不管你了解了多少谈判技巧,摆平自己的心态很重要。有一部分程序员觉得谈薪资谈来谈去怪不好意思怪伤感情的,其实不必,就跟你在商场买衣服一样,争取到合理的价位是人之常情,而且如果你不情不愿地进到了公司,时候发现被压低了工资,会产生非常消极的影响,不管对自己还是对公司,所以呢,你肯进入公司之前谈个明白,是对双方负责任的体现,因此你就不必担心这个过程会有多大的不良影响。
6、在三到五年的时间内,你的职业规划?
回答提示:这是每一个应聘者都不希望被问到的问题,但是几乎每个人都会被问到,比较多的答案是“管理者”。但是近几年来,许多公司都已经建立了专门的技术途径。这些工作地位往往被称作“顾问”、“参议技师”或“高级软件工程师”等等。当然,说出其他一些你感兴趣的职位也是可以的,比如产品销售部经理,生产部经理等一些与你的专业有相关背景的工作。要知道,考官总是喜欢有进取心的应聘者,此时如果说“不知道”,或许就会使你丧失一个好机会。最普通的回答应该是“我准备在技术领域有所作为”或“我希望能按照公司的管理思路发展”。
7、你还有什么问题要问吗?
回答提示:企业的这个问题看上去可有可无,其实很关键,企业不喜欢说“没问题”的人,因为其很注重员工的个性和创新能力。企业不喜欢求职者问个人福利之类的问题,如果有人这样问:贵公司对新入公司的员工有没有什么培训项目,我可以参加吗?或者说贵公司的晋升机制是什么样的?企业将很欢迎,因为体现出你对学习的热情和对公司的忠诚度以及你的上
8、谈谈你对跳槽的看法?
回答提示:①正常的“跳槽”能促进人才合理流动,应该支持。②频繁的跳槽对单位和个人双方都不利,应该反对。进心。
9、为什么要离职?
回答提示:回答这个问题时一定要小心,就算在前一个工作受到再大的委屈,对公司有多少的怨言,都千万不要表现出来,尤其要避免对公司本身主管的批评,避免面试官的负面情绪及印象。建议此时最好的回答方式是将问题归咎在自己身上,例如觉得工作没有学习发展的空间,自己想在面试工作的相关产业中多加学习,或是前一份工作与自己的生涯规划不合等等,回答的答案最好是积极正面的。
回答样本:我希望能获得一份更好的工作,如果机会来临,我会抓住。我觉得目前的工作,已经达到顶峰,即沒有升迁机会。
10、你对于我们公司了解多少?
回答提示:在去公司面试前上网查一下该公司主营业务。如回答:贵公司有意改变策略,加强与国外大厂的OEM合作,自有品牌的部分则透过海外经销商。
11、请说出你选择这份工作的动机?
回答提示:这是想知道面试者对这份工作的热忱及理解度,并筛选因一时兴起而来应试的人,如果是无经验者,可以强调“就算职种不同,也希望有机会发挥之前的经验”。
12、你最擅长的技术方向是什么?
回答提示:说和你要应聘的职位相关的课程,表现一下自己的热诚没有什么坏处。
13、喜欢这份工作的哪一点?
回答提示:相信其实大家心中一定都有答案了吧!每个人的价值观不同,自然评断的标准也会不同,但是,在回答面试官这个问题时可不能太直接就把自己心理的话说出来,尤其是薪资方面的问题,不过一些无伤大雅的回答是不错的考虑,如交通方便,工作性质及内容颇能符合自己的兴趣等等都是不错的答案,不过如果这时自己能仔细思考出这份工作的与众不同之处,相信在面试上会大大加分。
14、你为什么愿意到我们公司来工作?
回答提示:对于这个问题,你要格外小心,如果你已经对该单位作了研究,你可以回答一些详细的原因,像“公司本身的高技术开发环境很吸引我。”、“我同公司出生在同样的时代,我希望能够进入一家与我共同成长的公司。”、“你们公司一直都稳定发展,在近几年来在市场上很有竞争力。”、“我认为贵公司能够给我提供一个与众不同的发展道路。”这都显示出你已经做了一些调查,也说明你对自己的未来有了较为具体的远景规划。
15、在完成某项工作时,你认为领导要求的方式不是最好的,自己还有更好的方法,你应该怎么做?
回答提示:①.原则上我会尊重和服从领导的工作安排;同时私底下找机会以请教的口吻,婉转地表达自己的想法,看看领导是否能改变想法。②如果领导没有采纳我的建议,我也同样会按领导的要求认真地去完成这项工作。③.还有一种情况,假如领导要求的方式违背原则,我会坚决提出反对意见,如领导仍固执己见,我会毫不犹豫地再向上级领导反映。
16、如何安排自己的时间?会不会排斥加班?
回答提示:基本上,如果上班工作有效率,工作量合理的话,应该不太需要加班。可是我也知道有时候很难避免加班,加上现在工作都采用责任制,所以我会调配自己的时间,全力配合。
分析:虽然不会有人心甘情愿的加班,但依旧要表现出高配合度的诚意。
17、何时可以到职?
回答提示:大多数企业会关心就职时间,最好是回答“如果被录用的话,到职日可按公司规定上班”,但如果还未辞去上一个工作、上班时间又太近,似乎有些强人所难,因为交接至少要一个月的时间,应进一步说明原因,录取公司应该会通融的。
18、想过创业吗?
回答提示:这个问题可以显示你的冲劲,但如果你的回答是“有”的话,千万小心,下一个问题可能就是:那么为什么你不这样做呢?
19、怎样看待学历和能力?
回答提示:学历我想只要是大学专科的学历,就表明觉得我具备了根本的学习能力。剩下的,你是学士也好,还是博士也好,对于这一点的讨论,不是看你学了多少知识,而是看你在这个领域上发挥了什么,也就是所说的能力问题。一个人工作能力的高低直接决定其职场命运,而学历的高低只是进入一个企业的敲门砖,如果贵公司把学历卡在博士上,我就无法进入贵公司,当然这不一定只是我个人的损失,如果一个专科生都能完成的工作,您又何必非要招聘一位博士生呢?
常见的人事面试问题就整理到这里,这些都是面试中常问到的问题,只要看一遍就可以了,想想面试的时候该怎么措辞才恰当,虽然我们不是很擅长交际,但是我们的学习能力是很强的,做编程的,那智商,你懂得!
Android开发面试经——2.常见Android基础笔试题
1、Android四大组件是什么?作用以及应用场景?
Android 的四大组件分别是是Activity,Service,BroadcastReceiver和ContentProvider;
Activity:
从字面上理解,Activity是活动的意思。一个Activity通常展现为一个可视化的用户界面,是Android程序与用户交互的窗口,也是Android组件中最基本也是最复杂的一个组件。从视觉效果来看,一个Activity占据当前的窗口,响应所有窗口事件,具备有控件,菜单等界面元素。从内部逻辑来看,Activity需要为了保持各个界面状态,需要做很多持久化的事情,还需要妥善管理生命周期,和一些转跳逻辑。
Service
服务是运行在后台的一个组件,从某从意义上说,服务就像一个没有界面的Activity。它们在很多Android的概念方面比较接近,封装有一个完整的功能逻辑实现,接受上层指令,完成相关的事件,定义好需要接受的Intent提供同步和异步的接口。
BroadcastReceiver
广播接收者,不执行任何任务,广播是一种广泛运用的在应用程序之间传输信息的机制 。而 BroadcastReceiver 是对发送出来的广播进行过滤接收并响应的一类组件。Broadcast Receiver 不包含任何用户界面。然而它们可以启动一个Activity以响应接受到的信息,或者通过NotificationManager通知用户。可以通过多种方式使用户知道有新的通知产生:闪动背景灯、震动设备、发出声音等等。通常程序会在状态栏上放置一个持久的图标,用户可以打开这个图标并读取通知信息。在Android中还有一个很重要的概念就是Intent,如果说Intent是一个对动作和行为的抽象描述,负责组件之间程序之间进行消息传递。那么Broadcast Receiver组件就提供了一种把Intent作为一个消息广播出去,由所有对其感兴趣的程序对其作出反应的机制。
Content Provider
即内容提供者,作为应用程序之间唯一的共享数据的途径,Content Provider 主要的功能就是存储并检索数据以及向其他应用程序提供访问数据。
对应用而言,也可以将底层数据封装成ContentProvider,这样可以有效的屏蔽底层操作的细节,并且使程序保持良好的扩展性和开放性。Android提供了一些主要数据类型的Contentprovider,比如音频、视频、图片和私人通讯录等。可在android.provider包下面找到一些android提供的Contentprovider。可以获得这些Contentprovider,查询它们包含的数据,当然前提是已获得适当的读取权限。如果我们想公开自己应用程序的数据,可以创建自己的 Content provider 的接口。
2、android中的动画有哪几类,它们的特点和区别是什么?
两种,一种是Tween动画、还有一种是Frame动画。Tween动画,这种实现方式可以使视图组件移动、放大、缩小以及产生透明度的变化;另一种Frame动画,传统的动画方法,通过顺序的播放排列好的图片来实现,类似电影。
3、后台的activity被系统回收怎么办?如何在被系统回收之前保存当前状态?
当一个Activity被pause或者stop的时候,这个Activity的对象实际上还是保存在内存中,因此这个Activity中的信息(成员和状态信息)还可以重新获取到.
如果系统为了整理内存而销毁了Activity对象时,系统没法简单的原封不动地恢复先前的Activity对象及其状态信息.
Activity中提供了一个方法:onSavedInstanceState(Bundle obj).当系统销毁一个Activity时,会将Activity的状态信息已键值对形式存放在bundle对象中.
第一次启动Activity时,这个bundle对象是空的,null.如果Activity被系统销毁了,然后用户要回退回去看的话,系统会调用这个Activity的onCreate方法,并把bundle对象传递过去.
4. 请描述一下Activity 生命周期。
5. 如何将一个Activity设置成窗口的样式。
在AndroidManifest.xml 中定义Activity的地方一句话android:theme=”@android:style/Theme.Dialog”或android:theme=”@android:style/Theme.Translucent”就变成半透明的
6.注册广播有几种方式,有何优缺点?
有两种,一种是代码动态注册:
//生成广播处理
smsBroadCastReceiver = new SmsBroadCastReceiver();
//实例化过滤器并设置要过滤的广播
IntentFilter
intentFilter = new IntentFilter(“android.provider.Telephony.SMS_RECEIVED”);
//注册广播
BroadCastReceiverActivity.this.registerReceiver(smsBroadCastReceiver,
intentFilter);
一种是在AndroidManifest.xml中配置广播
<!--广播注册-->
<receiver android:name=".SmsBroadCastReceiver">
<intent-filter android:priority="20">
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
· 1
· 2
· 3
· 4
· 5
· 6
两种注册类型的区别是:
1)第一种不是常驻型广播,也就是说广播跟随程序的生命周期
2)第二种是常驻型,也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行。
注册的方法有两种,一种是静态注册,一种是动态注册。
动态注册优点: 在 Android 的广播机制中, 动态注册的优先级是要高于静态注册优先级的 , 因此在必要的情况下,我们是需要动态注册广播接收器的。
静态注册优点:动态注册广播接收器还有一个特点,就是当用来注册的 Activity 关掉后 ,广播也就失效了。同时反映了静态注册的一个优势,就是无需担忧广播接收器是否被关闭 , 只要设备是开启状态,广播接收器就是打开着的。
7.IntentService有何优点?
普通的service ,默认运行在ui main 主线程
这是带有异步处理的service类,
异步处理的方法 OnHandleIntent()
OnHandleIntent() 处理耗时的操作
Android的进程处理器现在会尽可能的不kill掉你
8.横竖屏切换时候activity的生命周期?
1、不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次
2、设置Activity的android:configChanges=”orientation”时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次
3、设置Activity的android:configChanges=”orientation|keyboardHidden”时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法
9、如何将SQLite数据库(dictionary.db文件)与apk文件一起发布? 如何将打开res raw目录中的数据库文件?
解答:以将dictionary.db文件复制到res raw目录中 ,在Android中不能直接打开res
raw目录中的数据库文件,而需要在程序第一次启动时将该文件复制到手机内存或SD卡的某个目录中,然后再打开该数据库文件。复制的基本方法是使用getResources().openRawResource方法获得res raw目录中资源的 InputStream对象,然后将该InputStream对象中的数据写入其他的目录中相应文件中。在Android
SDK中可以使用SQLiteDatabase.openOrCreateDatabase方法来打开任意目录中的SQLite
;
10.AndroidManifest.xml文件中主要包含哪些信息
说明应用程序的Java 包,该包名是应用程序的唯一标识;
描述应用程序的组件:该应用程序由哪些activity,service,broadcast receiver和content provider组成;
声明应用程序所必须具备的权限,用以访问受保护的部分API,以及与其他应用程序的交互;
声明应用程序所需要的Android API的最低版本级别,比如1.0,1.1,1.5;
manifest:根节点,描述了 package 中所有的内容。
uses-permission:请求你的 package 正常运作所需赋予的安全许可。
permission: 声明了安全许可来限制哪些程序能你
package 中的组件和功能。
instrumentation:声明了用来测试此 package 或其他 package 指令组件的代码。
application:包含 package 中 application 级别组件声明的根节点。
activity:Activity 是用来与用户交互的主要工具。
receiver:IntentReceiver 能使的 application 获得数据的改变或者发生的操作,即使它当 前不在运行。
service:Service 是能在后台运行任意时间的组件。
provider:ContentProvider 是用来管理持久化数据并发布给其他应用程序使用的组件。
11.Android数据储存方式
一.SharedPreferences方式:它是 Android提供的用来存储一些简单配置信息的一种机制,采用了
XML 格式将数据存储到设备中。只能在同一个包内使用,不能在不同的包之间使用。
二.文件存储方式 /data/data/包名/files 内存里面
/ context.openFileInput(name) 默认是私有的访问权限
三.SQLite数据库方式:SQLite 是 Android 所带的一个标准的数据库, 它支持 SQL语句,它是一个轻量级的嵌入式数据库。
四.内容提供器(Content provider)方式:主要用于应用程序之间进行数据交换,从而能够让其他的应用保存或读取此 Content Provider 的各种数据类型。
五. 网络存储方式: 通过网络上提供给我们的存储空间来上传(存储)和下载(获取)我们存储 在网络空间中的数据信息。
12.Android中常见五种布局介绍
FrameLayout(帧布局): 从屏幕的左上角开始布局,叠加显示, 实际应用 播放器的暂停按钮.
LinearLayout (线性布局):可分为垂直布局,水平布局;
AbsoluteLayout(绝对布局):用X,Y坐标来指定元素的位置;
RelativeLayout(相对布局): 相对布局可以理解为某一个元素为参照物,来定位的布局方式。
TableLayout(表格布局):表格布局类似Html里面的Table。每一个TableLayout里面有表格行TableRow,TableRow里面可以具体定义每一个元素,设定他的对齐方式 android:gravity=”” 。
每一个布局都有自己适合的方式,另外,这五个布局元素可以相互嵌套应用,做出美观的界面。
13.Activity的四种启动模式?,activity与task的启动方式有哪些,她们的含义具体说明
standard: 标准模式,一调用 startActivity()方法就会产生一个新的实例。
singleTop: 如果已经有一个实例位于 Activity 栈的顶部时, 就不产生新的实例, 而只是调用Activity 中的 newInstance()方法。如果不位于栈顶,会产生一个新的实例。
singleTask: 会在一个新的 task 中产生这个实例,以后每次调用都会使用这个,不会去产生 新的实例了。
singleInstance: 这个跟 singleTask 基本上是一样, 只有一个区别: 在这个模式下的
Activity实例所处的 task 中,只能有这个 activity实例,不能有其他的实例。
14.Android 中的长度单位详解
如果设置表示长度 、 高度等属性时可以使用
dp 或 sp。但如果设置字体,需要使用 sp。dp 是与密度无关,sp 除了与密度无关外,还与 scale 无关。如果屏幕密度为160,这时 dp 和 sp 和 px 是一样
的。1dp=1sp=1px,
也就是说,如果使用 dp 和 sp,系统会根据屏幕密度的变化自动进行转换
px :表示屏幕实际的象素
in:表示英寸,是屏幕的物理尺寸。每英寸等于2.54 厘米。
15.android 析中有哪几种解析 l xml 的类, , , , 官方推荐哪种?以及它们的原理和区别
DOM 解析
优点:
1.XML 树在内存中完整存储,因此可以直接修改其数据和结构.
2.可以通过该解析器随时访问 XML 树中的任何一个节点.
3.DOM 解析器的 API 在使用上也相对比较简单.
缺点:如果 XML 文档体积比较大时,将文档读入内存是非常消耗系统资源的
Ø SAX 解析
优点:
SAX 对内存的要求比较低,因为它让开发人员自己来决定所要处理的标签.特别是当开发人 员只需要处理文档中所包含的部分数据时,SAX
这种扩展能力得到了更好的体现.
缺点:
用 SAX 方式进行 XML 解析时,需要顺序执行,所以很难访问到同一文档中的不同数据.此外,在基于该方式的解析编码过程也相对复杂
Ø Xmlpull 解析(官方推荐使用)
android SDK 提供了 xmlpull api,xmlpull 和 sax 类似,是基于流(stream)操作文件,然后根据节点事件回调开发者编写的处理程序.因为是基于流的处理,因此 xmlpull 和 sax 都比较节
约内存资源,不会象 dom 那样要把所有节点以对橡树的形式展现在内存中.xmlpull 比 sax 更 简明,而且不需要扫描完整个流.
16.ListView 的优化方案
(1),如果自定义适配器,那么在 getView 方法中要考虑方法传进来的参数 contentView 是否 为 null,如果为 null 就创建 contentView 并返回,如果不为
null 则直接使用。在这个方法中,尽可能少创建 view。
(2),给 contentView 设置 tag(setTag()),传入一个 viewHolder 对象,用于缓存要显示的数 据,可以达到图像数据异步加载的效果
(3),如果 listview 需要显示的 item 很多,就要考虑分页加载。比如一共要显示100条或者更多的时候,我们可以考虑先加载20条,等用户拉到列表底部的时候,再去加载接下来的20 条。
(4) 快速滑动时不加载图片
(5) 如果自定义的item中有图片,需要处理图片(减少图片所占内存)
1.对图片进行边界压缩 2.用option类来保存图片大小 3.避免图片的实时缩放,最好预先缩放到视图大小
(6)尽量避免在listview适配器中使用线程,因为线程是产生内存泄露的主要原因在于线程的生命周期不可控。
17.Android中intent的作用
在一个 Android 应用中,主要是由一些组件组成(Activity,Service,ContentProvider,etc.) 在这些组件之间的通讯中,由
Intent 协助完成。
Intent 负责对应用中一次操作的动作、动作涉及数据、附加数据
进行描述,Android 则根据此 Intent 的描述,负责找到对应的组件,将 Intent 传递给调用的组件,并完成组件的调用。Intent 在这里起着实现调用者与被调用者之间的解耦作用。
有两种方式,一种是显示匹配,一种是隐示匹配;
显示:明确的指定要跳转的Activity,或者Service等;
隐示:隐式匹配,首先要匹配 Intent 的几项值:Action,Category, Data/Type,Component如果填写了 Componet 就是这就形成了显示匹配。
1.如果你填写了 Action, 如果有一个程序的
Manifest.xml 中的某一个 Activity 的 IntentFilter 段中定义了包含了相同的 Action 那么这个 Intent 就与这个目标 Action 匹配, 如果这个 Filter段中没有定义
Type,Category,那么这个 Activity 就匹配了。但是如果手机中有两个以上的程序匹配,那么就会弹出一个对话可框来提示说明。
2,data/type,你可以用 Uri 来做为 data,比如 Uri uri = Uri.parse(http://www.google.com );
Intent i = new Intent(Intent.ACTION_VIEW,uri);手机的 Intent 分发过程中,会根据 http://www.google.com 的 scheme 判断出数据类型 type手机的 Brower 则能匹配它,在
Brower 的 Manifest.xml 中的 IntenFilter中首先有ACTION_VIEW Action,也能处理 http:的 type;
3,至于分类 Category,一般不要去在 Intent 中设置它,如果你写 Intent 的接收者,就在Manifest.xml 的 Activity 的 IntentFilter 中包含 android.category.DEFAULT,这样所有不设置Category(Intent.addCategory(String
c);)的 Intent 都会与这个 Category 匹配。
4,extras(附加信息) ,是其它所有附加信息的集合。使用
extras 可以为组件提供扩展信息 ,比如,如果要执行“发送电子邮件”这个动作,可以将电子邮件的标题、正文等保存在
extras里,传给电子邮件发送组件。
18.如何退出 Activity ?如何安全退出?
对于单一 Activity 的应用来说,退出很简单,直接 finish()即可。
当然,也可以用 killProcess()和 System.exit()这样的方法。
为了编程方便,最好定义一个 Activity 基类,处理这些共通问题。
1、记录打开的 Activity:
每打开一个 Activity,就记录下来。在需要退出时,关闭每一个 Activity 即可。
2、发送特定广播:
在需要结束应用时,发送一个特定的广播,每个 Activity 收到广播后,关闭即可。
1、Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型?
方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现,重载Overloading是一个类中多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被”屏蔽”了。如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载(Overloading)。Overloaded的方法是可以改变返回值的类型。
2、String和StringBuffer,StringBuilder的区别
String 字符串常量
StringBuffer 字符串变量(线程安全)
StringBuilder 字符串变量(非线程安全)
String的长度是不可变的,StringBuffer,StringBuilder的长度是可变的。如果你对字符串中的内容经常进行操作,特别是内容要修改时,那么使用StringBuffer,如果最后需要String,那么使用StringBuffer的toString()方法。
3、说出ArrayList,Vector, LinkedList的存储性能和特性
ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized方法(线程安全),通常性能上较ArrayList差,而LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。
4.字符串“abcde”通过写一个函数不让调用第三方的字符串,实现一个字符串倒序,比如字符串“abcde”变成“edcba”
String src = “abcde”;
String dst = new StringBuffer(src).reverse().toString();
5、Collection 和 Collections的区别。
Collection是集合类的上级接口,继承与他的接口主要有Set 和List.
Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作
6、final, finally, finalize的区别。
final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。
finally是异常处理语句结构的一部分,表示总是执行。
finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。
7、sleep() 和 wait() 有什么区别?
1.这两个方法来自不同的类分别是,sleep来自Thread类,和wait来自Object类。
2.最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。sleep不出让系统资源;wait是进入线程等待池等待,出让系统资源,其他线程可以占用CPU。一般wait不会加时间限制,因为如果wait线程的运行资源不够,再出来也没用,要等待其他线程调用notify/notifyAll唤醒等待池中的所有线程,才会进入就绪队列等待OS分配系统资源。sleep(milliseconds)可以用时间指定使它自动唤醒过来,如果时间不到只能调用interrupt()强行打断。
3.wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用
4. Sleep需要捕获异常,而wait不需要
8、同步和异步有何异同,在什么情况下分别使用他们?举例说明。
如果数据将在线程间共享。例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取。
当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效率。
9,抽象类与接口的区别(abstract与interface的区别)
abstract可以修饰抽象方法,而一个类只要有一个抽象方法,就必须用abstract定义该类,即抽象类。
用interface修饰的类,里面的方法都是抽象方法,因此在定义接口的时候,可以直接不加那些修饰,系统会默认的添上去。接口里面的字段都是公有常量,即public static final修饰的字段。
10、线程中wait,join,sleep,yield, notify,notifyall,synchronized,区别及联系
1).sleep()方法
在指定时间内让当前正在执行的线程暂停执行,但不会释放“锁标志”。不推荐使用。sleep()使当前线程进入阻塞状态,在指定时间内不会执行。
2).wait()方法
在其他线程调用对象的notify或notifyAll方法前,导致当前线程等待。线程会释放掉它所占有的“锁标志”,从而使别的线程有机会抢占该锁。
唤醒当前对象锁的等待线程使用notify或notifyAll方法,waite() 和notify()必须在synchronized函数或synchronized block中进行调用。
yield方法暂停当前正在执行的线程对象。yield()只是使当前线程重新回到可执行状态,所以执行
3)yield()的线程有可能在进入到可执行状态后马上又被执行。yield()只能使同优先级或更高优先级的线程有执行的机会。
4).join方法
等待该线程终止。等待调用join方法的线程结束,再继续执行。如:t.join();//主要用于等待t线程运行结束,若无此句,main则会执行完毕,导致结果不可预测。
11、接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承实体类(concrete class)?
接口可以继承接口。抽象类可以实现(implements)接口,抽象类是否可继承实体类,但前提是实体类必须有明确的构造函数。
12、abstract的method是否可同时是static,是否可同时是native,是否可同时是synchronized?
13、是否可以继承String类?
String类是final类故不可以继承。
14、Javaswitch支持的数据类型:
java支持的数据类型有五种
他们分别是:
byte、char、short、int、枚举
以上是JDK1.6以前的版本。JDK1.7时,又增加了String,所以相对于JDK1.7而言就是六种了
15、什么是单例模式,请写出一个来:
Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在。
一般Singleton模式通常有几种种形式:
第一种形式: 定义一个类,它的构造函数为private的,它有一个static的private的该类变量,在类初始化时实例话,通过一个public的getInstance方法获取对它的引用,继而调用其中的方法。
publicclass
Singleton {
privateSingleton
(){}
//注意这是private 只供内部调用
private
static
Singleton instance =
newSingleton();
//这里提供了一个供外部访问本class的静态方法,可以直接访问
public
static
Singleton
getInstance() {
return
instance;
}
}
第二种形式
:
publicclass
Singleton {
private
static
Singleton instance =
null;
public
static
synchronized Singleton
getInstance() {
//这个方法比上面有所改进,不用每次都进行生成对象,只是第一次
//使用时生成实例,提高了效率!
if
(instance==
null)
instance
=
newSingleton();
return instance; }
}
其他形式:
定义一个类,它的构造函数为private的,所有方法为static的。
一般认为第一种形式要更加安全些
16、Java常用的设计模式?说明工厂模式。
Java中的23种设计模式:
Factory(工厂模式), Builder(建造模式), Factory Method(工厂方法模式),
Prototype(原始模型模式),Singleton(单例模式), Facade(门面模式),
Adapter(适配器模式), Bridge(桥梁模式), Composite(合成模式),
Decorator(装饰模式), Flyweight(享元模式), Proxy(代理模式),
Command(命令模式), Interpreter(解释器模式), Visitor(访问者模式),
Iterator(迭代子模式), Mediator(调停者模式), Memento(备忘录模式),
Observer(观察者模式), State(状态模式), Strategy(策略模式),
Template Method(模板方法模式), Chain Of Responsibleity(责任链模式)
工厂模式:工厂模式是一种经常被使用到的模式,根据工厂模式实现的类可以根据提供的数据生成一组类中某一个类的实例,
通常这一组类有一个公共的抽象父类并且实现了相同的方法,但是这些方法针对不同的数据进行了不同的操作。
首先需要定义一个基类,该类的子类通过不同的方法实现了基类中的方法。然后需要定义一个工厂类,工厂类可以根据条件
生成不同的子类实例。当得到子类的实例后,开发人员可以调用基类中的方法而不必考虑到底返回的是哪一个子类的实例。
Android开发面试经——4.常见Android进阶笔试题(更新中...)
1.什么是ANR,如何避免?
ANR:Application Not Responding。
在 Android 中,活动管理器和窗口管理器这两个系统服务负责监视应用程序的响应。当出现下列情况时,Android 就会显示 ANR 对话框了:
①.用户对应用程序的操作(如输入事件,按键、触摸屏事件)在5秒内无响应
②. 广播接受器(BroadcastReceiver)在10秒内仍未执行完毕
Android 应用程序完全运行在一个独立的线程中(例如 main)。这就意味着,任何在主 线程中运行的,需要消耗大量时间的操作都会引发
ANR。因为此时,你的应用程序已经没有机会去响应输入事件和意向广播(Intentbroadcast)。
避免方法:Activity 应该在它的关键生命周期方法(如 onCreate()和 onResume())里尽可能少的去做创建操作,
潜在的耗时操作。例如网络或数据库操作,或者高耗时的计算如改变位图尺寸,应该在子线程里(或者异步方式)来完成。
主线程应该为子线程提供一个 Handler,以便完成时能够提交给主线程。
2.Handler机制原理?
andriod 提供了 Handler 和 Looper 来满足线程间的通信。Handler 先进先出原则。
Looper 类用来管理特定线程内对象之间的消息交换 (MessageExchange)。
1)Looper: 一个线程可以产生一个 Looper 对象,由它来管理此线程里的 MessageQueue(消息队列)。
2)Handler: 你可以构造 Handler 对象来与 Looper 沟通,以便 push 新消息到 MessageQueue 里;或者接收 Looper 从 MessageQueue 取出)所送来的消息。
3) Message Queue(消息队列 ): 用来存放线程放入的消息。
4)线程: UI thread 通常就是 main thread, 而 Android 启动程序时会替它建立一个
MessageQueue。
3.请解释下在单线程模型中Message、Handler、Message Queue、Looper之间的关系。
简单的说,Handler获取当前线程中的 looper对象,looper 用来从存放 Message 的 MessageQueue中取出 Message,再有 Handler 进行 Message 的分发和处理.
Message Queue(消息队列): 用来存放通过
Handler 发布的消息, 通常附属于某一个创建它的线程,可以通过
Looper.myQueue()得到当前线程的消息队列
Handler:可以发布或者处理一个消息或者操作一个 Runnable,通过 Handler发布消息, 消息将只会发送到与它关联的消息队列,然也只能处理该消息队列中的消息
Looper:是 Handler 和消息队列之间通讯桥梁,程序组件首先通过 Handler 把消息传递给 Looper,Looper 把消息放入队列。Looper 也把消息队列里的消息广播给所有的
Handler:Handler 接受到消息后调用 handleMessage进行处理
Message:消息的类型,在 Handler 类中的 handleMessage 方法中得到单个的消息进行处理
在单线程模型下, 为了线程通信问题,
Android 设计了一个 Message Queue(消息队列), 线程间可以通过该
Message Queue 并结合 Handler 和 Looper 组件进行信息交换。
下面将对它 们进行分别介绍:
1. Message
Message 消息,理解为线程间交流的信息,处理数据后台线程需要更新 UI ,则发送Message 内含一些数据给 UI 线程。
2. Handler
Handler处理者,是 Message 的主要处理者,负责 Message 的发送,Message 内容的执行处理。后台线程就是通过传进来的 Handler对象引用来 sendMessage(Message)。
而使用 Handler,需要 implement 该类的 handleMessage(Message)方法,它是处理这些
Message 的操作内容,例如 Update UI 。通常需要子类化 Handler 来实现 handleMessage方法。
3. Message Queue
Message Queue 消息队列,用来存放通过 Handler 发布的消息,按照先进先出执行。每个 message queue 都会有一个对应的 Handler。Handler 会向 messagequeue 通过两种方法发送消息:sendMessage 或 post。这两种消息都会插在 message queue 队尾并
按先进先出执行。但通过这两种方法发送的消息执行的方式略有不同:通过 sendMessage发送的是一个 message 对象,会被 Handler 的 handleMessage()函数处理;而通过 post 方法发送的是一个 runnable 对象,则会自己执行。
4. Looper
Looper 是每条线程里的 Message Queue 的管家。Android 没有 Global 的MessageQueue,而 Android 会自动替主线程(UI 线程)建立 Message Queue,但在子线程里并没有建立 Message Queue。 所以调用
Looper.getMainLooper()得到的主线程的 Looper 不为 NULL,但调用 Looper.myLooper()得到当前线程的 Looper 就有可能为 NULL。
4.Android 中线程与线程,进程与进程之间如何通信
1、一个 Android 程序开始运行时,会单独启动一个 Process。
默认情况下,所有这个程序中的 Activity 或者 Service 都会跑在这个 Process。
默认情况下,一个 Android 程序也只有一个 Process,但一个 Process 下却可以有许多个 Thread。
2、一个 Android 程序开始运行时,就有一个主线程 MainThread 被创建。该线程主要负责 UI 界面的显示、更新和控件交互,所以又叫 UI Thread。
一个 Android 程序创建之初,一个 Process 呈现的是单线程模型–即 Main Thread,
所有的任务都在一个线程中运行。所以,Main Thread 所调用的每一个函数,其耗时应该
越短越好。而对于比较费时的工作,应该设法交给子线程去做,以避免阻塞主线程(主线程被阻塞,会导致程序假死 现象) 。
3、Android 单线程模型:Android UI 操作并不是线程安全的并且这些操作必须在 UI 线程中执行。如果在子线程中直接修改 UI,会导致异常。
4.Android 的 的 IPC ( 进程间通信 ) 机制
IPC 是内部进程通信的简称, 是共享 ” 命名管道 ” 的资源。Android 中的 IPC机制是为了让
Activity 和 Service之间可以随时的进行交互,故在 Android 中该机制,只适用于 Activity 和 Service之间的通信,类似于远程方法调用,类似于 C/S 模式的访问。通过定义 AIDL 接口文件来定义 IPC 接口。Servier 端实现 IPC接口,Client 端调用 IPC接口本地代理。
5.Android应用程序框架
6.View, surfaceView, GLSurfaceView的区别
View 是最基础的,必须在 UI 主线程内更新画面,速度较慢。
SurfaceView 是 view 的子类,类似使用双缓机制,在新的线程中更新画面所以刷新界面速度比 view 快 GLSurfaceView 是 SurfaceView 的子类,opengl 专用的。
区别:SurfaceView是从View基类中派生出来的显示类,直接子类有GLSurfaceView和VideoView,可以看出GL和视频播放以及Camera摄像头一般均使用SurfaceView
SurfaceView和View最本质的区别在于,surfaceView是在一个新起的单独线程中可以重新绘制画面而View必须在UI的主线程中更新画面。
那么在UI的主线程中更新画面 可能会引发问题,比如你更新画面的时间过长,那么你的主UI线程会被你正在画的函数阻塞。那么将无法响应按键,触屏等消息。
当使用surfaceView 由于是在新的线程中更新画面所以不会阻塞你的UI主线程。但这也带来了另外一个问题,就是事件同步。比如你触屏了一下,你需要surfaceView中thread处理,一般就需要有一个event queue的设计来保存touch event,这会稍稍复杂一点,因为涉及到线程同步。
7. AIDL的全称是什么?如何工作?
AIDL 全称 Android Interface Definition Language(Android 接口描述语言)是一种接口描述语言 ;
编译器可以通过 aidl文件生成一段代码, 通过预先定义的接口达到两个进程内
部通信进程跨界对象访问的目的.AIDL 的 IPC 的机制和 COM 或 CORBA 类似 , 是基于接口的, 但它是轻量级的。 它使用代理类在客户端和实现层间传递值 .
如果要使用 AIDL, 需要完成2件事情 :
1. 引入AIDL的相关类 .;
2. 调用 aidl产生的 class.理论上 , 参数可以传递基本数据类型和String, 还有就是Bundle的派生类
当A进程要去调用B进程中的service时,并实现通信,我们通常都是通过AIDL来操作的 。
A工程:
首先我们在net.blogjava.mobile.aidlservice包中创建一个RemoteService.aidl文件,在里面我们自定义一个接口,含有方法get。ADT插件会在gen目录下自动生成一个RemoteService.java文件,该类中含有一个名为RemoteService.stub的内部类,该内部类中含有aidl文件接口的get方法。
说明一:aidl文件的位置不固定,可以任意
然后定义自己的MyService类,在MyService类中自定义一个内部类去继承RemoteService.stub这个内部类,实现get方法。在onBind方法中返回这个内部类的对象,系统会自动将这个对象封装成IBinder对象,传递给他的调用者。
其次需要在AndroidManifest.xml文件中配置MyService类,代码如下:
<!-- 注册服务 -->
<service android:name=".MyService">
<intent-filter>
<!-- 指定调用AIDL服务的ID -->
<action android:name="net.blogjava.mobile.aidlservice.RemoteService" />
</intent-filter>
</service>
为什么要指定调用AIDL服务的ID,就是要告诉外界MyService这个类能够被别的进程访问,只要别的进程知道这个ID,正是有了这个ID,B工程才能找到A工程实现通信。
说明:AIDL并不需要权限
B工程:
首先我们要将A工程中生成的RemoteService.java文件拷贝到B工程中,在bindService方法中绑定aidl服务
绑定AIDL服务就是将RemoteService的ID作为intent的action参数。
说明:如果我们单独将RemoteService.aidl文件放在一个包里,那个在我们将gen目录下的该包拷贝到B工程中。如果我们将RemoteService.aidl文件和我们的其他类存放在一起,那么我们在B工程中就要建立相应的包,以保证RmoteService.java文件的报名正确,我们不能修改RemoteService.java文件
bindService(new Inten(“net.blogjava.mobile.aidlservice.RemoteService”),
serviceConnection, Context.BIND_AUTO_CREATE);
ServiceConnection的onServiceConnected(ComponentName name, IBinder service)方法中的service参数就是A工程中MyService类中继承了RemoteService.stub类的内部类的对象。
8.关于AndroidOOM,以及如何避免?
Android的虚拟机是基于寄存器的Dalvik,它的最大堆大小一般是16M,有的机器为24M。因此我们所能利用的内存空间是有限的。如果我们的内存占用超过了一定的水平就会出现OutOfMemory的错误。
①.为什么会出现内存不够用的情况呢?我想原因主要有两个:由于我们程序的失误,长期保持某些资源(如Context)的引用,造成内存泄露,资源造成得不到释放。保存了多个耗用内存过大的对象(如Bitmap),造成内存超出限制。
② .如何避免优化?
1、应该尽量避免static成员变量引用资源耗费过多的实例,比如Context。Context尽量使用Application Context,因为Application的Context的生命周期比较长,引用它不会出现内存泄露的问题。使用WeakReference代替强引用。比如可以使用WeakReference mContextRef;
2、线程也是造成内存泄露的一个重要的源头。线程产生内存泄露的主要原因在于线程生命周期的不可控。将线程的内部类,改为静态内部类。3、Bitmap问题:可以说出现OutOfMemory问题的绝大多数人,都是因为Bitmap的问题。因为Bitmap占用的内存实在是太多了,它是一个“超级大胖子”,特别是分辨率大的图片,如果要显示多张那问题就更显著了。
如何解决Bitmap带给我们的内存问题?
及时的销毁。 虽然,系统能够确认Bitmap分配的内存最终会被销毁,但是由于它占用的内存过多,所以很可能会超过java堆的限制。因此,在用完Bitmap时,要及时的recycle掉。recycle并不能确定立即就会将Bitmap释放掉,但是会给虚拟机一个暗示:“该图片可以释放了”。设置一定的采样率。 有时候,我们要显示的区域很小,没有必要将整个图片都加载出来,而只需要记载一个缩小过的图片,这时候可以设置一定的采样率,那么就可以大大减小占用的内存。如下面的代码: BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;//图片宽高都为原来的二分之一,即图片为原来的四分之一。
4、巧妙的运用软引用(SoftRefrence) 有些时候,我们使用Bitmap后没有保留对它的引用,因此就无法调用Recycle函数。这时候巧妙的运用软引用,可以使Bitmap在内存快不足时得到有效的释放
5、及时释放Cursor;
6、尽量使用9path图片。Adapter要使用convertView复用等等;
9. AsyncTask 的介绍
在开发 Android 移动客户端的时候往往要使用多线程来进行操作, 我们通常会将耗时的操作放在单独的线程执行, 避免其占用主线程而给用户带来不好的用户体验。 但是在子线程中无法 去操作主线程(UI
线程) ,在子线程中操作
UI 线程会出现错误。因此 android 提供了一个类 Handler 来在子线程中来更新 UI 线程,用发消息的机制更新 UI 界面,呈现给用户。 这样就解决了子线程更新
UI 的问题。但是费时的任务操作总会启动一些匿名的子线程,太多的子线程给系统带来巨大的负担,随之带来一些性能问题。因此 android 提供了一个工具类AsyncTask,顾名思义异步执行任务。这个 AsyncTask 生来就是处理一些后台的比较耗时的任务,给用户带来良好用户体验的,从编程的语法上显得优雅了许多,不再需要子线程和Handler就可以完成异步操作并且刷新用户界面。
10.说说mvc模式的原理,它在android中的运用
答:android的官方建议应用程序的开发采用mvc模式。何谓mvc?
mvc是model,view,controller的缩写,mvc包含三个部分:
l、模型(model)对象:是应用程序的主体部分,所有的业务逻辑都应该写在该层。
2、视图(view)对象:是应用程序中负责生成用户界面的部分。也是在整个mvc架构中用户唯一可以看到的一层,接收用户的输入,显示处理结果。
3、控制器(control)对象:是根据用户的输入,控制用户界面数据显示及更新model对象状态的部分,控制器更重要的一种导航功能,想用用户出发的相关事件,交给m处理。
android鼓励弱耦合和组件的重用,在android中mvc的具体体现如下:
1)视图层(view):一般采用xml文件进行界面的描述,使用的时候可以非常方便的引入,当然,如何你对android了解的比较的多了话,就一定 可以想到在android中也可以使用javascript+html等的方式作为view层,当然这里需要进行java和javascript之间的通 信,幸运的是,android提供了它们之间非常方便的通信实现。
2)控制层(controller):android的控制层的重 任通常落在了众多的acitvity的肩上,这句话也就暗含了不要在acitivity中写代码,要通过activity交割model业务逻辑层处理, 这样做的另外一个原因是android中的acitivity的响应时间是5s,如果耗时的操作放在这里,程序就很容易被回收掉。
3)模型层(model):对数据库的操作、对网络等的操作都应该在model里面处理,当然对业务计算等操作也是必须放在的该层的。
11.根据自己的理解描述下Android数字签名。
答:(1)所有的应用程序都必须有数字证书,Android系统不会安装一个没有数字证书的应用程序
(2)Android程序包使用的数字证书可以是自签名的,不需要一个权威的数字证书机构签名认证
(3)如果要正式发布一个Android ,必须使用一个合适的私钥生成的数字证书来给程序签名,而不能使用adt插件或者ant工具生成的调试证书来发布。
(4)数字证书都是有有效期的,Android只是在应用程序安装的时候才会检查证书的有效期。如果程序已经安装在系统中,即使证书过期也不会影响程序的正常功能
12. 谈谈对 Android NDK 的理解
NDK 全称:Native Development Kit。
1、NDK 是一系列工具的集合。 * NDK 提供了一系列的工具,帮助开发者快速开发 C(或 C++)的动态库,并能自动将 so 和 java 应用
一起打包成 apk。这些工具对开发者的帮助是巨大的。 * NDK 集成了交叉编译器,并提供了相应的 mk 文件隔离 CPU、平台、ABI 等差异,开发人员只需要简单修改 mk 文件(指出“哪些文件需要编译”、“编译特性要求”等) ,就可以创建出
so。 * NDK 可以自动地将
so 和 Java 应用一起打包,极大地减轻了开发人员的打包工作。
2、NDK 提供了一份稳定、功能有限的 API 头文件声明。 Google 明确声明该 API 是稳定的,在后续所有版本中都稳定支持当前发布的 API。从该版本的 NDK 中看出,这些 API 支持的功能非常有限,
包含有:C 标准库(libc) 、标准数学库(libm) 、压缩库(libz) 、Log 库(liblog) 。
13.ViewStub的应用
在开发应用程序的时候,经常会遇到这样的情况,会在运行时动态根据条件来决定显示哪个View或某个布局。那么最通常的想法就是把可能用到的View都写在上面,先把它们的可见性都设为View.GONE,然后在代码中动态的更改它的可见性。这样的做法的优点是逻辑简单而且控制起来比较灵活。但是它的缺点就是,耗费资源。虽然把View的初始可见View.GONE但是在Inflate布局的时候View仍然会被Inflate,也就是说仍然会创建对象,会被实例化,会被设置属性。也就是说,会耗费内存等资源。
推荐的做法是使用android.view.ViewStub,ViewStub是一个轻量级的View,它一个看不见的,不占布局位置,占用资源非常小的控件。可以为ViewStub指定一个布局,在Inflate布局的时候,只有ViewStub会被初始化,然后当ViewStub被设置为可见的时候,或是调用了ViewStub.inflate()的时候,ViewStub所向的布局就会被Inflate和实例化,然后ViewStub的布局属性都会传给它所指向的布局。这样,就可以使用ViewStub来方便的在运行时,要还是不要显示某个布局。
但ViewStub也不是万能的,下面总结下ViewStub能做的事儿和什么时候该用ViewStub,什么时候该用可见性的控制。
首先来说说ViewStub的一些特点:
1. ViewStub只能Inflate一次,之后ViewStub对象会被置为空。按句话说,某个被ViewStub指定的布局被Inflate后,就不会够再通过ViewStub来控制它了。
2. ViewStub只能用来Inflate一个布局文件,而不是某个具体的View,当然也可以把View写在某个布局文件中。
基于以上的特点,那么可以考虑使用ViewStub的情况有:
1. 在程序的运行期间,某个布局在Inflate后,就不会有变化,除非重新启动。
因为ViewStub只能Inflate一次,之后会被置空,所以无法指望后面接着使用ViewStub来控制布局。所以当需要在运行时不止一次的显示和隐藏某个布局,那么ViewStub是做不到的。这时就只能使用View的可见性来控制了。
2. 想要控制显示与隐藏的是一个布局文件,而非某个View。
因为设置给ViewStub的只能是某个布局文件的Id,所以无法让它来控制某个View。
所以,如果想要控制某个View(如Button或TextView)的显示与隐藏,或者想要在运行时不断的显示与隐藏某个布局或View,只能使用View的可见性来控制。
1.HttpURLConnection和HttpClient他们各自的优缺点是什么?
HttpUrlConnection 在 2.3 以前的版本是有 bug 的,所以之前的版本推荐使用 HttpClient,但是 google 现在已经不维护 HttpClient 了,5.1里面已经把 HttpClient 标过期。另外 HttpURLConnection 支持gzip压缩等,推荐首选它。
在 Froyo(2.2) 之前,HttpURLConnection 有个重大 Bug,调用 close() 函数会影响连接池,导致连接复用失效,所以在
Froyo 之前使用 HttpURLConnection 需要关闭 keepAlive。
另外在 Gingerbread(2.3) HttpURLConnection 默认开启了 gzip 压缩,提高了
HTTPS 的性能,Ice Cream Sandwich(4.0) HttpURLConnection 支持了请求结果缓存。
再加上 HttpURLConnection 本身 API 相对简单,所以对 Android 来说,在 2.3 之后建议使用
HttpURLConnection,之前建议使用 AndroidHttpClient。
2.Android开发中XML解析方式的比较,及优缺点?
DOM,SAX,Pull解析。
SAX解析器的优点是解析速度快,占用内存少;
DOM在内存中以树形结构存放,因此检索和更新效率会更高。但是对于特别大的文档,解析和加载整个文档将会很耗资源,不适合移动端;
PULL解析器的运行方式和SAX类似,都是基于事件的模式,PULL解析器小巧轻便,解析速度快,简单易用,非常适合在Android移动设备中使用,Android系统内部在解析各种XML时也是用PULL解析器。
3.请问平时开发过程中,你是如何做到多分辨率适配的?
1.根据不同分辨率建立不同的布局文件
2.根据分辨率不同建立不同分辨率的资源图片
3.在程序启动时,获取当前屏幕的分辨率和密度,在代码中进行适配
4.为不同分辨率的写不同的dimen文件。
5.其实还有就是多使用fragement
4. 谈谈你在工作中是怎样解决一个bug的?
1.看Log日志
2.Log解决不了就断点调试
3.如果debug不行
4.就在异常代码的附近Log.e(“error”,”1”);,2,3,4,5,6,7,8,9 每隔一行一个Log输出,看结果
5.找到问题,自行找思路。如果是技术瓶颈,就google之
5.声明ViewHolder内部类时,为什么建议使用static关键字?
其实这个是考静态内部类和非静态内部类的主要区别之一。非静态内部类会隐式持有外部类的引用,就像大家经常将自定义的adapter在Activity类里,然后在adapter类里面是可以随意调用外部activity的方法的。当你将内部类定义为static时,你就调用不了外部类的实例方法了,因为这时候静态内部类是不持有外部类的引用的。声明ViewHolder静态内部类,可以将ViewHolder和外部类解引用。大家会说一般ViewHolder都很简单,不定义为static也没事吧。确实如此,但是如果你将它定义为static的,说明你懂这些含义。万一有一天你在这个ViewHolder加入一些复杂逻辑,做了一些耗时工作,那么如果ViewHolder是非静态内部类的话,就很容易出现内存泄露。如果是静态的话,你就不能直接引用外部类,迫使你关注如何避免相互引用。 所以将 ViewHolder内部类 定义为静态的,是一种好习惯.
非静态内部类隐式持有外部类的强引用,只是可能会导致内存泄露,而一般情况下在使用viewhodler是不会导致内存泄露的,加static是一个比较好的习惯
6.如何在不失真的条件下显示一张超高清的图片或者长图?
1、通过计算BitmapFactory.Options 对象的inSamleSize 值 等比的压缩图片 。
2、使用WebView来加载该图片;
3、使用MapView或者TileView来显示图片(类似地图的机制);
7. Android中有哪些方法实现定时和延时任务?它们的适用场景是什么?
倒计时类
用CountDownTimer
延迟类
CountDownTimer,可巧妙的将countDownInterval设成和millisInFuture一样,这样就只会调用一次onTick和一次onFinish
handler.sendMessageDelayed,可参考CountDownTimer的内部实现,简化一下,个人比较推荐这个
TimerTask,代码写起来比较乱
Thread.sleep,感觉这种不太好
使用Handler方法postDelay(runnable, delayTime)
定时类
参照延迟类的,自己计算好要延迟多少时间
handler.sendMessageAtTime
AlarmManager,适用于定时比较长远的时间,例如闹铃
8.谈谈你对StrongReference、WeakReference和SoftReference的认识
强引用(StrongReference):就是在代码中普遍存在的,类似Object obj = new Object()这类的引用,只要强引用还存在,GC永远不会回收掉被引用的对象。
软引用(SoftReference):用来描述一些还有用但非必须的对象。对于软引用关联着的对象,在系统将要发生内存溢出异常时,将会把这些对象列入回收范围之中进行第二次回收。如果这次回收还没有足够的内存,才会抛出内存溢出异常。在JDK 1.2之后,提供了SoftReference类来实习软引用。
弱引用(WeakReference):也是用来描述非必须对象的,但是它的强度比软引用更弱一些,被弱引用关联的对象只能生存到了下一次GC发生之前。当GC工作时,无论当时内存是否足够,都会回收只被弱引用关联的对象。在JDK 1.2之后,提供了WeakReference类来实现弱引用。
虚引用(PhantomReference):这个引用po主没有提到,不过也可以顺带了解一下。虚引用也称幽灵引用或者幻影引用,它是最弱的一种引用关系。一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用的唯一目的就是在这个对象被GC回收是收到一个系统通知。在JDK 1.2之后提供了PhantomReference类来实现虚引用。
9.你应用中的网络层是怎么设计的?
1. android-async-http.
封装了下常用的方法,get post 上传 下载 ,所有的请求我都是用的同步请求.
具体的用法一般都是和业务逻辑在一起,而我的业务逻辑是用异步去处理的.
关于网络请求结果的缓存,我是单独处理的.并没有放在网络层.
2.在HttpUrlConnection基础上封装, 包括请求成功, 失败, 请求中, 网络问题等封装, 利用广播与UI交互
3.直接使用xUtils,afinal,okHttp,Volley等开源第三方框架;
Bitmap是android中经常使用的一个类,它代表了一个图片资源。
Bitmap消耗内存很严重,如果不注意优化代码,经常会出现OOM问题,优化方式通常有这么几种:
1. 使用缓存;
2. 压缩图片;
3. 及时回收;
10.谈谈你对Bitmap的理解, 什么时候应该手动调用bitmap.recycle()?
至于什么时候需要手动调用recycle,这就看具体场景了,原则是当我们不再使用Bitmao时,需要回收之。另外,我们需要注意,2.3之前Bitmap对象与像素数据是分开存放的,Bitmap对象存在java Heap中而像素数据存放在Native Memory中,这时很有必要调用recycle回收内存。但是2.3之后,Bitmap对象和像素数据都是存在Heap中,GC可以回收其内存。
11.ViewPager中加载Fragment的优化问题?如何做到微信那样切换界面时的延时加载?
利用fragment中的setUserVisibleHint这个方法可以来做到.
privateboolean
hasLoadedOnce =
false;
// your boolean field
@Override
publicvoid
setUserVisibleHint
(
booleanisVisibleToUser) {
super
.setUserVisibleHint(isVisibleToUser);
if
(
this.isVisible()) {
// we check that the fragment is becoming visible
if
(isVisibleToUser && !hasLoadedOnce) {
//do something
}
}
}
}
12什么是aar?aar和jar有什么区别?
“aar”包是 Android 的类库项目的二进制发行包。
文件扩展名是.aar,maven 项目类型应该也是aar,但文件本身是带有以下各项的
zip 文件:
/AndroidManifest.xml
(mandatory)
/classes.jar (mandatory)
/res/ (mandatory)
/R.txt (mandatory)
/assets/ (optional)
/libs/*.jar (optional)
/jni//*.so (optional)
/proguard.txt (optional)
/lint.jar (optional)
这些条目是直接位于 zip 文件根目录的。
其中R.txt 文件是aapt带参数–output-text-symbols的输出结果。
jar打包不能包含资源文件,比如一些drawable文件、xml资源文件之类的,aar可以。
13.如何加密Url防止被黑?
加密到JNI里面还是会通过抓包工具抓取到.最后的方式就是进行HTTPS证书双向加密验证
14.Android fragment和activity的区别
你可以理解Fragment是一种特殊的View,负责一个模块或者一个特殊部分的展示。
大部分Fragment是依托于Activity存在的,由Activity的FragmentManager来管理
Fragment可以解决多Activity的问题,即将3.0之前的频繁Activity跳转改成一个Activity内Fragment的切换。
Fragment可以解决碎片化的问题。
fragment是android3.0新增的
fragment可以重用
fragment必须嵌套在activity中使用,它的生命周期受activity的影响。
15.Service和广播 BroadcastReceivre会不会出现ANR?
Service,广播 会出现ANR
服务, 广播都是主线程中, 既然是主线程 当然会anr 所以耗时操作还是必须另起线程
通俗的说超时时间:Activity 5秒, Broadcast 10秒, Server 20秒
16.你在平时开发中会使用到哪些设计模式,能谈谈这些设计模式的使用场景吗?
平时用的比较多有单例模式(在内存中仅实例化一个对象时使用),适配器模式(典型的就是ListView和GridView的适配器),建造者模式(AlertDialog.Builder),观察者模式可能比较隐蔽,在Android源码中BaseAdapater的NotifyDataSetChanged的实现(?)
单例:DownloadManager
1.静态内部类、内部类、匿名内部类,为什么内部类会持有外部类的引用?持有的引用是this?还是其它?
静态内部类:使用static修饰的内部类
内部类:就是在某个类的内部又定义了一个类,内部类所嵌入的类称为外部类
匿名内部类:使用new生成的内部类
因为内部类的产生依赖于外部类,持有的引用是类名.this
2.Java中try catch finally的执行顺序
先执行try中代码,如果发生异常执行catch中代码,最后一定会执行finally中代码
3.equals与==的区别:
==是判断两个变量或实例是不是指向同一个内存空间 equals是判断两个变量或实例所指向的内存空间的值是不是相
4.Object有哪些公用方法?
方法equals测试的是两个对象是否相等
方法clone进行对象拷贝
方法getClass返回和当前对象相关的Class对象
方法notify,notifyall,wait都是用来对给定对象进行线程同步的
5.String、StringBuffer与StringBuilder的区别
String 类型和 StringBuffer 类型的主要性能区别其实在于
String 是不可变的对象 StringBuffer和StringBuilder底层是 char[]数组实现的 StringBuffer是线程安全的,而StringBuilder是线程不安全的
6.Java的四种引用的区别
强引用:如果一个对象具有强引用,它就不会被垃圾回收器回收。即使当前内存空间不足,JVM 也不会回收它,而是抛出 OutOfMemoryError 错误,使程序异常终止。如果想中断强引用和某个对象之间的关联,可以显式地将引用赋值为null,这样一来的话,JVM在合适的时间就会回收该对象
软引用:在使用软引用时,如果内存的空间足够,软引用就能继续被使用,而不会被垃圾回收器回收,只有在内存不足时,软引用才会被垃圾回收器回收。
弱引用:具有弱引用的对象拥有的生命周期更短暂。因为当
JVM 进行垃圾回收,一旦发现弱引用对象,无论当前内存空间是否充足,都会将弱引用回收。不过由于垃圾回收器是一个优先级较低的线程,所以并不一定能迅速发现弱引用对象
虚引用:顾名思义,就是形同虚设,如果一个对象仅持有虚引用,那么它相当于没有引用,在任何时候都可能被垃圾回收器回收。
7.介绍垃圾回收机制
标记回收法:遍历对象图并且记录可到达的对象,以便删除不可到达的对象,一般使用单线程工作并且可能产生内存碎片
标记-压缩回收法:前期与第一种方法相同,只是多了一步,将所有的存活对象压缩到内存的一端,这样内存碎片就可以合成一大块可再利用的内存区域,提高了内存利用率
复制回收法:把现有内存空间分成两部分,gc运行时,它把可到达对象复制到另一半空间,再清空正在使用的空间的全部对象。这种方法适用于短生存期的对象,持续复制长生存期的对象则导致效率降低。
分代回收发:把内存空间分为两个或者多个域,如年轻代和老年代,年轻代的特点是对象会很快被回收,因此在年轻代使用效率比较高的算法。当一个对象经过几次回收后依然存活,对象就会被放入称为老年的内存空间,老年代则采取标记-压缩算法
集合、数据结构相关
1.你用过哪些集合类
数据结构中用于存储数据的有哪些
数组
数组存储区间是连续的,占用内存严重,故空间复杂的很大。但数组的二分查找时间复杂度小,为O(1);数组的特点是:寻址容易,插入和删除困难;
链表
链表存储区间离散,占用内存比较宽松,故空间复杂度很小,但时间复杂度很大,达O(N)。链表的特点是:寻址困难,插入和删除容易。
2.说说hashMap是怎样实现的
哈希表:由数组+链表组成的
当我们往HashMap中put元素的时候,先根据key的hashCode重新计算hash值,根据hash值得到这个元素在数组中的位置(即下标),如果数组该位置上已经存放有其他元素了,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放在链尾。如果数组该位置上没有元素,就直接将该元素放到此数组中的该位置上。
3.ArrayList,LinkedList的区别
ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。
4.ArrayList和Vector的主要区别是什么?
ArrayList 和Vector底层是采用数组方式存储数据
Vector:
线程同步
当Vector中的元素超过它的初始大小时,Vector会将它的容量翻倍,
ArrayList:
线程不同步,但性能很好
当ArrayList中的元素超过它的初始大小时,ArrayList只增加50%的大小
5.HashMap和 HashTable 的区别:
HashTable比较老,是基于Dictionary 类实现的,HashTable 则是基于 Map接口实现的
HashTable 是线程安全的, HashMap 则是线程不安全的
HashMap可以让你将空值作为一个表的条目的key或value
算法相关
1.排序算法和稳定性,快排什么时候情况最坏?
2.给最外层的rootview,把这个根视图下的全部button背景设置成红色,手写代码,不许用递归
算法原理:
Android的view视图是按树形结构分布,所以按树形结构遍历
循环判断每一层的ViewGroup元素,将其入栈;否则判断当前view是否是Button类实例,是则改写背景色
当前ViewGroup检查childView完成后,判断栈是否非空,取出栈顶元素ViewGroup重复步骤2直至栈为空。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
void changeAllBtnBGColor(View view, int color) { if (view == null || !(view return; Stack m = new Stack<>(); while (view != null) { ViewGroup tmpGroup = (ViewGroup) view; int count = tmpGroup.getChildCount(); for (int i = 0; i < count; i++) { if (child instanceof ViewGroup) else if (child instanceof Button) { child.setBackgroundColor(color); } } if (m.isEmpty()) break; else view = m.pop(); } } |
Thread、AsynTask相关
1.wait()和sleep()的区别
sleep来自Thread类,和wait来自Object类
调用sleep()方法的过程中,线程不会释放对象锁。而
调用 wait 方法线程会释放对象锁
sleep睡眠后不出让系统资源,wait让出系统资源其他线程可以占用CPU
sleep(milliseconds)需要指定一个睡眠时间,时间一到会自动唤醒
2.若Activity已经销毁,此时AsynTask执行完并且返回结果,会报异常吗?
当一个App旋转时,整个Activity会被销毁和重建。当Activity重启时,AsyncTask中对该Activity的引用是无效的,因此onPostExecute()就不会起作用,若AsynTask正在执行,折会报 view not attached to window manager 异常
同样也是生命周期的问题,在 Activity 的onDestory()方法中调用Asyntask.cancal方法,让二者的生命周期同步
3.Activity销毁但Task如果没有销毁掉,当Activity重启时这个AsyncTask该如何解决?
还是屏幕旋转这个例子,在重建Activity的时候,会回掉Activity.onRetainNonConfigurationInstance()重新传递一个新的对象给AsyncTask,完成引用的更新
4.Android 线程间通信有哪几种方式(重要)
共享内存(变量);
文件,数据库;
Handler;
Java 里的 wait(),notify(),notifyAll()
5.请介绍下 AsyncTask的内部实现,适用的场景是
AsyncTask 内部也是 Handler 机制来完成的,只不过 Android 提供了执行框架来提供线程池来
执行相应地任务,因为线程池的大小问题,所以
AsyncTask 只应该用来执行耗时时间较短的任务,
比如 HTTP 请求,大规模的下载和数据库的更改不适用于 AsyncTask,因为会导致线程池堵塞,没有
线程来执行其他的任务,导致的情形是会发生
AsyncTask 根本执行不了的问题。
网络相关
1.TCP三次握手
2.为什么TCP是可靠的,UDP早不可靠的?为什么UDP比TCP快?
TCP/IP协议高,因为其拥有三次握手双向机制,这一机制保证校验了数据,保证了他的可靠性。
UDP就没有了,udp信息发出后,不验证是否到达对方,所以不可靠。
但是就速度来说,还是UDP协议更高,毕竟其无需重复返回验证,只是一次性的
3.http协议了解多少,说说里面的协议头部有哪些字段?
http(超文本传输协议)是一个基于请求与响应模式的、无状态的、应用层的协议;http请求由三部分组成,分别是:请求行、消息报头、请求正文。
HTTP消息报头包括普通报头、请求报头、响应报头、实体报头
4.https了解多少
HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。
5.谈谈 HTTP 中Get 和 Post 方法的区别
GET - 从指定的服务器中获取数据,明文发送内容
POST - 提交数据给指定的服务器处理
1. POST请求不能被缓存下来
2. POST请求不会保存在浏览器浏览记录中
3. 以POST请求的URL无法保存为浏览器书签
4. POST请求没有长度限制
6.推送心跳包是TCP包还是UDP包或者HTTP包
心跳包的实现是调用了socket.sendUrgentData(0xFF)这句代码实现的,所以,当然是TCP包。
7.如何实现文件断点上传
在 Android 中上传文件可以采用 HTTP 方式,也可以采用 Socket 方式,但是 HTTP 方式不能上传
大文件,这里介绍一种通过 Socket 方式来进行断点续传的方式,服务端会记录下文件的上传进度,
当某一次上传过程意外终止后,下一次可以继续上传,这里用到的其实还是 J2SE 里的知识。
这个上传程序的原理是:客户端第一次上传时向服务端发送
“Content-Length=35;filename=WinRAR_3.90_SC.exe;sourceid=“这种格式的字符串,服务端
收到后会查找该文件是否有上传记录,如果有就返回已经上传的位置,否则返回新生成的 sourceid
以及 position 为 0,类似 sourceid=2324838389;position=0“这样的字符串,客户端收到返回后
的字符串后再从指定的位置开始上传文件。
Fragment相关
1.Fragment 如何实现类似 Activity 栈的压栈和出栈效果的?
Fragment 的事物管理器内部维持了一个双向链表结构,该结构可以记录我们每次 add 的
Fragment 和 replace 的 Fragment,然后当我们点击 back 按钮的时候会自动帮我们实现退栈操作。
2.Fragment 在你们项目中的使用
Fragment 是 android3.0 以后引入的的概念,做局部内容更新更方便,原来为了到达这一点要
把多个布局放到一个 activity 里面,现在可以用多 Fragment 来代替,只有在需要的时候才加载
Fragment,提高性能。
Fragment 的好处:
1. Fragment 可以使你能够将 activity 分离成多个可重用的组件,每个都有它自己的生命周期和
UI。
2. Fragment 可以轻松得创建动态灵活的 UI 设计,可以适应于不同的屏幕尺寸。从手机到平板电
脑。
3. Fragment 是一个独立的模块,紧紧地与 activity 绑定在一起。可以运行中动态地移除、加入、
交换等。
4. Fragment 提供一个新的方式让你在不同的安卓设备上统一你的 UI。
5. Fragment 解决 Activity 间的切换不流畅,轻量切换。
6. Fragment 替代 TabActivity 做导航,性能更好。
7. Fragment 在 4.2.版本中新增嵌套 fragment 使用方法,能够生成更好的界面效果
3.如何切换 fragement,不重新实例化
正确的切换方式是 add(),切换时 hide(),add()另一个
Fragment;再次切换时,只需 hide()当前,
show()另一个
四大组件相关
1.Activity和Fragment生命周期有哪些?
Activity——onCreate->onStart->onResume->onPause->onStop->onDestroy
Fragment——onAttach->onCreate->onCreateView->onActivityCreated->onStart->onResume->onPause->onStop->onDestroyView->onDestroy->onDetach
2.广播的两种注册方式及有什么区别
3.内存不足时,怎么保持Activity的一些状态,在哪个方法里面做具体操作?
Activity的 onSaveInstanceState() 和
onRestoreInstanceState()并不是生命周期方法,它们不同于 onCreate()、onPause()等生命周期方法,它们并不一定会被触发。当应用遇到意外情况(如:内存不足、用户直接按Home键)由系统销毁一个Activity,onSaveInstanceState() 会被调用。但是当用户主动去销毁一个Activity时,例如在应用中按返回键,onSaveInstanceState()就不会被调用。除非该activity是被用户主动销毁的,通常onSaveInstanceState()只适合用于保存一些临时性的状态,而onPause()适合用于数据的持久化保存。
4.启动service的两种方法?有什么区别?
一种是startService(),另一种是bindService()。这两者的区别是第一种方式调用者开启了服务,即会与服务失去联系,两者没有关联。即使访问者退出了,服务仍在运行。如需解除服务必须显式的调用stopService方法。主要用于调用者与服务没有交互的情况下,也就是调用者不需要获取服务里的业务方法。比如电话录音。而后者调用者与服务绑定在一起的。当调用者退出的时候,服务也随之退出。用于需要与服务交互。
5.Android中的Context, Activity,Appliction有什么区别?
相同:Activity和Application都是Context的子类。
Context从字面上理解就是上下文的意思,在实际应用中它也确实是起到了管理上下文环境中各个参数和变量的总用,方便我们可以简单的访问到各种资源。
不同:维护的生命周期不同。 Context维护的是当前的Activity的生命周期,Application维护的是整个项目的生命周期。
使用context的时候,小心内存泄露,防止内存泄露,注意一下几个方面:
1. 不要让生命周期长的对象引用activity context,即保证引用activity的对象要与activity本身生命周期是一样的。
2. 对于生命周期长的对象,可以使用application,context。
3. 避免非静态的内部类,尽量使用静态类,避免生命周期问题,注意内部类对外部对象引用导致的生命周期变化。
6.Context是什么?
它描述的是一个应用程序环境的信息,即上下文。
该类是一个抽象(abstract class)类,Android提供了该抽象类的具体实现类(ContextIml)。
通过它我们可以获取应用程序的资源和类,也包括一些应用级别操作,例如:启动一个Activity,发送广播,接受Intent,信息,等。
7.Service 是否在 main thread 中执行, service 里面是否能执行耗时的操
作?
默认情况,如果没有显示的指 servic 所运行的进程, Service 和 activity 是运行在当前 app 所在进
程的 main thread(UI 主线程)里面。
service 里面不能执行耗时的操作(网络请求,拷贝数据库,大文件 )
<service<
p=""></service<>
特殊情况 ,可以在清单文件配置 service 执行所在的进程 ,让
service 在另外的进程中执行
1 2 3 4 5 |
<service android:name="com.baidu.location.f" android:enabled="true" android:process=":remote" > </service> |
8.Activity 怎么和 Service 绑定,怎么在 Activity 中启动自己对应的
Service?
Activity 通过 bindService(Intent service, ServiceConnection conn,
int flags)跟 Service 进行
绑定,当绑定成功的时候 Service 会将代理对象通过回调的形式传给 conn,这样我们就拿到了
Service 提供的服务代理对象。
在 Activity 中可以通过 startService 和 bindService 方法启动 Service。一般情况下如果想获取
Service 的服务对象那么肯定需要通过 bindService()方法,比如音乐播放器,第三方支付等。如
果仅仅只是为了开启一个后台任务那么可以使用
startService()方法。
9.说说 Activity、Intent、Service 是什么关系
他们都是 Android 开发中使用频率最高的类。其中 Activity 和 Service 都是 Android 四大组件
之一。他俩都是 Context 类的子类 ContextWrapper 的子类,因此他俩可以算是兄弟关系吧。不过
兄弟俩各有各自的本领,Activity 负责用户界面的显示和交互,Service 负责后台任务的处理。Activity
和 Service 之间可以通过 Intent 传递数据,因此可以把 Intent 看作是通信使者。
10.请描述一下 BroadcastReceiver
BroadCastReceiver 是 Android 四大组件之一,主要用于接收系统或者 app 发送的广播事件。
广播分两种:有序广播和无序广播。
内部通信实现机制:通过 Android 系统的 Binder 机制实现通信。
1. 无序广播:完全异步,逻辑上可以被任何广播接收者接收到。优点是效率较高。缺点是一个接收者不
能将处理结果传递给下一个接收者,并无法终止广播
intent 的传播。
2. 有序广播:按照被接收者的优先级顺序,在被接收者中依次传播。比如有三个广播接收者 A,B,C,
优先级是 A > B > C。那这个消息先传给 A,再传给 B,最后传给 C。每个接收者有权终止广播,比
如 B 终止广播,C 就无法接收到。此外 A 接收到广播后可以对结果对象进行操作,当广播传给 B 时,
B 可以从结果对象中取得 A 存入的数据。
在通过
Context.sendOrderedBroadcast(intent, receiverPermission, resultReceiver,
scheduler,
initialCode, initialData, initialExtras)时我们可以指定 resultReceiver 广播接收者,这个接收者我们
可以认为是最终接收者,通常情况下如果比他优先级更高的接收者如果没有终止广播,那么他的
onReceive 会被执行两次,第一次是正常的按照优先级顺序执行,第二次是作为最终接收者接收。
如果比他优先级高的接收者终止了广播,那么他依然能接收到广播
11.为什么要用 ContentProvider?它和 sql 的实现上有什么差别?
ContentProvider 屏蔽了数据存储的细节,内部实现对用户完全透明,用户只需要关心操作数据的
uri 就可以了,ContentProvider 可以实现不同 app 之间共享。
Sql 也有增删改查的方法,但是 sql 只能查询本应用下的数据库。而
ContentProvider 还可
以去增删改查本地文件. xml 文件的读取等。
12.说说 ContentProvider、ContentResolver、ContentObserver 之间的关系
a. ContentProvider 内容提供者,用于对外提供数据
b. ContentResolver.notifyChange(uri)发出消息
c. ContentResolver 内容解析者,用于获取内容提供者提供的数据
d. ContentObserver 内容监听器,可以监听数据的改变状态
e.
ContentResolver.registerContentObserver()监听消息。
View 相关
1.onInterceptTouchEvent()和onTouchEvent()的区别
onInterceptTouchEvent()用于拦截触摸事件
onTouchEvent()用于处理触摸事件
2.RemoteView在哪些功能中使用
APPwidget和Notification中
3. SurfaceView和View的区别是什么?
SurfaceView中采用了双缓存技术,在单独的线程中更新界面
View在UI线程中更新界面
4.View的绘制过程
一个View要显示在界面上,需要经历一个View树的遍历过程,这个过程又可以分为三个过程,也就是自定义View中的三要素:大小,位置,画什么,即onMesure(),onLayout(),onDraw()。
1.onMesure()确定一个View的大小;
2.onLayout()确定View在父节点上的位置;
3.onDraw()绘制View 的内容;
5.如何自定义ViewGroup
1.指定的LayoutParams
2.onMeasure中计算所有childView的宽和高,然后根据childView的宽和高,计算自己的宽和高。(当然,如果不是wrap_content,直接使用父ViewGroup传入的计算值即可)
3.onLayout中对所有的childView进行布局。
6.View中onTouch,onTouchEvent,onClick的执行顺序
dispatchTouchEvent—->onTouch—->onTouchEvent—–>onClick。在所有ACTION_UP事件之后才触发onClick点击事件。
性能优化相关
1.ListView卡顿的原因与性能优化,越多越好
重用converView: 通过复用converview来减少不必要的view的创建,另外Infalte操作会把xml文件实例化成相应的View实例,属于IO操作,是耗时操作。
减少findViewById()操作:
将xml文件中的元素封装成viewholder静态类,通过converview的setTag和getTag方法将view与相应的holder对象绑定在一起,避免不必要的findviewbyid操作
避免在 getView 方法中做耗时的操作: 例如加载本地 Image 需要载入内存以及解析 Bitmap ,都是比较耗时的操作,如果用户快速滑动listview,会因为getview逻辑过于复杂耗时而造成滑动卡顿现象。用户滑动时候不要加载图片,待滑动完成再加载,可以使用这个第三方库glide
Item的布局层次结构尽量简单,避免布局太深或者不必要的重绘
尽量能保证 Adapter 的 hasStableIds() 返回 true 这样在 notifyDataSetChanged() 的时候,如果item内容并没有变化,ListView 将不会重新绘制这个 View,达到优化的目的
在一些场景中,ScollView内会包含多个ListView,可以把listview的高度写死固定下来。 由于ScollView在快速滑动过程中需要大量计算每一个listview的高度,阻塞了UI线程导致卡顿现象出现,如果我们每一个item的高度都是均匀的,可以通过计算把listview的高度确定下来,避免卡顿现象出现
使用 RecycleView 代替listview: 每个item内容的变动,listview都需要去调用notifyDataSetChanged来更新全部的item,太浪费性能了。RecycleView可以实现当个item的局部刷新,并且引入了增加和删除的动态效果,在性能上和定制上都有很大的改善
ListView 中元素避免半透明: 半透明绘制需要大量乘法计算,在滑动时不停重绘会造成大量的计算,在比较差的机子上会比较卡。 在设计上能不半透明就不不半透明。实在要弄就把在滑动的时候把半透明设置成不透明,滑动完再重新设置成半透明。
尽量开启硬件加速: 硬件加速提升巨大,避免使用一些不支持的函数导致含泪关闭某个地方的硬件加速。当然这一条不只是对 ListView。
2.如何避免 OOM 问题的出现
使用更加轻量的数据结构 例如,我们可以考虑使用ArrayMap/SparseArray而不是HashMap等传统数据结构。通常的HashMap的实现方式更加消耗内存,因为它需要一个额外的实例对象来记录Mapping操作。另外,SparseArray更加高效,在于他们避免了对key与value的自动装箱(autoboxing),并且避免了装箱后的解箱。
避免在Android里面使用Enum Android官方培训课程提到过“Enums often
require more than twice as much memory as static constants. You should strictly
avoid using enums on Android.”,具体原理请参考《Android性能优化典范(三)》,所以请避免在Android里面使用到枚举。
减小Bitmap对象的内存占用 Bitmap是一个极容易消耗内存的大胖子,减小创建出来的Bitmap的内存占用可谓是重中之重,,通常来说有以下2个措施: ++inSampleSize++:缩放比例,在把图片载入内存之前,我们需要先计算出一个合适的缩放比例,避免不必要的大图载入。 ++decode format++:解码格式,选择ARGB_6666/RBG_545/ARGB_4444/ALPHA_6,存在很大差异
Bitmap对象的复用 缩小Bitmap的同时,也需要提高BitMap对象的复用率,避免频繁创建BitMap对象,复用的方法有以下2个措施 LRUCache : “最近最少使用算法”在Android中有极其普遍的应用。ListView与GridView等显示大量图片的控件里,就是使用LRU的机制来缓存处理好的Bitmap,把近期最少使用的数据从缓存中移除,保留使用最频繁的数据, inBitMap高级特性:利用inBitmap的高级特性提高Android系统在Bitmap分配与释放执行效率。使用inBitmap属性可以告知Bitmap解码器去尝试使用已经存在的内存区域,新解码的Bitmap会尝试去使用之前那张Bitmap在Heap中所占据的pixel data内存区域,而不是去问内存重新申请一块区域来存放Bitmap。利用这种特性,即使是上千张的图片,也只会仅仅只需要占用屏幕所能够显示的图片数量的内存大小
使用更小的图片 在涉及给到资源图片时,我们需要特别留意这张图片是否存在可以压缩的空间,是否可以使用更小的图片。尽量使用更小的图片不仅可以减少内存的使用,还能避免出现大量的InflationException。假设有一张很大的图片被XML文件直接引用,很有可能在初始化视图时会因为内存不足而发生InflationException,这个问题的根本原因其实是发生了OOM。
StringBuilder 在有些时候,代码中会需要使用到大量的字符串拼接的操作,这种时候有必要考虑使用StringBuilder来替代频繁的“+”。
避免在onDraw方法里面执行对象的创建
类似onDraw等频繁调用的方法,一定需要注意避免在这里做创建对象的操作,因为他会迅速增加内存的使用,而且很容易引起频繁的gc,甚至是内存抖动。
避免对象的内存泄露
3.三级缓存的原理
从缓存中加载。
从本地文件中加载(数据库,SD)
从网络加载。
a.加载 bitmap 的时候无需考虑 bitmap 加载过程中出现的 oom(内存溢出)和 android 容器快速
滑动的时候出现的图片错位等现象。(16M)
b. 支持加载网络图片和本地图片。
c. 内存管理使用的 lru 算法(移除里面是有频率最少的对象),更好的管理 bitmap 的内存
Android其他
1.讲一下android中进程的优先级?
前台进程
可见进程
服务进程
后台进程
空进程
2.介绍Handle的机制
Handler通过调用sendmessage方法把消息放在消息队列MessageQueue中,Looper负责把消息从消息队列中取出来,重新再交给Handler进行处理,三者形成一个循环
通过构建一个消息队列,把所有的Message进行统一的管理,当Message不用了,并不作为垃圾回收,而是放入消息队列中,供下次handler创建消息时候使用,提高了消息对象的复用,减少系统垃圾回收的次数
每一个线程,都会单独对应的一个looper,这个looper通过ThreadLocal来创建,保证每个线程只创建一个looper,looper初始化后就会调用looper.loop创建一个MessageQueue,这个方法在UI线程初始化的时候就会完成,我们不需要手动创建
3.Dalvik虚拟机与JVM有什么区别
Dalvik 基于寄存器,而 JVM 基于栈。基于寄存器的虚拟机对于更大的程序来说,在它们编译的时候,花费的时间更短。
Dalvik执行.dex格式的字节码,而JVM执行.class格式的字节码。
4.每个应用程序对应多少个Dalvik虚拟机
每一个Android应用在底层都会对应一个独立的Dalvik虚拟机实例,其代码在虚拟机的解释下得以执行 ,而所有的Android应用的线程都对应一个Linux线程
5.应用常驻后台,避免被第三方杀掉的方法
Service设置成START_STICKY kill 后会被重启(等待5秒左右),重传Intent,保持与重启前一样
通过 startForeground将进程设置为前台进程,
做前台服务,优先级和前台应用一个级别,除非在系统内存非常缺,否则此进程不会被 kill
双进程Service: 让2个进程互相保护对方,其中一个Service被清理后,另外没被清理的进程可以立即重启进程
用C编写守护进程(即子进程) : Android系统中当前进程(Process)fork出来的子进程,被系统认为是两个不同的进程。当父进程被杀死的时候,子进程仍然可以存活,并不受影响(Android5.0以上的版本不可行
联系厂商,加入白名单
6.根据自己的理解描述下Android数字签名。
所有的应用程序都必须有数字证书,Android系统不会安装一个没有数字证书的应用程序
Android程序包使用的数字证书可以是自签名的,不需要一个权威的数字证书机构签名认证
如果要正式发布一个Android程序,必须使用一个合适的私钥生成的数字证书来给程序签名,而不能使用adt插件或者ant工具生成的调试证书来发布。
数字证书都是有有效期的,Android只是在应用程序安装的时候才会检查证书的有效期。如果程序已经安装在系统中,即使证书过期也不会影响程序的正常功能。
7.Dalvik基于JVM的改进
几个class变为一个dex,constant pool,省内存
Zygote,copy-on-write shared,省内存,省cpu,省电
基于寄存器的bytecode,省指令,省cpu,省电
Trace-based JIT,省cpu,省电,省内存
8.ARGB_8888占用内存大小
本题的答案,是4byte,即ARGB各占用8个比特来描述。
9.apk安装卸载的原理
安装过程:复制apk安装包到data/app目录下,解压并扫描安装包,把dex文件(dalvik字节码)保存到dalvik-cache目录,并data/data目录下创建对应的应用数据目录。
卸载过程:删除安装过程中在上述三个目录下创建的文件及目录。
10.通过Intent传递一些二进制数据的方法有哪些?
使用Serializable接口实现序列化,这是Java常用的方法。
实现Parcelable接口,这里Android的部分类比如Bitmap类就已经实现了,同时Parcelable在Android AIDL中交换数据也很常见的。
11.横竖屏切换时Activity的生命周期
此时的生命周期跟清单文件里的配置有关系。
不设置Activity的android:configChanges时,切屏会重新调用各个生命周期默认首先销毁当前activity,然后重新加载。
设置Activity
android:configChanges=”orientation|keyboardHidden|screenSize”时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法
12.Serializable 和 Parcelable 的区别
在使用内存的时候,Parcelable 类比 Serializable 性能高,所以推荐使用 Parcelable 类。
1. Serializable 在序列化的时候会产生大量的临时变量,从而引起频繁的
GC。
2. Parcelable 不能使用在要将数据存储在磁盘上的情况。尽管
Serializable 效率低点,但在这
种情况下,还是建议你用 Serializable 。
13.Android 中如何捕获未捕获的异常
自 定 义 一 个 Application ,
比 如 叫 MyApplication 继 承 Application 实
现
UncaughtExceptionHandler。
覆写
UncaughtExceptionHandler 的 onCreate 和 uncaughtException 方法。
14.Android 的权限规则
Android 中的 apk 必须签名
基于 UserID 的进程级别的安全机制
默认 apk 生成的数据对外是不可见的
AndroidManifest.xml 中的显式权限声明
15.多线程间通信和多进程之间通信有什么不同,分别怎么实现?
一、进程间的通信方式
1. 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的
进程间使用。进程的亲缘关系通常是指父子进程关系。
2. 有名管道 (namedpipe) : 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的
通信。
3. 信号量(semophore ) : 信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它
常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进
程间以及同一进程内不同线程之间的同步手段。
4. 消息队列( messagequeue ) : 消息队列是由消息的链表,存放在内核中并由消息队列标识符
标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
5. 信号 (sinal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
6. 共享内存(shared memory ) :共享内存就是映射一段能被其他进程所访问的内存,这段共享内
存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间
通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间
的同步和通信。
7. 套接字(socket ) : 套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同
及其间的进程通信。
二、线程间的通信方式
1. 锁机制:包括互斥锁、条件变量、读写锁
*互斥锁提供了以排他方式防止数据结构被并发修改的方法。
*读写锁允许多个线程同时读共享数据,而对写操作是互斥的。
*条件变量可以以原子的方式阻塞进程,直到某个特定条件为真为止。对条件的测试是在互斥锁
的保护下进行的。条件变量始终与互斥锁一起使用。
2. 信号量机制(Semaphore):包括无名线程信号量和命名线程信号量
3. 信号机制(Signal):类似进程间的信号处理
线程间的通信目的主要是用于线程同步,所以线程没有像进程通信中的用于数据交换的通信机
制。
16.说说 LruCache 底层原理
LruCache 使用一个 LinkedHashMap 简单的实现内存的缓存,没有软引用,都是强引用。如果添
加的数据大于设置的最大值,就删除最先缓存的数据来调整内存。
maxSize 是通过构造方法初始化的值,他表示这个缓存能缓存的最大值是多少。
size 在添加和移除缓存都被更新值,他通过 safeSizeOf 这个方法更新值。safeSizeOf 默认返回 1,
但一般我们会根据 maxSize 重写这个方法,比如认为 maxSize 代表是 KB 的话,那么就以 KB 为单
位返回该项所占的内存大小。
除异常外首先会判断 size 是否超过 maxSize,如果超过了就取出最先插入的缓存,如果不为空就
删掉,并把 size 减去该项所占的大小。这个操作将一直循环下去,直到 size 比 maxSize 小或者缓存
为空。
1.
Activity建立在哪些窗口组件之上?顺带涉及View的事件传递问题。
没读懂问题,=。=不知道是不是问Activity的UI结构,如果是可以参考这篇文章。
对于View的事件传递,则可以从 Activity -->
ViewGroup --> ...... --> Activity 的** U型 **消费结构去说。
2.
什么情况下,Activity的onNewInstent()方法会执行?Activity的启动模式相关。
当此Activity的实例已经存在,并且此时的启动模式为SingleTask和SingleInstance,另外当这个实例位于栈顶且启动模式为SingleTop时也会触发onNewInstent()。
3.
Activity A使用startForResult启动Activity B,B什么都不做并返回A,A中的onActivityResult回调是否会执行?
startActivity()方法,最终都是调用startActivityForResult()方法。默认的requestCode = -1
resultCode = RESULT_CANCELED = 0,当你的requestCode != -1时,onActivityResult()一定会被调用。
4.
Fragment能否不依赖于Activity存在?简析一下Fragment的栈管理。
Fragment不能独立存在,它必须嵌入到activity中,而且Fragment的生命周期直接受所在的activity的影响。
// Create new fragment and transaction
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
// Replace whatever is in the
fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
transaction只是记录了从一个状态到另一个状态的变化过程,即比如从FragmentA替换到FragmentB的过程,当通过函数transaction.addToBackStack(null)将这个事务添加到回退栈,则会记录这个事务的状态变化过程,如从FragmentA —>FragmentB,当用户点击手机回退键时,因为transaction的状态变化过程被保存,则可以将事务的状态变化过程还原,即将FragmentB —> FragmentA.
添加到回退栈的函数:transaction.addToBackStack(null);
参考文章: http://blog.csdn.net/u011026329/article/details/47903177
5.
能否将一个Activity放到系统的最近任务列表里,独立于宿主app任务卡之外?
我印象中是可以做到了,平时没用到,知道的同学请@我,谢谢!
6.
对于同一个Service,在被start启动之后还能不能被bind?
能
服务基本上分为两种形式:
启动
当应用组件(如
Activity)通过调用 startService() 启动服务时,服务即处于“启动”状态。一旦启动,服务即可在后台无限期运行,即使启动服务的组件已被销毁也不受影响。 已启动的服务通常是执行单一操作,而且不会将结果返回给调用方。例如,它可能通过网络下载或上传文件。 操作完成后,服务会自行停止运行。
绑定
当应用组件通过调用
bindService() 绑定到服务时,服务即处于“绑定”状态。绑定服务提供了一个客户端-服务器接口,允许组件与服务进行交互、发送请求、获取结果,甚至是利用进程间通信 (IPC) 跨进程执行这些操作。 仅当与另一个应用组件绑定时,绑定服务才会运行。 多个组件可以同时绑定到该服务,但全部取消绑定后,该服务即会被销毁。
虽然本文档是分开概括讨论这两种服务,但是您的服务可以同时以这两种方式运行,也就是说,它既可以是启动服务(以无限期运行),也允许绑定。问题只是在于您是否实现了一组回调方法:onStartCommand()(允许组件启动服务)和
onBind()(允许绑定服务)。
来自官方文档
7.
Service有哪些派生类?这些派生类的使用场景是什么?
这个问题不知道问的具体是什么,如果是要 IntentService那么可以参考官方文档的解释与使用说明:
扩展 IntentService 类
由于大多数启动服务都不必同时处理多个请求(实际上,这种多线程情况可能很危险),因此使用 IntentService 类实现服务也许是最好的选择。
IntentService 执行以下操作:
创建默认的工作线程,用于在应用的主线程外执行传递给 onStartCommand() 的所有 Intent。
创建工作队列,用于将
Intent 逐一传递给 onHandleIntent() 实现,这样您就永远不必担心多线程问题。
在处理完所有启动请求后停止服务,因此您永远不必调用 stopSelf()。
提供 onBind() 的默认实现(返回 null)。
提供 onStartCommand() 的默认实现,可将 Intent 依次发送到工作队列和 onHandleIntent() 实现。
综上所述,您只需实现 onHandleIntent() 来完成客户端提供的工作即可。(不过,您还需要为服务提供小型构造函数。)
以下是 IntentService 的实现示例:
public class HelloIntentService extends IntentService {
/**
* A constructor is required, and must call
the super IntentService(String)
* constructor with a name for the worker
thread.
*/
public HelloIntentService() {
super("HelloIntentService");
}
/**
* The IntentService calls this method from
the default worker thread with
* the intent that started the service. When
this method returns, IntentService
* stops the service, as appropriate.
*/
@Override
protected void onHandleIntent(Intent intent) {
// Normally we would do some work here, like download a
file.
// For our sample, we just sleep for 5 seconds.
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// Restore interrupt status.
Thread.currentThread().interrupt();
}
}
}
您只需要一个构造函数和一个 onHandleIntent() 实现即可。
如果您决定还重写其他回调方法(如 onCreate()、onStartCommand() 或
onDestroy()),请确保调用超类实现,以便 IntentService 能够妥善处理工作线程的生命周期。
例如,onStartCommand() 必须返回默认实现(即,如何将
Intent 传递给
onHandleIntent()):
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
return super.onStartCommand(intent,flags,startId);
}
除 onHandleIntent() 之外,您无需从中调用超类的唯一方法就是 onBind()(仅当服务允许绑定时,才需要实现该方法)。
8.
Service与其它组件之间的通信实现方式有哪些?
- binder
- broadcast
- 其他参见线程和进程的通信方式
9.
View的post(Runnable
r)方法里,r会带来一个新的线程吗?多线程相关。
不会,最终还是handler发送消息,执行在UI线程。
如下是源码和注释:
/**
* <p>Causes the Runnable to be added
to the message queue.
* The runnable will be run on the user
interface thread.</p>
*
* @param
action The Runnable that will be executed.
*
* @return Returns true if the Runnable was successfully placed in
to the
*
message queue. Returns false on
failure, usually because the
*
looper processing the message queue is exiting.
*
* @see
#postDelayed
* @see
#removeCallbacks
*/
public boolean post(Runnable action) {
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
return attachInfo.mHandler.post(action);
}
// Postpone the runnable until we know on which thread it
needs to run.
// Assume that the runnable will be successfully placed
after attach.
getRunQueue().post(action);
return true;
}
10.
在非UI线程中使用Handler需要注意哪些问题?
new Thread(){
public void run(){
Looper.prepare();//给当前线程初始化Looper
Toast.makeText(getApplicationContext(),"更新UI",0).show();//Toast初始化的时候会new Handler();无参构造默认获取当前线程的Looper,如果没有prepare过,则抛出题主描述的异常。上一句代码初始化过了,就不会出错。
Looper.loop();//这句执行,Toast排队show所依赖的Handler发出的消息就有人处理了,Toast就可以吐出来了。但是,这个Thread也阻塞这里了,因为loop()是个for (;;) ...
}
}.start();
参考:
https://www.zhihu.com/question/51099935
https://www.zhihu.com/question/34652589
11.
自定义View时有哪些重要的方法,它们的作用及执行顺序是怎样的?
按照顺序:onMeasure() --> onLayout() --> onDraw().其他的自己扩展吧。
12.
如何单独对ListView上的一个item进行更新?
- 更新对应view的内容
- 通过ViewHolder去设置值
- 调用一次getView()方法(Google IO 推荐)
参考文章
http://blog.csdn.net/linglongxin24/article/details/53020164
13.
简析一下大图片的加载处理。
对Bitmap的理解,然后就是压缩图片。
14.
设计师只给了一套1280*800的UI图标注,如何进行其它分辨率尺寸屏幕的适配?
名称 |
像素密度范围 |
图片大小 |
mdpi |
120dp~160dp |
48×48px |
hdpi |
160dp~240dp |
72×72px |
xhdpi |
240dp~320dp |
96×96px |
xxhdpi |
320dp~480dp |
144×144px |
xxxhdpi |
480dp~640dp |
192×192px |
以 720*1080 5英寸为例:
(720^2 + 1080^2)开方=260
放在xhdpi中。
本题中同理可以算得 293,还是xhdpi中。
15.
6.0系统新权限机制的解决方案。
这个。。。没什么好说的,真正了解的很好说,不了解的话就有点绕。
?你们精通的开源框架,问题来了
写各种精通其实是可以的,要么真牛x,如果不是很牛x那就在最后加上一条精通----精通各种被打脸。
16.
EventBus的机制是什么?和Handler的区别怎样?
EventBus是采用观察者模式实现的事件订阅总线,可以用在应用程序中,组件之间,线程之间的通信,并且由于事件可以是任意类型的对象,所以使用起来更加的方便快捷。
Handler是 Android 的消息机制,集中解决线程间通信问题。
17.
RxJava的机制是什么?
RxJava是使用Java语言,以响应式编程思维来进行编程的Java类库。参考ReactiveX。
18.
Butterknife的机制是什么?
Java Annotation Processing技术,在Java代码编译成Java字节码的时候就已经处理了@Bind、@OnClick(ButterKnife还支持很多其他的注解)这些注解了。
Annotation
processing 是javac中用于编译时扫描和解析Java注解的工具
Annotation processing是在编译阶段执行的,它的原理就是读入Java源代码,解析注解,然后生成新的Java代码。新生成的Java代码最后被编译成Java字节码,注解解析器(Annotation Processor)不能改变读入的Java
类,比如不能加入或删除Java方法。
参考:ButterKnife框架原理
19.
Okhttp是基于HTTP连接还是Socket连接?
基于Http的。
20.
例举一种ORM框架,说说它的优缺点。
我熟悉的两种GreenDao3和AndroidActive,GreenDao 比较常规,注解不多(我这里都是指3.0版本后,之前的版本在生存实体的时候略显麻烦。),AndroidActive 相对而言注解较多,最后的综合性能上 GreenDao 排第一毫无争议。硬要说缺点的话就是 GreenDao 体积稍大。
安卓面试题 Android interview questions的更多相关文章
-
[译]Node.js Interview Questions and Answers (2017 Edition)
原文 Node.js Interview Questions for 2017 什么是error-first callback? 如何避免无止境的callback? 什么是Promises? 用什么工 ...
-
WCF学习系列二---【WCF Interview Questions – Part 2 翻译系列】
http://www.topwcftutorials.net/2012/09/wcf-faqs-part2.html WCF Interview Questions – Part 2 This WCF ...
-
WCF学习系列三--【WCF Interview Questions – Part 3 翻译系列】
http://www.topwcftutorials.net/2012/10/wcf-faqs-part3.html WCF Interview Questions – Part 3 This WCF ...
-
WCF学习系列四--【WCF Interview Questions – Part 4 翻译系列】
WCF Interview Questions – Part 4 This WCF service tutorial is part-4 in series of WCF Interview Qu ...
-
[转]Design Pattern Interview Questions - Part 4
Bridge Pattern, Composite Pattern, Decorator Pattern, Facade Pattern, COR Pattern, Proxy Pattern, te ...
-
[转]Design Pattern Interview Questions - Part 2
Interpeter , Iterator , Mediator , Memento and Observer design patterns. (I) what is Interpreter pat ...
-
[转]Design Pattern Interview Questions - Part 3
State, Stratergy, Visitor Adapter and fly weight design pattern from interview perspective. (I) Can ...
-
[转]Design Pattern Interview Questions - Part 1
Factory, Abstract factory, prototype pattern (B) What are design patterns? (A) Can you explain facto ...
-
101+ Manual and Automation Software Testing Interview Questions and Answers
101+ Manual and Automation Software Testing Interview Questions and Answers http://www.softwaretesti ...
随机推荐
-
SIP学习(实例详解)
本文摘自:http://blog.chinaunix.net/uid-20655530-id-1589483.html 学习 SIP 协议最快捷的方法是通过范例来学习, 找到了一个完整的呼叫流程,le ...
-
CentOS 7 yum nginx MySQL PHP 简易环境搭建
用centos自带的yum源来安装nginx,mysql和php,超级方便,省去编译的麻烦,省去自己配置的麻烦,还能节省非常多的时间. 我们先把yum源换成国内的阿里云镜像源(当然不换也可以),先备份 ...
-
C#中string,char[],byte[]互相转换
string 转换成 Char[] string ss = "我爱你,中国"; char[] cc = ss.ToCharArray(); Char[] 转换成string str ...
-
201521123026《Java程序设》 第10周学习总结
1. 本章学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容. 1.守护线程:setDaemon(true or false),如果所有前台线程死亡,守护线程自动结束,一般 ...
-
BootStrap Table使用小结
1.在当前表格的最后新增数据 $("#data_module_table").bootstrapTable('append', data.data);//data.data---- ...
-
MYSQL Optimizing LIMIT Queries
如果要指定查询的数据行数,在查询语句中使用limit子句,而不是获取所有数据行结果集,然后去掉没用的数据. MYSQL有时会对没有having子句,带有limit关键字的查询进行优化: 1:如果用li ...
-
sqlserver常用存储过程基本语法
一.定义变量--简单赋值 declare @a intset @a=5 print @a --使用select语句赋值 declare @user1 nvarchar(50) select @user ...
-
CSS 背景图像 填充整个页面示例
background-image 属性可以设置背景图像. 背景图像可以填充整个页面的,也可以填写一部分. background-image 属性的使用很简单:background-image:url( ...
-
JAVA记录-java代码优化策略
java代码优化策略 1.生成对象时,合理分配空间和大小:new ArrayList(100); 2.优化for循环: Vector vect = new Vector(1000); For(int ...
-
Android中px, ppi, dpi, dp, dip, sp概念解析
Android中px, ppi, dpi, dp, dip, sp概念解析