前几天整理了Java面试题集合,今天再来整理下Android相关的面试题集合.假设你希望能得到最新的消息,能够关注https://github.com/closedevice/interview-about,我会不断的添加和修正相关问题的描写叙述.

基础

谈谈Activity的生命周期

介绍不同场景下Activity生命周期的变化过程

  • 启动Activity: onCreate()—>onStart()—>onResume(),Activity进入运行状态。
  • Activity退居后台: 当前Activity转到新的Activity界面或按Home键回到主屏: onPause()—>onStop(),进入停滞状态。
  • Activity返回前台: onRestart()—>onStart()—>onResume()。再次回到运行状态。

  • Activity退居后台。且系统内存不足。 系统会杀死这个后台状态的Activity。若再次回到这个Activity,则会走onCreate()–>onStart()—>onResume()
  • 锁定屏与解锁屏幕 仅仅会调用onPause()。而不会调用onStop方法,开屏后则调用onResume()

Activity销毁但Task假设没有销毁掉,当Activity重新启动时这个AsyncTask该怎样解决?

还是屏幕旋转这个样例,在重建Activity的时候,会回调

Activity.onRetainNonConfigurationInstance()又一次传递一个新的对象给AsyncTask。完毕引用的更新

Asynctask为什么要设置为仅仅能够一次任务

考虑到线程安全问题

若Activity已经销毁,此时AsynTask运行完并返回结果,会报异常么?

当一个App旋转时,整个Activity会被销毁和重建。当Activity重新启动时,AsyncTask中对该Activity的引用是无效的,因此onPostExecute()就不会起作用,若AsynTask正在运行,折会报 view not attached to window manager 异常

同样也是生命周期的问题。在 Activity 的onDestory()方法中调用Asyntask.cancal方法。让二者的生命周期同步

内存不足时,系统会杀死后台的Activity,假设须要进行一些暂时状态的保存,在哪个方法进行

Activity的 onSaveInstanceState() 和 onRestoreInstanceState()并非生命周期方法,不同于 onCreate()、onPause()等生命周期方法,它们并不一定会被触发。当应用遇到意外情况(如:内存不足、用户直接按Home键)由系统销毁一个Activity。onSaveInstanceState() 会被调用。

可是当用户主动去销毁一个Activity时,比如在应用中按返回键,onSaveInstanceState()就不会被调用。除非该activity是被用户主动销毁的,通常onSaveInstanceState()仅仅适合用于保存一些暂时性的状态,而onPause()适合用于数据的持久化保存。

介绍Activity 四中launchMode:

  • standard
  • singleTop
  • singleTask
  • singleInstance

我们能够在AndroidManifest.xml配置的android:launchMode属性为以上四种之中的一个。

1. standard standard模式是默认的启动模式,不用为配置android:launchMode属性就可以,当然也能够指定值为standard。

standard启动模式,无论有没有已存在的实例,都生成新的实例。

2. singleTop 我们在上面的基础上为指定属性android:launchMode=”singleTop”,系统就会依照singleTop启动模式处理跳转行为。

跳转时系统会先在栈结构中寻找是否有一个Activity实例正位于栈顶。假设有则不再生成新的,而是直接使用。假设系统发现存在有Activity实例,但不是位于栈顶,又一次生成一个实例。 这就是singleTop启动模式,假设发现有对应的Activity实例正位于栈顶。则反复利用,不再生成新的实例。

3. singleTask 假设发现有对应的Activity实例。则使此Activity实例之上的其它Activity实例统统出栈。使此Activity实例成为栈顶对象。显示到幕前。

4. singleInstance 这样的启动模式比較特殊,由于它会启用一个新的栈结构,将Acitvity放置于这个新的栈结构中,并保证不再有其它Activity实例进入。

LaunchMode使用场景

  1. singleTop适合接收通知启动的内容显示页面。

    比如,某个新闻client的新闻内容页面,假设收到10个新闻推送,每次都打开一个新闻内容页面是非常烦人的。

  2. singleTask适合作为程序入口点。

    比如浏览器的主界面。无论从多少个应用启动浏览器,仅仅会启动主界面一次,其余情况都会走onNewIntent,而且会清空主界面上面的其它页面。
  3. singleInstance应用场景:

    闹铃的响铃界面。

    你以前设置了一个闹铃:上午6点。在上午5点58分,你启动了闹铃设置界面,并按 Home 键回桌面;在上午5点59分时,你在微信和朋友聊天;在6点时。闹铃响了,而且弹出了一个对话框形式的 Activity(名为 AlarmAlertActivity) 提示你到6点了(这个 Activity 就是以 SingleInstance 载入模式打开的),你按返回键,回到的是微信的聊天界面,这是由于 AlarmAlertActivity 所在的 Task 的栈仅仅有他一个元素, 因此退出之后这个 Task 的栈空了。

    假设是以 SingleTask 打开 AlarmAlertActivity,那么当闹铃响了的时候,按返回键应该进入闹铃设置界面。

怎样把一个应用设置为系统应用

  1. Android设置是Debug版本号,且root,直接将该apk用adb工具push到system/app或system/priv-app
  2. 假设是非root设备,须要编译后烧写镜像
  3. 有些权限(如WRITE_SECURE_SETTINGS)不开放给第三方应用,仅仅能在对应设备源代码总编译然后作为系统app使用

Activity,Window,View三者的联系和差别?

Activity像一个工匠(控制单元),Window像窗户(承载模型),View像窗花(显示视图) LayoutInflater像剪刀,Xml配置像窗花图纸。

Activity启动Service的两种方式

  1. startService:生命周期和调用者不同.启动后若调用者未调用stopService而直接退出,Service仍会运行
  2. bindService:生命周期与调用者绑定,调用者一旦退出,Service就会调用unBind->onDestory

Android两个应用能在同一个任务栈吗?

栈一般以包名命名,两个应用的签名和udid要同样

Fragment是什么?你以前遇到哪些有关Fragment的问题?

Fragment能够作为Activity界面的一部分组成出现.一个Activity中能够同一时候出现多个Fragment,并一个Fragment也能够在多个Activity中使用.

在Activity中能够加入,删除,替换Fragment.Fragment能够响应自己的输入时间,而且有自己的生命周期,但其生命周期收Activity影响.

