下面是笔者自己最近面试以后总结的一些面试题,以后会一点一点的添加。 题目有点多,送给有缘人! 面试题:有没有用过自定义View? 答:有用过,一般指定View都需要进行这几个步骤,首先可以自定义一些自己的属性,在res/values/attrs.xml里面定义,然后在layout中使用,在View中通过context.obtainStyledAttributes(attrs,R.styleable.自定义属性的名字)进行获取。 然后在测量onMeasure,一般通过他的三个模式(EXACTLY,AT_MODE,,UNSPECIFIED)进行测量,调用setMeasuredDimension进行传入设置的值。 接着如果是ViewGroupt 的话我们还需要设置下子View的位置,一般是通过requestLayout去触发onLayout的方法的。 最后在onDraw里面通过Canvas的一些方法进行绘制。 如果需要进行触摸事件的话,一般需要有实现onTouchEvent事件,注意,如果需要多点触摸,需要实现ACTION_POINTER_DOWN和ACTION_POINTER_UP进行处理。 面试题:layout_weight怎么理解? 答:layout_weight的尺寸分配一般是先满足设置尺寸的分配然后剩下的尺寸在进行比例分配的。如果一个view需要设置1:2的比例显示,可以在LinearLayout中设置weightSum进行设置总的比例,然后在设置子View的比例。 面试题:layout_gravity和gravity的区别? 答:layout_gravity是根据父布局设置位置的,而gravity是根据自身内容设置位置。 面试题:你了解Handler吗?Handler机制是什么? 答:Handler是Android官方给我们提供的一套更新UI线程的机制,也是一套消息处理机制,可以通过Handler来处理消息,更新UI等。 然后Handler机制大约是这样的:首先Handler发送一个消息MessageQueue里面,然后通过Looper的loop方法进行无限循环,如果产生了一个新消息,那么就调用handler的handlermessage方法进行余下的操作。之所以这样做的原因是因为避免多线程并发更新UI线程所产生的问题的,如果我们允许其他子线程都可以更新界面,那么势必会造成界面的错乱(因为没有加锁机制),如果我们加锁,又会影响速度,所以,只能在主线程即UI线程里面更新界面。 面试题:只能在UI线程里面更新界面吗? 答:不一定,之所以子线程不能更新界面,是因为Android在线程的方法里面采用checkThread进行判断是否是主线程,而这个方法是在ViewRootImpl中的,这个类是在onResume里面才生成的,因此,如果这个时候子线程在onCreate方法里面生成更新UI,而且没有做阻塞,就是耗时多的操作,还是可以更新UI的。 面试题:Android子线程更新UI的方式有几种? 答:一般情况下,我们都采用Handler的方式进行更新UI,当然,代码层的实现有不同的方法,比如可以使用Handler的post方法进行更新UI,或者用Handler的sendMessage方法进行更新UI,或者通过View的post方法进行更新,还有一个是runOnUIThread也是可以进行更新的。但这些本质上还是通过Handler进行子线程的更新。 面试题: 使用Handler的时候一般会遇到什么问题? 答:比如说子线程更新UI,是因为触发了checkThread方法检查是否在主线程更新UI,还有就是子线程中没有Looper,这个原因是因为Handler的机制引起的,因为Handler发送Message的时候,需要将Message放到MessageQueue里面,而这个时候如果没有Looper的话,就无法循环输出MessageQueue了,这个时候就会报Looper为空的错误。 面试题:你知道HandlerThread是什么吗? 答:HandlerThread是Android官方给我们提供好的一套子线程的Handler,也就是异步处理机制,它是为了避免线程切换导致空指针异常的错误。 面试题:怎么在主线程中通知子线程?这样做有什么好处? 答:可以利用HandlerThread进行生成一个子线程的Handler,并且实现handlerMessage方法,然后在主线程里面也生成一个Handler,然后通过调用sendMessage方法进行通知子线程。同样,子线程里面也可以调用sendMessage方法进行通知主线程。这样做的好处比如有些图片的加载啊,网络的访问啊可能会比较耗时,所以放到子线程里面做是比较合适的。 面试题:异步处理有几种方式? 答:可以采用Handler的形式,利用官方提供的HandlerThread类进行声明一个子线程的Handler,然后在Handler里面就可以做耗时的操作了,注意,需要在子线程中提前准备好Looper对象,可以使用Looper.prepare方法,最后需要使用Looper.loop方法进行循环。还可以直接用AsyncTask进行操作,一般会构造函数有三个参数,一个是传入参数,一个是进度,还有一个是结果,然后一般会实现一些方法,比如:execute用来用来执行一个异步任务,就是实现的AsyncTask的类调用的,还有onPreExecute,就是调用后立即执行,doInBackground,在onPreExecute完成后立即执行,用于执行较为费时的操作,此方法将接收输入参数和返回计算结果。onProgressUpdate,可以直接将进度信息更新到UI界面上。onPostExecute,后台结束时候调用的方法,会返回结果。注意,不能执行多次,不然会报错,且必须在UI线程中调用,至于上面提到的方法都不要手动调用。doInBackground方法中不可以更新UI。 (因为Android3.0以后必须要求网络访问在子线程中,不然会抛NetworkOnMainThreadException异常,尝试ANR现象(5秒不响应现象)) 面试题:Android中有几种布局? 答:Android中一般有五种布局,首先比较常用的两种布局是LinearLayout和RelativeLayout,就是线性布局和相对布局,线性布局的话一般是指定方向,然后从左往右或者从上往下排列的,相对布局的话是依赖与父控件或者其他View进行确定位置的。然后还有FrameLayout,TableLayout和AbsoluteLayout,其中FrameLayout就是一层一层的叠加的,TableLayout有点类似与HTML的表格,然后AbsoluteLayout的话是通过坐标确定位置的,因为Android屏幕多种多样,所以一般都不推荐用绝对布局。 面试题:说下Activity的生命周期。 答:Activity的生命周期是这样的,首先当用户启动一个Activity的时候,就会调用onCreate的方法,这个时候一般把要初始化的东西都放到这里,接着就会调用onStart方法,这个时候如果需要监听UI的变化或者数据的变化,一般可以放到这里,然后执行onResume方法,这个时候界面就已经显示好了。然后如果这个时候按了home键的话,就会调用onPause方法,接着是执行onStop方法,这个时候可以取消或停止刚才监听的UI或数据变化的监听器,接着如果这个时候你返回到刚才的Activity的话,可能产生两种情况,一种就是因为系统回收了你的Activity,这个时候就重新执行onCreate onStart onResume,如果系统没有回收你的Activity的话,就执行onRestart onResume方法,如果这个时候又不想回去,刚好内存不够了,就会执行onDestory方法进行销毁。 面试题:Activity的启动模式有几种? 答:有四种启动模式,首先默认的启动模式是standard,就是没创建一个Activity就会将其压入任务栈栈顶,不管是否存在,一种是singleTop,就是如果任务栈栈顶刚好是要显示的Activity,它就不会创建一个新的Activity,如果不是,就会重新创建一个新的Activity,一种是singleTask,如果Activiy 已经存在,不管是栈顶还是栈中,它就会把要创建的Activiy移到栈顶。一种是singleInstance,就是如果应用1创建了Activity,这个时候应用2也想调用该Activity,这个时候就不需要重新调用了。 面试题:Android中的四大组件是什么? 答:Android中的四大组件分别是,Activity,就是我们看到的界面显示,Service,就是服务,一般是没有界面的,如果按照运行地点分的话,可以分为本地服务和远程服务,也就是说它的启动是否跟启动他的进程有关系。ContentProvide,就是内容提供者,主要用来对外共享数据的。还有一个就是BroadcastReceiver,就是广播接收者,是一个全局的监听器,一般用来传递接受消息的。 面试题:Activity的缓存方法是怎么样的? 答:可以在onSaveInstanceState中将要保存的数据保存起来,可以通过Bundle进行临时保存,然后在onCreate中的Bundle中取出来进行恢复,这样就可以避免Activity被销毁的时候数据的清空。因为onSaveInstanceState在Activity销毁之前必然会调用,所以可以在这里做缓存操作。记住,这个是系统未经你同意的时候就销毁的时候才会的。 面试题:Fragment的生命周期是怎么样的,跟Activity有什么关系? 答:Fragment是Activity的一个组件片段,也就是说他的生命周期是依赖于Activity的,但是它比Activity多了几个生命步骤,首先onAttach当fragment加入Activity的时候调用,然后是onCreate进行启动Activity,接着是onCreateView进行绘制View,一般的View就是这里绘制的,然后是onActivityCreated,接着跟Activity的生命周期差不多,调用onStart和onResume,然后是onPause,onStop,如果这个时候需要回收Fragment的时候,就会调用,接着是onDestoryView销毁布局,然后是onDestory和onDetach完成。 面试题:为什么在Service中创建子线程而不是Activity中? 答:因为假如在Activity中创建子线程的话,当Activity销毁的时候,这个时候重新再调用该Activity就会重新走新的生命周期,这个时候就无法再重新获取到刚才的子线程,而且如果在一个Activity中创建子线程,另一个Activity也无法操作该子线程,但是Service就不一样,所有的Activity都可以和Service关联,即使是Activity被销毁了,只要再重新建立联系就好了,所以,一般后台任务都是通过Service去控制的。 面试题:Intent可以传递哪些数据?怎么传递? 答:Intent可以传递String类型的,基本类型,还有对象,如果是基本类型,可以通过Intent的方法直接传递就好了,如果是对象的话,一般可以通过Bundle进行传递,有些对象需要进行序列化和包裹化。 面试题:怎么启动Service? 答:有两种启动方式,一种是通过startService进行启动,这个时候Service跟启动的Activity没有关联,只有当调用stopService的时候才会结束Service,他的生命周期是:onCreate->onStartCommand->Service Run ->stopService->onDestory();如果是通过bindService启动的,那么这个Service就跟启动他的进程有关了,这个时候如果启动他的进程销毁了,那么这个Service也紧跟着销毁了或者直接调用unBindService,生命周期是:onCreate->onBindService->Service Run->unBindService->onDestory. 面试题:广播的动态注册和静态注册有什么区别? 答:静态注册:在AndroidManifest.xml文件中进行注册,当App退出后,Receiver仍然可以接收到广播并且进行相应的处理 动态注册:在代码中动态注册,当App退出后,也就没办法再接受广播了。 面试题:ContentProvide的使用方法? 答:首先我们应该为数据创建一个类,集成ContentProvide,然后在配置文件里面配置这个ContentProvide,接着需要准备好数据库操作类和数据库访问类,初始化URI,URI的形式为:content://包名,然后便是在数据库操作类中实现操作方法,这个时候就可以提供数据共享服务了。 面试题:URI的格式和意义。 答:URI叫做统一资源标识符,主要分四部分,第一部分是协议名称,可以是官方的,也可以自定义,第二部分是是URI的授权部分,是唯一标识符,用来定位ContentProvider。格式一般是自定义ContentProvider类的完全限定名称,注册时需要用到,如:com.alexzhou.provider.NoteProvider第三部分部分和第四部分部分:是每个ContentProvider内部的路径部分,C和D部分称为路径片段,C部分指向一个对象集合,一般用表的名字,如:/notes表示一个笔记集合;D部分指向特定的记录,如:/notes/1表示id为1的笔记,如果没有指定D部分,则返回全部记录。 面试题:动画有哪两类?各有什么特点? 答:tween补间动画,通过指定View的初末状态和变化时间、方式,对View的内容完成一系列的图形变换来实现动画效果。 Alpha Scale Translate Rotate。 frame帧动画,AnimationDrawable 控制 animation-list xml布局。 PropertyAnimation 属性动画。 面试题:Android存储形式有几种? 答:1.SQLite方式,SQLite是一个轻量级的数据库, 支持基础的SQL语法,官方提供了一个SQLiteDatabase的类,并提供一些api。 2.SharedPreference:存储简单的参数信息,本质上是xml. 3.File:文件存储,常用来存储大数据量的数据,但是更新麻烦。 4.ContentProvide,一般情况下数据在各个应用中是私密的,但是因为它也是可以用来存储分享数据。 5.网络存储,将数据放到网络云里面,然后通过网络进行访问。 面试题:SQLite的基础操作。 答:首先需要创建库和表,并且需要继承SQLiteOpenHelper类,然后在这个表里面实现增删改查的方法,可以用Android官方封装好的方法进行,也可以调用SQL语句进行操作。调用SQLiteDatabase中的execSQL方法操作SQL语句。 面试题:如何判断应用被强制杀死? 答:可以在Application中定义一个static常量,赋值为-1,然后在欢迎页面修改值为0,如果被强杀,Application被重新初始化,这个时候如果父Activity判断该常量是多少。 面试题:如何解决应用被强制杀死? 答:如果在每一个Activity的onCreate里判断是否被强杀,冗余了,封装到Activity的父类中,如果被强杀,跳转回主界面,如果没有被强杀,执行Activity的初始化操作,给主界面传递intent参数,主界面会调用onNewIntent方法,在onNewIntent跳转到欢迎页面,重新来一遍流程。 面试题:Json有什么优势? 答:JSON格式简单,兼容性高,易于读写,并且传输的带宽小,方便解析,并且服务端容易生成。 面试题:动画有哪些类型,动画的区别? 答: 在Android3.0以前,动画有两种类型,一种是补间动画,即tween,他指的是通过自身的变形达到的效果,比如说透明度的变化,放大缩小等,还有一种是帧动画,即Frame,是通过一针一针的对图片进行连贯起来播放的,Android3.0的时候定义了一个属性动画,即PropertyAnimation,指的是控件的真实移动,就是不断的改变某些属性的值进行的。具体可以通过实现ValueAnimator等类进行实现。 面试题:Asset和res目录的区别? 答:Asset不会在R文件里面生成一个ID,所以它不能直接用R文件来调用,这就说明要读取Asset目录下的文件需要指定文件的目录,可以通过AssetManager类来访问。res会自动在R文件里面生成id,直接可以用R.的方式进行访问资源。 面试题:Android怎么优化启动速度? 答:因为Android启动应用程序一般分为两种,一种是冷启动,就是要启动的应用程序没有后台进程的启动,这个时候需要重新分配一个进程给他,所以这个时候会先初始化Application类,再创建和初始化MainAcitvity 类,最后显示到界面上,还有一种是热启动,就是后台还有该应用的进程,比如说按下的home键或者返回键,虽然表面上退出了,但是在任务栈里面仍然还存在的,这个时候就不需要再初始化Application类了,只要重新初始化MainActivity了。因为大多数应用的启动都是冷启动(用户习惯将应用程序在任务栈中删除),所以这个时候可以采取这几个步骤,比如尽量不在Application的构造器,attachBaseContext方法和onCreaete方法中做过多的耗时操作,将一些数据预取放在异步线程中,可以采Callback的方式。优化MainActivity,尽量不要在MainActivity的onCreate,onStart和onResume等方法里面做过多的耗时操作。 面试题:Android怎么加快Activity的显示速度? 答:首先因为Activiy的显示是在这几个生命周期之间的,onCreate,onStart,和onResume,这个时候我们需要将我们需要初始化的数据分类,比如说我们将一些只需要初始化的一次的数据放到onCreate中,尽量不要在onCreate中做耗时的操作,然后将需要加载比较长时间的数据放到onResume中,可以利用handler的机制进行更新UI,或者放到AsyncTask逐个显示,然后可以设置一些动画进行显示,如果这个时候有许多数据都是一次显示的, 那么可以在onCreate里面进行标记,并且在onResume里面判断是否需要初始化,初始化完成以后就立刻false掉,这样就可以避免多次初始化了,也可以提升Activity的显示速度。 面试题: Android内存泄漏可以引发什么问题? 答:可能使程序造成卡顿的现象,或者莫名的消失,因为内存过大,系统就更可能的回收这一块的内存,或者直接崩溃。 面试题:产生Android内存泄漏的原因有什么? 答:handler等生命周期较长的匿名内部类,因为这些匿名内部类可能会持有外部的引用,从而导致短期内就算Activity退出而一些资源没有被回收,数据结构未优化,图片没有优化,没有注意到对象的生命周期,造成许多对象没有被回收,过多的使用Service,单例的过多使用,无效的资源等等。 面试题:怎么处理Android内存泄漏? 答:可以使用更加轻量的数据结构,比如ArrayMap而不是HashMap,避免在Android里面使用enum,减小Bitmap对象的内存占用,可以采用缩放比例,或者使用缓存缩略图的方式。 (总结不易,点赞容易,有了你的一个赞,笔者会更加努力!一起为了工作加油吧!)
作者: 野老盟客
链接:http://t.imooc.com/article/11965
来源:慕课网
作者: 野老盟客
链接:http://t.imooc.com/article/11965
来源:慕课网