Fragment生命周期

怎样实现Activity窗体高速变暗

      * @param from\>=0&&from\<=1.0f
* @param to\>=0&&to\<=1.0f
*
* */
private void dimBackground(final float from, final float to) {
final Window window = getWindow();
ValueAnimator valueAnimator = ValueAnimator.ofFloat(from, to);
valueAnimator.setDuration(500);
valueAnimator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
WindowManager.LayoutParams params = window.getAttributes();
params.alpha = (Float) animation.getAnimatedValue();
window.setAttributes(params);
}
}); valueAnimator.start();
}

Fragment重叠问题

是否使用过本地广播,和全局广播有什么差别?

本地广播在本应用范围内传播,不用操心隐私数据泄露,不用操心别的应用伪造广播.相比全局广播,本地广播更高效.

注冊广播的几种方法?

1.静态注冊:在清单文件里注冊, 常见的有监听设备启动,常驻注冊不会随程序生命周期改变

2.动态注冊:在代码中注冊。随着程序的结束。也就停止接受广播了

补充一点:有些广播仅仅能通过动态方式注冊,比方时间变化事件、屏幕亮灭事件、电量变更事件,由于这些事件触发频率通常非常高。假设同意后台监听。会导致进程频繁创建和销毁。从而影响系统总体性能

为什么Android引入广播机制?

a:从MVC的角度考虑(应用程序内) 事实上回答这个问题的时候还能够这样问,android为什么要有那4大组件,如今的移动开发模型基本上也是照搬的web那一套MVC架构。仅仅只是是改了点嫁妆而已。android的四大组件本质上就是为了实现移动或者说嵌入式设备上的MVC架构,它们之间有时候是一种相互依存的关系,有时候又是一种补充关系。引入广播机制能够方便几大组件的信息和数据交互。

b:程序间互通消息(比如在自己的应用程序内监听系统来电)

c:效率上(參考UDP的广播协议在局域网的方便性)

d:设计模式上(反转控制的一种应用。相似监听者模式)

BroadCastReceiver的安全性问题

详细參见:[http://blog.csdn.net/t12x3456/article/details/9256609]

了解IntentServices吗?

IntentService是Service的子类。是一个异步的。会自己主动停止的服务,非常好攻克了传统的Service中处理完耗时操作忘记停止并销毁Service的问题

生成一个默认的且与线程相互独立的工作线程运行全部发送到onStartCommand()方法的Intent,能够在onHandleIntent()中处理.

串行队列,每次仅仅运行一个任务,不存在线程安全问题,全部任务运行完后自己主动停止服务,不须要自己手动调用stopSelf()来停止.

Service的onCreate运行在哪个线程中?

UI线程

提升Service进程优先级

在AndroidManifest.xml文件里对于intent-filter能够通过android:priority = “1000”这个属性设置最高优先级,1000是最高值。假设数字越小则优先级越低。同一时候适用于广播。

介绍Android下的数据存储方式

  1. SharedPreference
  2. 内部存储
  3. 外部存储
  4. SQLite
  5. 网络存储

ContentProvider是怎样实现数据共享

当一个应用程序须要把自己的数据暴露给其它程序使用时,该就用程序就可通过提供ContentProvider来实现;其它应用程序就可通过ContentResolver来操作ContentProvider暴露的数据。 一旦某个应用程序通过ContentProvider暴露了自己的数据操作接口,那么无论该应用程序是否启动,其它应用程序都能够通过该接口来操作该应用程序的内部数据,包含添加数据、删除数据、改动数据、查询数据等。

ContentProvider以某种Uri的形式对外提供数据,同意其它应用訪问或改动数据;其它应用程序使用ContentResolver依据Uri去訪问操作指定数据。 步骤:

1. 定义自己的ContentProvider类,该类须要继承Android提供的ContentProvider基类。

2. 在AndroidManifest.xml文件里注冊个ContentProvider,注冊ContenProvider时须要为它绑定一个URL。

例: android:authorities=”com.myit.providers.MyProvider” /> 说明:authorities就相当于为该ContentProvider指定URL。 注冊后。其它应用程序就能够通过该Uri来訪问MyProvider所暴露的数据了。

3. 接下来,使用ContentResolver操作数据,Context提供了例如以下方法来获取ContentResolver对象。 一般来说。ContentProvider是单例模式,当多个应用程序通过ContentResolver来操作 ContentProvider提供的数据时,ContentResolver调用的数据操作将会托付给同一个ContentProvider处理。 使用ContentResolver操作数据仅仅需两步: 1、调用Activity的ContentResolver获取ContentResolver对象。 2、依据须要调用ContentResolver的insert()、delete()、update()和query()方法操作数据就可以

ContentProvider和sql的差别

ContentProvider的主要还是用于数据共享,其能够对Sqlite,SharePreferences。File等进行数据操作用来共享数据。

而sql的能够理解为数据库的一门语言,能够使用它完毕CRUD等一系列的操作

数据存储相关

  • 文件存储: 通过java.io.FileInputStream和java.io.FileOutputStream这两个类来实现对文件的读写,java.io.File类则用来构造一个详细指向某个文件或者文件夹的对象。

  • SharedPreferences: SharedPreferences是一种轻量级的数据存储机制,他将一些简单的数据类型的数据。包含boolean类型,int类型。float类型,long类型以及String类型的数据,以键值对的形式存储在应用程序的私有Preferences文件夹(/data/data/<包名>/shared_prefs/)中。这样的Preferences机制广泛应用于存储应用程序中的配置信息。

  • SQLite数据库: 当应用程序须要处理的数据量比較大时,为了更加合理地存储、管理、查询数据。我们往往使用关系数据库来存储数据。Android系统的非常多用户数据,如联系人信息,通话记录,短信息等,都是存储在SQLite数据库其中的,所以利用操作SQLite数据库的API能够同样方便的訪问和改动这些数据。

  • ContentProvider: 主要用于在不同的应用程序之间实现数据共享的功能,不同于sharepreference和文件存储中的两种全局可读写操作模式,内容提供其能够选择仅仅对哪一部分数据进行共享。从而保证我们程序中的隐私数据不会有泄漏的风险

怎样导入外部数据库?

怎样将打开res aw文件夹中的数据库文件?

在Android中不能直接打开res aw文件夹中的数据库文件,而须要在程序第一次启动时将该文件拷贝到手机内存或SD卡的某个文件夹中。然后再打开该数据库文件。

复制的基本方法是使用getResources().openRawResource方法获得res aw文件夹中资源的 InputStream对象,然后将该InputStream对象中的数据写入其它的文件夹中对应文件里。在Android SDK中能够使用SQLiteDatabase.openOrCreateDatabase方法来打开随意文件夹中的SQLite数据库文件。

一条最长的短信息约占多少byte?

中文70(包含标点),英文160。160个字节。

Context与ApplicationContext的差别,

Application的Context是一个全局静态变量,SDK的说明是仅仅有当你引用这个context的生命周期超过了当前activity的生命周期,而和整个应用的生命周期挂钩时,才去使用这个application的context。

在android中context能够作非常多操作。可是最基本的功能是载入和訪问资源。在android中有两种context,一种是 application context。一种是activity context。通常我们在各种类和方法间传递的是activity context。

什么是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能够。

SQLite支持事务吗?

加入删除怎样提高性能?

SQLite作为轻量级的数据库,比MySQL还小,但支持SQL语句查询,提高性能能够考虑通过原始经过优化的SQL查询语句方式处理

SQLite优化

參考:[http://www.cnblogs.com/devinzhang/archive/2012/01/16/2323949.html]

怎样将SQLite数据库(dictionary.db文件)与apk文件一起公布?

能够将dictionary.db文件拷贝到Eclipse Android工程中的res aw文件夹中。全部在res aw文件夹中的文件不会被压缩,这样能够直接提取该文件夹中的文件。能够将dictionary.db文件拷贝到res aw文件夹中

Webview中的漏洞

[http://jiajixin.cn/2014/09/16/webview-js-safety/]

Service和Activity通信

  1. 通过Binder
  2. 通过broadcast

怎样保证Service在后台不被kill

  1. Service设置成START_STICKY kill 后会被重新启动(等待5秒左右),重传Intent,保持与重新启动前一样

  2. 通过 startForeground将进程设置为前台进程, 做前台服务,优先级和前台应用一个级别​。除非在系统内存非常缺。否则此进程不会被 kill

  3. 双进程Service: 让2个进程互相保护**。其中一个Service被清理后。另外没被清理的进程能够马上重新启动进程

  4. QQ黑科技: 在应用退到后台后,另起一个仅仅有 1 像素的页面停留在桌面上。让自己保持前台状态,保护自己不被后台清理工具杀死

  5. 在已经root的设备下,改动对应的权限文件,将App伪装成系统级的应用 Android4.0系列的一个漏洞。已经确认可行

  6. 用C编写守护进程(即子进程) : Android系统中当前进程(Process)fork出来的子进程。被系统觉得是两个不同的进程。

    当父进程被杀死的时候。子进程仍然能够存活,并不受影响。鉴于眼下提到的在Android->- Service层做双守护都会失败,我们能够fork出c进程。多进程守护。

    死循环在那检查是否还存在,详细的思路例如以下(Android5.0以上的版本号不可行)

  7. 用C编写守护进程(即子进程),守护进程做的事情就是循环检查目标进程是否存在,不存在则启动它。

  8. 在NDK环境中将1中编写的C代码编译打包成可运行文件(BUILD_EXECUTABLE)。主进程启动时将守护进程放入私有文件夹下。赋予可运行权限,启动它就可以。

  9. 联系厂商。加入白名单

谈谈你对Android中Context的理解

參考:[http://blog.csdn.net/qinjuning/article/details/7310620]

RemoteView的应用

widget和Notification中

Android中怎样获得手机的唯一标示.

1 首先尝试读取IMEI、Mac地址、CPU号等物理信息(有不少工具能够改动IMEI);

2 假设均失败,能够自己生成UUID然后保存到文件(文件也可能被篡改或删除)

參考:[http://blog.csdn.net/xushuaic/article/details/25077179]

Android应用中验证码登录都有哪些实现方案

验证码应该仅仅有两种获取方式: 从server端获取图片, 通过短信服务,将验证码发送给client这两种

为什么要设计Bundle而不是直接使用Map?

Map里实现了Serializable接口,而在Bundle实现了Parcelable的接口

Bundle 父类 BaseBundle内部确实有个 ArrayMap

Android中XML解析方式的比較急优缺点

DOM,SAX,Pull解析。

SAX解析器的优点是解析速度快。占用内存少;

DOM在内存中以树形结构存放,因此检索和更新效率会更高。

可是对于特别大的文档。解析和载入整个文档将会非常耗资源,不适合移动端;

PULL解析器的运行方式和SAX相似。都是基于事件的模式。PULL解析器小巧轻便。解析速度快,简单易用。非常适合在Android移动设备中使用。Android系统内部在解析各种XML时也是用PULL解析器。


布局相关

LinearLayout和RelativeLayout性能对照

1 RelativeLayout会让子View调用2次onMeasure。LinearLayout 在有weight时。也会调用子View2次onMeasure

2 RelativeLayout的子View假设高度和RelativeLayout不同,则会引发效率问题,当子View非常复杂时。这个问题会更加严重。假设能够。尽量使用padding取代margin。

3 在不影响层级深度的情况下,使用LinearLayout和FrameLayout而不是RelativeLayout。

最后再思考一下文章开头那个矛盾的问题。为什么Google给开发人员默认新建了个RelativeLayout。而自己却在DecorView中用了个LinearLayout。由于DecorView的层级深度是已知而且固定的,上面一个标题栏,以下一个内容栏。採用RelativeLayout并不会降低层级深度,所以此时在根节点上用LinearLayout是效率最高的。

而之所以给开发人员默认新建了个RelativeLayout是希望开发人员能採用尽量少的View层级来表达布局以实现性能最优。由于复杂的View嵌套对性能的影响会更大一些。

屏幕适配相关

dp, dip, dpi, px, sp是什么意思以及他们的换算公式?layout-sw400dp, layout-h400dp分别代表什么意思

布局优化

  • 避免OverDraw过渡绘制
  • 优化布局层级
  • 避免嵌套过多无用布局
  • 当我们在画布局的时候,假设能实现同样的功能。优先考虑相对布局。然后在考虑别的布局,不要用绝对布局。

  • 使用<include />标签把复杂的界面须要抽取出来
  • 使用<merge />标签,由于它在优化UI结构时起到非常关键的数据。

    目的是通过删减多余或者额外的层级。从而优化整个Android Layout的结构。核心功能就是降低冗余的层次从而达到优化UI的目的!

  • ViewStub 是一个隐藏的。不占用内存空间的视图对象。它能够在运行时延迟载入布局资源文件。

mipmap文件夹和drawable文件夹的差别

它仅仅是用来放启动图标的,优点就是,你仅仅用放一个mipmap图标。它就会给你各种版本号(比方平板,手机)的apk自己主动生成对应分辨率的图标。以节约空间。

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。

怎样实现一个局部更新的ListView

怎样实现ListView多种布局

ViewHolder为什么要被声明成静态内部类

这个是考静态内部类和非静态内部类的主要差别之中的一个。

非静态内部类会隐式持有外部类的引用,就像大家常常将自己定义的adapter在Activity类里,然后在adapter类里面是能够随意调用外部activity的方法的。

当你将内部类定义为static时,你就调用不了外部类的实例方法了,由于这时候静态内部类是不持有外部类的引用的。声明ViewHolder静态内部类,能够将ViewHolder和外部类解引用。大家会说一般ViewHolder都非常简单,不定义为static也没事吧。确实如此,可是假设你将它定义为static的。说明你懂这些含义。万一有一天你在这个ViewHolder加入一些复杂逻辑。做了一些耗时工作,那么假设ViewHolder是非静态内部类的话。就非常easy出现内存泄露。假设是静态的话,你就不能直接引用外部类,迫使你关注怎样避免相互引用。 所以将 ViewHolder内部类 定义为静态的,是一种好习惯


进程,线程

有哪些进程通信的方式?

  1. Intent
  2. Binder(AIDL
  3. Messenger
  4. BroadcastReceiver

AIDL是什么?

AIDL全程是Android Interface Definition Language,用于生成两个进程之间通信(IPC)的代码.

AIDL 体现了哪些设计思想

代理

Binder机制

非常多人吧Binder的原理解释的非常复杂,让人看着就头大,可是熟悉Linux开发的小伙伴能够一下想到Binder驱动本质就是文件,实现採用了代理而已.详细看下图:

简单的说说Handler机制

  • Handler通过调用sendmessage方法把消息放在消息队列MessageQueue中。Looper负责把消息从消息队列中取出来,又一次再交给Handler进行处理,三者形成一个循环
  • 通过构建一个消息队列,把全部的Message进行统一的管理。当Message不用了,并不作为垃圾回收。而是放入消息队列中。供下次handler创建消息时候使用,提高了消息对象的复用,降低系统垃圾回收的次数
  • 每一个线程,都会单独对应的一个looper,这个looper通过ThreadLocal来创建。保证每一个线程仅仅创建一个looper,looper初始化后就会调用looper.loop创建一个MessageQueue,这种方法在UI线程初始化的时候就会完毕,我们不须要手动创建

动画相关

Android中的动画有哪些?

  • 逐帧动画(Drawable Animation): 载入一系列Drawable资源来创建动画。简单来说就是播放一系列的图片来实现动画效果,能够自己定义每张图片的持续时间

  • 补间动画(Tween Animation): Tween能够对View对象实现一系列简单的动画效果,比方位移,缩放,旋转。透明度等等。可是它并不会改变View属性的值。仅仅是改变了View的绘制的位置,比方,一个button在动画过后。不在原来的位置。可是触发点击事件的仍然是原来的坐标。

  • 属性动画(Property Animation): 动画的对象除了传统的View对象。还能够是Object对象,动画结束后。Object对象的属性值被实实在在的改变了

Android动画原理

Animation框架定义了透明度。旋转,缩放和位移几种常见的动画,而且控制的是整个View,实现原理是每次绘制视图时View所在的ViewGroup中的drawChild函数获取该View的Animation的Transformation值,然后调用canvas.concat(transformToApply.getMatrix())。通过矩阵运算完毕动画帧,假设动画没有完毕,继续调用invalidate()函数,启动下次绘制来驱动动画,动画过程中的帧之间间隙时间是绘制函数所消耗的时间,可能会导致动画消耗比較多的CPU资源,最重要的是,动画改变的仅仅是显示。并不能对应事件

Android属性动画特性

假设你的需求中仅仅须要对View进行移动、缩放、旋转和淡入淡出操作。那么补间动画确实已经足够健全了。可是非常显然,这些功能是不足以覆盖全部的场景的,一旦我们的需求超出了移动、缩放、旋转和淡入淡出这四种对View的操作。那么补间动画就不能再帮我们忙了。也就是说它在功能和可扩展方面都有相当大的局限性,那么以下我们就来看看补间动画所不能胜任的场景。

注意上面我在介绍补间动画的时候都有使用“对View进行操作”这样的描写叙述,没错,补间动画是仅仅能够作用在View上的。也就是说,我们能够对一个Button、TextView、甚至是LinearLayout、或者其它不论什么继承自View的组件进行动画操作,可是假设我们想要对一个非View的对象进行动画操作,抱歉,补间动画就帮不上忙了。可能有的朋友会感到不能理解,我怎么会须要对一个非View的对象进行动画操作呢?这里我举一个简单的样例。比方说我们有一个自己定义的View,在这个View其中有一个Point对象用于管理坐标,然后在onDraw()方法其中就是依据这个Point对象的坐标值来进行绘制的。也就是说。假设我们能够对Point对象进行动画操作,那么整个自己定义View的动画效果就有了。显然。补间动画是不具备这个功能的,这是它的第一个缺陷。

然后补间动画另一个缺陷,就是它仅仅能够实现移动、缩放、旋转和淡入淡出这四种动画操作。那假设我们希望能够对View的背景色进行动态地改变呢?非常遗憾。我们仅仅能靠自己去实现了。说白了。之前的补间动画机制就是使用硬编码的方式来完毕的。功能限定死就是这些,基本上没有不论什么扩展性可言。

最后,补间动画另一个致命的缺陷,就是它仅仅是改变了View的显示效果而已,而不会真正去改变View的属性。什么意思呢?比方说。如今屏幕的左上角有一个button,然后我们通过补间动画将它移动到了屏幕的右下角,如今你能够去尝试点击一下这个button,点击事件是绝对不会触发的。由于实际上这个button还是停留在屏幕的左上角,仅仅只是补间动画将这个button绘制到了屏幕的右下角而已。


View绘制相关

SurfaceView和View的差别

SurfaceView中採用了双缓存技术,在单独的线程中更新界面

View在UI线程中更新界面

介绍下自己定义view的基本流程

  1. 明白需求,确定你想实现的效果
  2. 确定是使用组合控件的形式还是全新自己定义的形式,组合控件即使用多个系统控件来合成一个新控件,你比方titilebar,这样的形式相对简单,參考
  3. 假设是全然自己定义一个view的话,你首先须要考虑继承哪个类,是View呢,还是ImageView等子类。
  4. 依据须要去复写View#onDraw、View#onMeasure、View#onLayout方法
  5. 依据须要去复写dispatchTouchEvent、onTouchEvent方法
  6. 依据须要为你的自己定义view提供自己定义属性。即编写attr.xml,然后在代码中通过TypedArray等类获取到自己定义属性值 7.须要处理滑动冲突、像素转换等问题

谈谈View的绘制流程



measure()方法,layout(),draw()三个方法主要存放了一些标识符。来推断每一个View是否须要再又一次測量。布局或者绘制。基本的绘制过程还是在onMeasure,onLayout,onDraw这个三个方法中

1.onMesarue() 为整个View树计算实际的大小,即设置实际的高(对应属性:mMeasuredHeight)和宽(对应属性: mMeasureWidth),每一个View的控件的实际宽高都是由父视图和本身视图决定的。

2.onLayout() 为将整个依据子视图的大小以及布局參数将View树放到合适的位置上。

3. onDraw() 開始绘制图像,绘制的流程例如以下

  1. 首先绘制该View的背景
  2. 调用onDraw()方法绘制视图本身 (每一个View都须要重载该方法,ViewGroup不须要实现该方法)
  3. 假设该View是ViewGroup,调用dispatchDraw ()方法绘制子视图
  4. 绘制滚动栏

自己定义View运行invalidate()方法,为什么有时候不会回调onDraw()

  1. 自己定义一个view时,重写onDraw。

    调用view.invalidate(),会触发onDraw和computeScroll()。前提是该view被附加在当前窗体.

    view.postInvalidate(); //是在非UI线程上调用的

  2. 自己定义一个ViewGroup。重写onDraw。

    onDraw可能不会被调用,原因是须要先设置一个背景(颜色或图)。表示这个group有东西须要绘制了。才会触发draw,之后是onDraw。因此,一般直接重写dispatchDraw来绘制viewGroup.自己定义一个ViewGroup,dispatchDraw会调用drawChild.

怎样实现一个字体的描边与阴影效果


事件传递机制

谈谈touch事件的传递流程



1. 全部Touch事件都被封装成了MotionEvent对象。包含Touch的位置、时间、历史记录以及第几个手指(多指触摸)等。

2. 事件类型分为ACTION_DOWN, ACTION_UP, ACTION_MOVE, ACTION_POINTER_DOWN, ACTION_POINTER_UP, ACTION_CANCEL,每一个事件都是以ACTION_DOWN開始ACTION_UP结束。

3. 对事件的处理包含三类,分别为传递——dispatchTouchEvent()函数、拦截——onInterceptTouchEvent()函数、消费——onTouchEvent()函数和OnTouchListener()

简单来说:

  1. 事件从Activity.dispatchTouchEvent()開始传递,仅仅要没有被停止或拦截,从最上层的View(ViewGroup)開始一直往下(子View)传递。

    子View能够通过onTouchEvent()对事件进行处理。

  2. 事件由父View(ViewGroup)传递给子View,ViewGroup能够通过onInterceptTouchEvent()对事件做拦截,停止其往下传递。

  3. 假设事件从上往下传递过程中一直没有被停止。且最底层子View没有消费事件,事件会反向往上传递,这时父View(ViewGroup)能够进行消费,假设还是没有被消费的话,最后会到Activity的onTouchEvent()函数。

  4. 假设View没有对ACTION_DOWN进行消费,之后的其它事件不会传递过来。

  5. OnTouchListener优先于onTouchEvent()对事件进行消费。

    上面的消费即表示对应函数返回值为true。

View中setOnTouchListener中的onTouch,onTouchEvent,onClick的运行顺序

onTouch优于onTouchEvent,onTouchEvent优于onClick

Android下滑冲突的常见解决思路

相关的滑动组件 重写onInterceptTouchEvent,然后推断依据xy值。来决定是否要拦截当前操作


高效使用Bitmap

谈谈你对Bitmap的理解,以及什么时候该bitmap.recycle()

Bitmap是android中常常使用的一个类,它代表了一个图片资源。

Bitmap消耗内存非常严重,假设不注意优化代码,常常会出现OOM问题,优化方式通常有这么几种: 1. 使用缓存; 2. 压缩图片; 3. 及时回收。

至于什么时候须要手动调用recycle,这就看详细场景了,原则是当我们不再使用Bitmap时。须要回收。

另外,我们须要注意,2.3之前Bitmap对象与像素数据是分开存放的。Bitmap对象存在java Heap中而像素数据存放在Native Memory中,这时非常有必要调用recycle回收内存。可是2.3之后,Bitmap对象和像素数据都是存在Heap中,GC能够回收其内存。


反射相关

什么时候会用到反射?

JAVA反射机制是在#运行时#,对于随意一个类。都能够知道这个类的全部属性和方法;对于随意一个对象,都能够调用它的随意一个方法;这样的动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

Java反射机制主要提供了以下功能: a)在运行时推断随意一个对象所属的类; b)在运行时构造随意一个类的对象; c)在运行时推断随意一个类所具有的成员变量和方法。 d)在运行时调用随意一个对象的方法。生成动态代理。

你以前利用反射做过什么?


JNI系列

NDK是什么?

NDK是一些列工具的集合。

NDK提供了一系列的工具,帮助开发人员迅速的开发C/C++的动态库,并能自己主动将so和java 应用打成apk包。

NDK集成了交叉编译器。并提供了对应的mk文件和隔离cpu、平台等的差异。开发人员仅仅需简单的改动mk文件就能够创建出so

Android ndk主要在哪些场景下使用?有啥坑?

  1. 加密
  2. 音视频解码
  3. 图像操作
  4. 安全相关,比方hookt
  5. 增量更新
  6. 游戏开发

NDK开发须要注意什么?

[https://developer.android.com/training/articles/perf-jni.html]

使用JNI的流程?

  1. JAVA中声明native 方法如private native String printJNI(String inputStr);
  2. 使用javah工具生成.h头文件这时候头文件里就会自己主动生成对应的函数JNIEXPORT jstring JNICALL Java_com_wenming_HelloWorld_printJNI
  3. 实现JNI原生函数源文件。新建HelloWorld.c文件,对刚才自己主动生成的函数进行详细的逻辑书写,比如返回一个java叫做HelloWorld的字符串等
  4. 编译生成动态链接so文件**
  5. Java中调用Sysytem.load方法把刚才的so库载入进来。就能够调用native方法了

怎样通过JNI传递String对象

Java的String和C++的string是不能对等起来的,所以当我们拿到.h文件以下的jstring对象,会做一次转换我们把jstring转换为C以下的char*类型。 获取值



constchar* str;

str = env->GetStringUTFChars(prompt,false);



赋予值



char* tmpstr ="return string succeeded";

jstring rtstr = env->NewStringUTF(tmpstr);


网络优化

移动端获取数据优化的几个点

  1. 连接复用 :

    节省连接建立时间,如开启 keep-alive。

    对于 Android 来说默认情况下 HttpURLConnection 和 HttpClient 都开启了 keep-alive。仅仅是 2.2 之前 HttpURLConnection 存在影响连接池的 Bug,详细可见:Android HttpURLConnection 及 HttpClient 选择
  2. 请求合并:

    即将多个请求合并为一个进行请求,比較常见的就是网页中的 CSS Image Sprites。

    假设某个页面内请求过多。也能够考虑做一定的请求合并。

  3. 降低请求数据的大小:

    对于post请求。body能够做gzip压缩的。header也能够作数据压缩(只是仅仅支持http 2.0)。
  4. 返回的数据的body也能够作gzip压缩,body数据体积能够缩小到原来的30%左右。

    (也能够考虑压缩返回的json数据的key数据的体积,尤其是针对返回数据格式变化不大的情况,支付宝聊天返回的数据用到了)

  5. 依据用户的当前的网络质量来推断下载什么质量的图片(电商用的比較多)。

怎样设计一个良好的网络层?

[http://blog.csdn.net/column/details/simple-net.html]

怎样防止反复发送网络请求

点击activity上的一个button,发送网络请求,在网络比較慢的情况下。用户可能会继续去点击button,这个时候,发送其它无谓的请求,不知道大家是怎么处理这类问题来拦截?

HTTP header中加入max-age,这样某个固定的时间内都将返回empty body,当然这种方法是死的,把时间全然限制了,这种方法回掉也会同样要运行多次。

还有个晕招,就是直接设置button的clickable为false,或者使用progressbar。相似于楼主的方法。比方点赞的场景。

使用Map的话,在回掉的时候,还是须要回收HashMap的,维护Map还不如仅仅维护一个boolean呢。

Volley中假设开了缓存的话, 同样的请求同一时候仅仅会有一个去真正的请求, 兴许都走缓存, 尽管不会请求多次, 可是回调是会运行多次的, 和这个需求不match

怎样实现wap联网

參考:[http://blog.csdn.net/asce1885/article/details/7844159]


測试与调试

怎样调试Android应用程序

Debug

Log

Android中常常使用的測试工具?

内存分析:mat,ddms,leakcanary

静态分析:find bugs

压力測试:monkey

自己主动化測试:UIAutomatorMonkeyRunner,Rubotium


内存泄漏/内存溢出相关

内存泄漏问题

  1. 资源对象没有关闭造成,如查询数据库没有关闭游标
  2. 构造Adapter时,没有使用缓存ConvertView
  3. Bitmap对象在不使用时调用recycle()释放内存
  4. context逃逸问题
  5. 注冊没有取消,如动态注冊广播在Activity销毁前没有unregisterReceiver
  6. 集合对象未清理,如无用时没有释放对象的引用
  7. 在Activity中使用非静态的内部类,并开启一个长时间运行的线程,由于内部类持有Activity的引用,会导致Activity本来能够被gc时却长期得不到回收

哪些情况下发生OOM

  • 类的静态变量持有大数据对象 静态变量长期维持到大数据对象的引用,阻止垃圾回收。

  • 非静态内部类存在静态实例 非静态内部类会维持一个到外部类实例的引用,假设非静态内部类的实例是静态的,就会间接长期维持着外部类的引用,阻止被回收掉。

  • 资源对象未关闭 资源性对象比方(Cursor,File文件等)往往都用了一些缓冲,我们在不使用的时候,应该及时关闭它们, 以便它们的缓冲及时回收内存。它们的缓冲不仅存在于java虚拟机内。还存在于java虚拟机外。

    假设我们仅仅是把它的引用设置为null,而不关闭它们,往往会造成内存泄露。 解决的方法: 比方SQLiteCursor(在析构函数finalize(),假设我们没有关闭它。它自己会调close()关闭), 假设我们没有关闭它。系统在回收它时也会关闭它。可是这样的效率太低了。 因此对于资源性对象在不使用的时候。应该调用它的close()函数。将其关闭掉,然后才置为null. 在我们的程序退出时一定要确保我们的资源性对象已经关闭。 程序中常常会进行查询数据库的操作。可是常常会有使用完毕Cursor后没有关闭的情况。

    假设我们的查询结果集比較小, 对内存的消耗不easy被发现。仅仅有在常时间大量操作的情况下才会复现内存问题。这样就会给以后的測试和问题排查带来困难和风险。记得try catch后,在finally方法中关闭连接

  • Handler内存泄漏 Handler作为内部类存在于Activity中,可是Handler生命周期与Activity生命周期往往并非同样的。比方当Handler对象有Message在排队,则无法释放,进而导致本该释放的Acitivity也没有办法进行回收。

    解决的方法

    • 声明handler为static类,这样内部类就不再持有外部类的引用了,就不会堵塞Activity的释放
    • 假设内部类实在须要用到外部类的对象,可在其内部声明一个弱引用引用外部类

一些不良代码习惯 有些代码并不造成内存泄露,可是他们的资源没有得到重用,频繁的申请内存和销毁内存,消耗CPU资源的同一时候,也引起内存抖动 解决方式 假设须要频繁的申请内存对象和和释放对象,能够考虑使用对象池来添加对象的复用。 比如ListView便是採用这样的思想,通过复用converview来避免频繁的GC

怎样排查OOM

參见:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0920/3478.html

怎样避免OOM

1. 使用更加轻量的数据结构 比如,我们能够考虑使用ArrayMap/SparseArray而不是HashMap等传统数据结构。通常的HashMap的实现方式更加消耗内存。由于它须要一个额外的实例对象来记录Mapping操作。

另外。SparseArray更加高效,在于他们避免了对key与value的自己主动装箱(autoboxing)。而且避免了装箱后的解箱。

2. 避免在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里面使用到枚举。

3. 减小Bitmap对象的内存占用 Bitmap是一个极easy消耗内存的大胖子,减小创建出来的Bitmap的内存占用可谓是重中之重。,通常来说有以下2个措施: inSampleSize:缩放比例。在把图片载入内存之前,我们须要先计算出一个合适的缩放比例,避免不必要的大图载入。

decode format:解码格式,选择ARGB_6666/RBG_545/ARGB_4444/ALPHA_6,存在非常大差异

4.Bitmap对象的复用 缩小Bitmap的同一时候。也须要提高BitMap对象的复用率。避免频繁创建BitMap对象,复用的方法有以下2个措施 LRUCache : “近期最少使用算法”在Android中有极其普遍的应用。ListView与GridView等显示大量图片的控件里,就是使用LRU的机制来缓存处理好的Bitmap,把近期最少使用的数据从缓存中移除,保留使用最频繁的数据, inBitMap高级特性:利用inBitmap的高级特性提高Android系统在Bitmap分配与释放运行效率。使用inBitmap属性能够告知Bitmap解码器去尝试使用已经存在的内存区域。新解码的Bitmap会尝试去使用之前那张Bitmap在Heap中所占领的pixel data内存区域,而不是去问内存又一次申请一块区域来存放Bitmap。利用这样的特性,即使是上千张的图片,也仅仅会仅仅仅仅须要占用屏幕所能够显示的图片数量的内存大小

4. 使用更小的图片 在涉及给到资源图片时。我们须要特别留意这张图片是否存在能够压缩的空间,能否够使用更小的图片。尽量使用更小的图片不仅能够降低内存的使用。还能避免出现大量的InflationException。假设有一张非常大的图片被XML文件直接引用,非常有可能在初始化视图时会由于内存不足而发生InflationException,这个问题的根本原因事实上是发生了OOM。

5.StringBuilder 在有些时候,代码中会须要使用到大量的字符串拼接的操作,这样的时候有必要考虑使用StringBuilder来替代频繁的“+”。

4.避免在onDraw方法里面运行对象的创建 相似onDraw等频繁调用的方法,一定须要注意避免在这里做创建对象的操作,由于他会迅速添加内存的使用。而且非常easy引起频繁的gc。甚至是内存抖动。

5. 避免对象的内存泄露 android中内存泄漏的场景以及解决的方法,參考上一问


ANR错误

什么是ANR

ANR全称Application Not Responding。意思就是程序未响应。

假设一个应用无法响应用户的输入,系统就会弹出一个ANR对话框,用户能够自行选择继续等待亦或者是停止当前程序。

一旦出现以下两种情况,则弹出ANR对话框

1. 应用在5秒内未响应用户的输入事件(如按键或者触摸)

2. BroadcastReceiver未在10秒内完毕相关的处理

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)

怎样定位ANR错误

开发机器上,查看/data/anr/traces.text.最新的ANR信息在最開始部分.

怎样避免ANR

避免ANR最核心的一点就是在主线程降低耗时操作.通常须要从以下几个方案下手:

  • 使用子线程处理耗时IO操作。

  • 降低子线程优先级使用Thread或者HandlerThread时,调用Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)设置优先级,否则仍然会降低程序响应,由于默认Thread的优先级和主线程同样。

  • 使用Handler处理子线程结果。而不是使用Thread.wait()或者Thread.sleep()来堵塞主线程。

  • Activity的onCreate和onResume回调中尽量避免耗时的代码

  • BroadcastReceiver中onReceive代码也要尽量降低耗时操作建议使用IntentService处理。IntentService是一个异步的。会自己主动停止的服务。非常好攻克了传统的Service中处理完耗时操作忘记停止并销毁Service的问题


安全相关

本地存储的数据怎么加密好?比方:shared_prefs,sqlite数据,username,password等.假设是aes加密,怎么保存key?

password不要存在本地,一般保存token。最基本的要代码混淆,能够的话加壳,防止反编译


系统相关

Android各版本号API差别

參考:[http://blog.csdn.net/lijun952048910/article/details/7980562]

什么是Dalvik虚拟机

Dalvik虚拟机是Android平台的核心。

它能够支持.dex格式的程序的运行,.dex格式是专为Dalvik设计的一种压缩格式,能够降低总体文件尺寸,提高I/O操作的速度,适合内存和处理器速度有限的系统

Dalvik虚拟机和JVM有什么差别

  • Dalvik 基于寄存器,而 JVM 基于栈。基于寄存器的虚拟机对于更大的程序来说,在它们编译的时候。花费的时间更短。
  • Dalvik运行.dex格式的字节码。而JVM运行.class格式的字节码

Android为每一个应用程序分配的内存大小是多少

通常是16m或者24m,可是能够通过android:largeHeap申请很多其它内存,详细參考:

[https://liuzhichao.com/2016/use-android_largeHeap.html]

[http://www.cnblogs.com/mythou/p/3203536.html]

怎样解决方法数65k问题?

使用Android Studio 的gradle 能够构建MutilDex

Android系统启动流程分析

  1. 打开adb shell 然后运行ps命令。能够看到首先运行的是init方法!找到init.c这个文件.
  2. 然后走init里面的main方法,在这main方法里面运行mkdir进行创建非常多的文件夹。和挂载一些文件夹
  3. 然后回去初始化init.rc这个配置文件!在这个配置文件里面回去启动孵化器这个服务。这个服务会去启动app_process这个文件夹。这个文件夹里面有个app_main.cpp这个文件。
  4. 然后在app_main.cpp这个c文件里面在main方法里面它会去启动安卓的虚拟机。然后安卓虚拟机会去启动os.zygoteinit这个服务!
  5. zygoteinit这是个java代码写的,然后我们找到了main方法,在这种方法里面我们看到他首先设置虚拟机的最小堆内存为5兆,然后走到preloadclasses()这种方法来载入安卓系统全部的2000多个类通过类载入器载入进来,比方activity,contentx,http,…(事实上没有必要一下子全部载入下来,我们能够等用到的时候在载入也能够!

  6. 然后又走preloadresources()这种方法来预载入安卓中定义好的资源比方颜色,图片。系统的id等等。

    。都载入了!(事实上这也是不是必需的! )

  7. 然后又走startSystemServer(),这种方法来载入系统的服务。他会先使用natvieJNI去调用C去初始化界面和声音的服务,这就是我们为什么先听到声音和界面的原因!
  8. 最后等服务载入完毕后也就启动起来了!

总结 linux启动->init进程启动(载入init.rc配置)->zygote启动->systemServer启动,systemServer会通过init1和init2启动navite世界和java世界_

Android面试题集的更多相关文章

  1. Android 面试题集 包含答案

    作者:guoxiaoxing 链接: https://github.com/guoxiaoxing/android-interview 本文基于作者采用的MIT协议分发. 手画一下Android系统架 ...

  2. android面试题集1

    Android 面试题(有详细答案) 附带答案,共100分 一.选择题(30题,每题1.5分,共45分) 1.java.io包中定义了多个流类型来实现输入和输出功能,可以从不同的角度对其进行分类,按功 ...

  3. Android - Android 面试题集

    1.Java部分 1.1 操作系统相关 1.什么是操作系统? 2.什么是线程,什么是进程? 1.2 JDK&JVM&JRE 1.JDK & JVM & JRE分别是什么 ...

  4. android笔试题集2

    1.请谈一下Android系统的架构.答:Android系统采用了分层架构,从高层到低层分别是应用程序层.应用程序框架层.系统运行库层和linux核心层. 2.谈谈android大众常用的五种布局.答 ...

  5. Android - Android 面试题集 -- Android 部分答案

    2.1 Activity1.Activity是什么?Activity是Android的四大组件之一.是用户操作的可视化界面:它为用户提供了一个完成操作指令的窗口.当我们创建完毕Activity之后,需 ...

  6. android面试题总结加强再加强版(一)

    在加强版的基础上又再加强的android应用面试题集 有些补充略显臃肿,只为学习 1.activity的生命周期. 方法 描述 可被杀死 下一个 onCreate() 在activity第一次被创建的 ...

  7. 【Android面试】Android面试题集锦 (陆续更新)(最新2012-6-18) eoe上看到的

    ===============eoeAndroid社区推荐:======================= 1.Android开发新浪面试题[开发者必看哦]下载地址 http://www.eoeand ...

  8. Android面试题整理【转载】

      面试宝典(5)  http://www.apkbus.com/android-115989-1-1.html 面试的几个回答技巧 http://blog.sina.com.cn/s/blog_ad ...

  9. 转:Java面试题集(1-50)

    Java程序员面试题集(1-50) http://blog.csdn.net/jackfrued/article/details/17403101 一.Java基础部分 1.面向对象的特征有哪些方面? ...

随机推荐

  1. vue开发的项目中遇到的警告,报错,配置项目文件等合集(长期更新)

    1. Vue组件里面data()里面没有return时触发错误:Vue components Cannot read property '__ob__' of undefined 这个警告不解决会触发 ...

  2. Npgsql使用入门(三)【批量导入数据】

    Program.cs代码: class Program { static void Main(string[] args) { var test = new PgBulkCopyHelper<S ...

  3. 纯CSS3文字Loading动画特效

    纯CSS3文字Loading动画特效是一款个性的loading文字加载动画. 在线演示本地下载

  4. JAVA基本数据类型转换的注意事项

    JAVA中基本数据类型: 类型: 字节: 范围: 默认值: byte 1 -128~127 0 short 2 -32768~32767 0 char 2 0~65535 '\u0000' int 4 ...

  5. android黑科技系列——微信抢红包插件原理解析和开发实现

    一.前言 自从几年前微信添加抢红包的功能,微信的电商之旅算是正式开始正式火爆起来.但是作为Android开发者来说,我们在抢红包的同时意识到了很多问题,就是手动去抢红包的速度慢了,当然这些有很多原因导 ...

  6. XML 之 命名空间详解

    最近学xml 遇到了点小问题qaq 找了n多的博客大佬,反复看了半小时终于明白了,可能我太蠢了... 基础的知识就不赘述,直接放“栗子”,切重点: <?xml version="1.0 ...

  7. 05《UML大战需求分析》之五

    调研需求的时候,用户会说这个软件要具备怎样的功能,能做什么事情等,这些是功能性的需求.部署图和构件图是用来描述软件架构的,但是我又怀疑软件需求调研也需要确定软件架构吗? 我阅读了一个例子,一个软件公司 ...

  8. (转)基于MVC4+EasyUI的Web开发框架形成之旅--基类控制器CRUD的操作

    http://www.cnblogs.com/wuhuacong/p/3352016.html 在上一篇随笔中,我对Web开发框架的总体界面进行了介绍,其中并提到了我的<Web开发框架>的 ...

  9. SPOJ-CRAN02 - Roommate Agreement(前缀和)

    CRAN02 - Roommate Agreement Leonard was always sickened by how Sheldon considered himself better tha ...

  10. 【转】Oracle 集群】ORACLE DATABASE 11G RAC 知识图文详细教程之ORACLE集群概念和原理(二)

      阅读目录 目录 Oracle集群概念和原理 RAC概述 RAC 集成集群件管理 RAC 的体系结构 RAC 的结构组成和机制 RAC 后台进程 RAC 共享存储 RAC 数据库和单实例数据库的区别 ...