安卓基础面试题

来源:互联网 发布:山东理工大学网络教育 编辑:程序博客网 时间:2024/05/18 03:39
10:简述Android操作系统的四层架构
·Linux内核层:C/C++/汇编等
·系统运行库和运行时(含Dalvik虚拟机):C/C++
·应用框架层(Framework层):Java为主
·应用层:Java






11:简要介绍SDK的目录结构
·platform:不同平台版本
·build-tools:编译工具
·tools:通用工具
·platform-tools:平台版本工具
·sources:源码
·system-images:系统镜像(模拟器使用)
·extras\android\m2repository\:support包所在位置
·SDK Manager:SDK管理器
·AVD Manager:虚拟设备管理器






12:Android应用的五种基本布局是什么?分别有何特点?
·FrameLayout:帧布局,子元素对齐左上角依次层叠放置
·LinearLayout:线性布局,横向或纵向排列子元素,支持按权重排列子元素
·RelativeLayout:相对布局,子元素可相对于父控件上下左右居中对齐、子元素可以与兄弟元素上下左右对齐、子元素可以位于兄弟元素的上下左右方位,默认的子元素排列方式与FrameLayout相同
·AbosoluteLayout:绝对布局,指定子元素的坐标来确定子元素的位置
·TableLayout:表格布局






13:ImageView的scaleType属性有哪几种取值,分别代表什么含义?
·matrix:从图片的左上角开始截取【ImageView的宽高所定义的像素数量】,如果ImageView的宽高超出图片的像素数,则显示全部,不缩放;
·fitXY:强行将图片拉伸到控件的宽高;
--------------------------------------------------
·fitStart:自动缩放到填满宽高之一,然后居左或居顶放置(取决于控件是“长的”还是“扁的”)
·fitEnd:自动缩放到填满宽高之一,然后居右或居底放置(取决于控件是“长的”还是“扁的”)
·fitCenter:居中显示全部,并自动缩放到填满宽高之一(取决于控件是“长的”还是“扁的”)
* fitXXX系列的共同点是:都会缩放以显示全部,并充满宽高之一
--------------------------------------------------
·center:不缩放,显示图片的正中间部分
·centerInside:居中显示全部,图片小于控件时不缩放
·centerCrop:缩放以填充长边,显示图片的正中间部分






14:如何定义和使用样式?
·在res/values/styles.xml下定义新的style
·指定其名称、父类(有parent="XXX"和XXX.XXX两种方式)
·指定具体布局属性和属性值
·布局文件中引用该样式:style="@style/XXX"






15:如何制作一个自定义样式的进度条?
·先引用系统样式(环形或水平)
·追踪系统样式定文件的位置
·拷贝、重命名和修改系统样式,主要包括:进度环美术资源、进度美术资源、二级进度美术资源、手柄美术资源、尺寸大小等
·引用自定义样式后的进度条






16:阐述ListView的复用原理
·在listView的滚动过程中,convertView是被系统自动回收复用的,因此我们通过关联布局文件holder到convertView,实现布局的复用;
·首次加载第一屏数据时,没有可以复用的convertView,因此加载布局文件
·将布局文件中的控件丢给holdr对象保管,holder对象交给convertView保管(setTag)
·当列表不再是首次加载第一屏时,有可以复用的convertView(滚出屏幕外的item的convertView会被系统回收,并复用到新滚入的item中)
·此时从convertView中拿出上次保管起来的holder(getTag),进而拿出控件并一一设置值






17:如何处理ListView的ITEM及ITEM内控件的点击事件冲突?
·如果item内有Button、ImageButton等强焦点控件,则item的点击事件会失效
·因此如果要item整体、item内的子控件有各自独立的点击事件,就不要使用Button、ImageButton等强焦点控件,而是使用TextView等弱焦点控件替代之;
·在item整体没有焦点的时候,使用【item根布局的点击事件】代替【item本身的点击事件】也是一种常见的做法;






18:简述ExpandableListView的用法
·界面布局、找出控件的方式与ListView相同;
·适配器继承BaseExpandableListAdapter并实现其中方法;
·getGroupCount()和getGroupView()定义了组的数量和显示外观;
·getChildrenCount()和getChildView()定义了组下组员ITEM的数量和显示外观;
·数据多采用Map<Integer,List<Bean>>结构存储,Integer为组序号,List为组内的数据集合;
·isChildSelectable()方法须返回true,以使childItem有点击事件;
* 着重讲明原理,方法名记个大概即可






19:drawNinePatch的四条黑边分别代表什么?
·左上两条黑线相交区域代表控件的可拉伸范围;
·右下两条黑线相交区域代表内容呈现的位置;






1A:gravity和layout_gravity有和区别?
·gravity指的是孩子和自己的对齐方式;
·layout_gravity指的是自己和父控件的对齐方式;
















20:简述startActivityForResult的用法
·AActivity使用startActivityForResult()方法启动BActivity,配置一个requestCode;
·当BActivity结束前,通过setResult(RESULT_OK,intent)方法向AActivity返回结果;
·BActivity结束时,AActivity通过onActivityResult(int requestCode, int resultCode, Intent data)覆写方法获得BActivity的返回结果;
·onActivityResult()方法内的逻辑一般为:
比对请求码是否和当初相同;
结果码是否为RESULT_OK;
从返回Intent中获取和处理返回数据;






21:如何将一个Activity配置为应用的默认启动项,不配可不可以,配置多个会如何?
·配置其intentFilter的行为为ACTION_MAIN,类别为CATEGORY_LAUNCHER;
·可以不配,但这样不会在程序列表中形成启动图标,用户无法手动启动应用;
·可以配多个,这种情况下会以第一个作为默认启动项;






22:如何为Activity定义和使用菜单?
·在res/menu中定义菜单资源,指定每个菜单项的title、id、icon、显示方式等;
·覆写onCreatOptionsMenu()方法和onOptionsItemSelected()方法;
·在onCreatOptionsMenu()中加载菜单资源:getMenuInflater().inflate(R.menu.menu_main,menu);
·在onOptionsItemSelected()方法中定义菜单的点击监听事件;






23:Intent可以传递哪些类型的数据?
·基本数据类型,包括String;
·基本数据类型数组(包括String数组);
·Bundle数据包
·Serializable和Parcelable






24:Activity的生命周期按顺序依次是什么?
·onCreate
·onStart
·onResume
·onPause
·onStop
·(经由onRestart返回onStart)
·onDestory






25:简述Activity在不同状态下被回收的可能性
·运行状态(onStart)——基本不回收
·暂停状态(onPause)——不倾向回收
·停止状态(onStop)——比较容易被回收
·消亡状态(onDestroy)——随时被收回






26:打开一个应用,返回桌面,然后再次返回应用,Activity经历了怎样的生命周期?
·onCreate-onStart-onResume;
·点击home键;onPause-onStop;
·重新打开;onRestart-onStart-onResume






27:进行横竖屏切换时,Activity经历了怎样的生命周期?(分类讨论)
·常规切换横竖屏:
onCreate-onStart-onResume;
竖屏切横屏;onPause-onStop-onDestroy;onCreate-onStart-onResume
·切换横竖屏并保存状态:
onCreate-onStart-onResume;
竖屏切横屏;onPause-onSaveInstanceState-onStop-onDestroy;onCreate-onStart-onRestoreInstanceState-onResume
一存一取,分别发生在:不可见之前,重新可见了以后
·清单文件中配置有android:configChanges="orientation|screenSize":
onCreate-onStart-onResume;
竖屏切横屏;onConfigurationChanged;






28:为避免Activity的异常消亡和数据丢失,应如何做?
·覆写onSaveInstanceState,在即将不可见之前保存数据;
·覆写onRestoreInstanceState,在重新可见以后恢复保存的数据;






29:打开一个Activity,点击跳转按钮跳转到一个Dialog风格的Activity,然后点返回,其间两个Activity分别经历了怎样的生命周期?
假设主Activity和窗口Activity分别为:MA、DA
·MAonCreate-MAonStart-MAonResume;
·按钮跳转;MAonPause-DAonCreate-DAonStart-DAonResume;
·点击back键;DAonPause-MAonResume-DAonStop-DAonDestroy






2A:Activity的启动模式有哪几种,分别有何特征?
·standard:标准,每次startActivity时都会新建一个该Activity的实例,并置于栈顶;//无限堆叠
·singleTop:栈顶单例,startActivity时,如果栈顶有该类的实例,就复用之,否则就新建实例置于栈顶;
·singleTask:任务栈中单例,startActivity时,如果栈中有该类的实例,就将其上层的其它实例全部弹出,没有就新建实例并置于栈顶;//踹飞模式
·singleInstance:绝对单例,独占一个任务栈,startActivity时,如果没有该类的实例,就在新的任务栈中新建一个该实例,并将该栈置于顶部,如果有就将其所在的任务栈切换到窗口顶层;//一人一栈






2B:Intent的七大属性是什么,分别有何含义?
·ComponentName:显式地指定要启动的活动的包名或类名;
·Extra:为意图携带额外参数;
·Action:指定要启动的活动的行为,隐式地启动具有某种特定功能的活动;
·Category:指定要启动的活动的类别,与行为共同作用缩小要启动的活动的范围,从而实现隐式启动活动;
·Data:为意图携带Uri类型的参数,如网址、文件地址、邮箱、电话等;
·Type:用于指定Data数据的Mime类型,如imag/png、audio/*等;
·Flag:额外标记,一般用于指定以何种启动模式启动活动;






2C:什么是有序广播和无序广播,有何区别?
·无序广播又称普通广播,以sendBroadcast()方式发送;
·无序广播的处理中,高优先级接收器不能屏蔽低优先级接收器,也不能篡改广播数据;
·有序广播的发送方式为sendOrderedBroadcast();
·有序广播的处理中,高优先级接收器能够屏蔽低优先级接收器对广播的接收和处理:abortBroadcast();
·有序广播的处理中,高优先级的接收器还可以篡改广播数据,如:setResultData(newString)或setResultExtras(newBundle);
·注意:所谓数据篡改,仅仅是resultData或resultExtras,不包括Intent携带的一般数据;






2D:广播接收器的静态注册和动态注册有何区别?
·静态广播接收器是注册在Manifest中的;
·静态广播接收器理论上常驻系统内存的,不需要启动应用界面;
·静态广播接收器一般用于收听系统级别的广播:比如收听开机广播,收听来电广播等;
·动态广播接收器是在运行时动态注册和注销的,分别通过retisterReceiver()和unregisterReceiver()方法;
·动态广播一般用于应用内的通信;


















30:安卓应用的数据存储方式有哪几种?分别适用于何种场景?
·SharedPreference:轻量级数据的本地存储;
·文件系统存储:文档、图片、音频视频、压缩包等二进制文件数据的本地存储;
·SQLiteDatabase:结构化数据的本地存储;
·网络存储:将数据上传保存到服务端;
·ContentProvider:设备内的跨进程数据共享;






32:用户手动执行清除缓存和清除数据操作时,分别会清空哪两个文件夹中的数据?
·【外部存储】中的【程序私有目录】下的数据缓存文件夹及数据文件夹;
·即:/Android/data/包名/files目录和/Android/data/包名/Cache目录;
·程序卸载时,这两个目录及其数据会被一并删除;






35:SQLite数据库支持的五种基本数据格式是什么?
·整型-INTEGER
·浮点型-REAL
·字符串-TEXT
·二进制-BLOB
·空-NULL






36:如何在程序中获取到SQLiteDatabase对象的实例?
·SQLiteDatabase db =  context.openOrCreateDatabase("db605.db", MODE_PRIVATE, null);
·通过SQLiteOpenHelper实例去getReadableDatabase()或getWritableDatabase();






37:如何将一条用户的信息(姓名,性别,年龄)存储到SQLite数据库?
·获取到数据库对象,可以通过openOrCreateDatabase()方法或sQLiteOpenHelper.getWritableDatabase()方法;
·通过执行SQL语句实现实现插入:db.execSQL("insert into tb_user(name,gender,age) values('zhangsan','male',20)");
·通过SQLiteDatabase的API实现插入:db.insert(...);
·db.insert()方法插入的数据对象为ContentValue,需要先将用户信息以键值对方式存储到ContentValue对象中才能执行insert();






38:对SQLite数据库进行增删改操作的方式有哪几种?查询的方式有哪几种?
·增删改操作都有两种选择:即通过db.execSQL(sql)或SQLiteDatabase的API(insert、delete、update);
·查询也是sql语句和API两种选择,但API分别为:db.rawQuery(sql)和db.query();
·查询结果为Cursor数据游标,需要遍历解析Cursor获得最终结果;






39:一个应用的SQLite数据库的存放在什么位置?
·设备的运行内存空间(非外存,用户无法手动访问)中的data/data/<包名>下;






3A:说出几种跨应用(跨进程,IPC)共享数据的方式,安全的方式是什么?
·通过意图启动远程活动;
·发送和接收全局广播;
·绑定和调用远程服务(AIDL,Messenger);
·通过ContentResolver远程访问ContentProvider共享出来的数据;
·其中远程服务绑定和ContentProvider分别是安卓推荐的相对安全的远程服务和数据访问方式;






3B:请简述ContentProvider跨应用共享数据的原理
·CP所在的应用(服务端)维护着一个可以共享的数据库
·服务端注册ContentProvider,并声明exported="true",即该CP可以被远程应用(客户端)访问
·CP定义数据访问规则,即Uri,通过UriMatcher将不同的Uri匹配到不同的访问标的(数据表)
·CP定义并对外抛出增删改查接口,其参数Uri代表了将要增删改查的数据标的(数据表)
·远程应用通过获取ContentResolver对象
·远程应用通过调用CR的增删改查(配以相应的Uri和参数),获取到CP的增删改查所返回的数据,即实现了对CP端数据的访问
·对系统CP提供的数据的访问往往要声明对应的权限






3C:当我们注册四大组件时,如何使该组件能被其它应用访问?
·在注册时声明:exported=true






3D:什么是数据库事务?其特点如何?
·批量执行的增删改操作;
·其执行结果要么全部成功,要么全部失败;
·如事务失败则所有【本次事务中已执行的操作】全部回滚至执行前的状态;












41:安卓动画分为哪几种,分别有何特点;
·逐帧动画FrameAnimation:逐帧播放图片;
·补间动画TweenAnimation(又称视图动画ViewAnimation):只改变视图的“影像”,不能实际上改变视图的实际属性;
·属性动画PropertyAnimation:既改变视图的视觉属性,又不影响其点击事件时使用;
·布局动画LayoutAnimation:定义ViewGroup中孩子的出场方式的动画;






42:属性动画和补间动画有何区别?
·补间动画改变的只是View的“影像”,其实质属性并未发生变化,点击事件仍存在与视图变化前的位置;
·属性动画是真正改变了View的属性,包括位置大小透明度旋转角度等,点击事件的响应区域也响应发生了变化;
·属性动画能改变的不仅仅是View的视觉属性,还可以是任何对象的任何属性,开发者可以在过程回调中进行任意操作从而实现动画效果;






43:简述碎片回退栈的入栈和出栈规律;
·每个Activity都维护有一个自己的碎片回退栈;
·入栈方式:在fragmentTransaction提交之前执行fragmentTransaction.addToBackstack(null)将当前要提交的碎片添加到回退栈;
·当用户点击返回物理键时,会先将碎片回退栈中的碎片实例一一弹出,然后才会弹出Activity的实例;






44:简述Fragment和Activity如何实现通信?
·活动的FragmentManager通过id或tag可以找到布局中定义的静态碎片:
·活动的FragmentManager通过tag可以找到动态加载的碎片(需要在replace时设置tag参数):
·活动在创建碎片实例时,可以进行初始化传参:
MyFragment fragment = new MyFragment();
fragment.setArguments(bundle);
·碎片找【宿主活动】进而调用:
Activity activity = getActivity();
·最后的也是最重点的——接口回调,其步骤为:
碎片定义接口、【接口实例】、【接口实例】的Setter方法;
活动实现碎片的回调接口;
活动调用碎片的Setter方法,将自身设置为碎片的【接口实例】;
碎片在触发业务时回调【接口实例】的实现方法;






45:按顺序说出Fragment的生命周期;
·对比活动的声明周期,碎片的生命周期可以概括为:前四后三中间同
--------------------
·onAttach
·onCreate
·onCreateView
·onActivityCreated
--------------------
·onStart
·onResume
·onPause
·onStop
--------------------
·onDestroyView
·onDestroy
·onDetach






45:简述Fragment的生命周期和Activity生命周期的联动规律;
·生长阶段:Activity先生长,Fragment再生长,即:
AonCreate -> FonAttach,FonCreate,FonCreateView,FonActivityCreated
AonStart -> FonStart
AonResume -> FonResume
·消亡阶段:Fragment先消亡,Activity再消亡,即:
FonPause -> AonPause
FonStop -> AonStop
FonDestroyView,FonDestroy,FonDetach -> AonDestory






46:说出几种Fragment的常用优化方案;
·将经常使用的碎片实例抽取为属性;
·保证每个碎片实例中onCreateView()只加载一次布局;
·对于常用的碎片实例,使用add()配合hide/show()替代replace();










51 什么是ANR?如何防治?
·ApplicationNotResponding——应用程序无响应;
·一般地,当应用程序在5秒以内无法响应用户的交互时,操作系统就会抛ANR,询问用户继续等待还是强制关闭;
·为什么会无响应呢?——因为主线程被阻塞了!
·防治的办法就是:不要在UI线程中做耗时操作,耗时操作交给子线程;






52 什么是OOM?如何防治图片过多过大造成的OOM?
√ OutOfMemory,不良代码创建了【太大或太多的对象实例】,且用完没有及时释放,导致运行内存超过了系统分配的上限(爆内存),从而使应用异常退出,的现象;
√ 更改图片的颜色模式减小其内存开销;
√ 更改图片的采样率减小其内存开销;
√ 用完的图片及时回收:bitmap.recycle();
√ 使用软弱引用替代强引用指向Bitmap对象:
if(softReference.get()!=null){
iv.setImageBitmap(softReference.get());
}else{
Bitmap bitmap = getBitmap();//重新获取图片
softReference = new SoftReference<Bitmap>(bitmap);//软引用指向图片
bitmap = null;//释放强引用


iv.setImageBitmap(softReference.get());
}
√ 使用三级缓存策略,用LruCache管理图片的内存缓存,给内存开销指定一个安全上限;






53 简述什么是图片的三级缓存策略,并简要介绍相关API;
·三级缓存是指:内存-文件系统-网络;
·即当有一个Bitmap请求时,先查看内存中是否有该图片的对象,内存没有再去查看文件系统中是否有,最后再去联网下载;
·LruCache是内存缓存的常用工具类,其算法原理为:最近最少使用的图片对象会被踢出缓存;
·LruCache在构造实例时可以配置一个大小,在sizeOf覆写方法中指定每张具体的Bitmap的大小;
·LruCache实例对外抛出put()和get()接口对应着图片对象的存和取;






54 什么是图片的二次采样?其原理是什么?
·图片的像素数量过多时,不但消耗大量内存,还常常导致显示失败;
·二次采样指的是:均匀地丢弃图片的一部分像素,以使图片的内存开销降低;
·BitmapFactory.Options.inSampleSize属性定义了图片的二次采样率,其值为2的整数幂,例如当采样率为4时,代表只均匀采集原有1/4的像素数量形成新的图片;
·当我们使用BitmapFactory来生成图片时,常常会使用到二次采样;






55 图片的颜色模式有哪几种?内存开销分别如何?
·ALPHA_8——只有透明度通道,占用一个字节8位,有256个不同透明度梯度
·RGB_565——有红绿蓝三个通道,每像素占用2字节16位,红绿蓝分别占5、6、6位,即32种不同梯度,显示效果可以接收,是一种常用的效果和开销都比较折中的颜色模式
·ARGB_4444——有透明度和红绿蓝四个通道,每像素占用2字节16位,每个通道占用4位,即16种不同梯度,显示效果较差
·ARGB_8888——有透明度和红绿蓝四个通道,每像素占用4字节32位,每个通道占用8位,即256种不同梯度,显示效果好,是安卓默认的颜色模式






56 简述安卓的线程通信原理;(Looper/Handler机制,消息机制)
·可以从以下三个大块来回答:
----------------------------------------
@ 消息传递和处理流程:
·假定A线程要发送消息给B线程;
·A线程创建消息;
·让B线程的Handler把消息取回家(bHandler.sendMessage(msg););
·bHandler将消息丢到消息队列MessageQueue的末尾;
·B线程的“消息循环器”Looper不断轮询和弹出MessageQueue头部的消息,丢给Handler处理;
·Handler处理消息;
----------------------------------------
@ 如何创建消息循环系统:
·主线程有默认的【消息循环系统】
·子线程默认是没有【消息循环系统】的(Looper和MessageQueue);
·创建的方式是(run方法中):
Looper.prepare();//创建Looper
bHandler = new Handler(){handleMessage(Message msg){...}};//为线程创建Handler
Looper.loop();//让Looper开始工作
----------------------------------------
@ Handler的线程归属问题:
·Handler处理消息和提交的Runnable都运行在Handler所属的线程;
·正常情况下,Handler在哪条线程赋值,就属于哪条线程——因为它持有了该条线程的Looper;
·本质上,Handler持有哪条线程的Looper,它就属于哪条线程;






57 简述异步任务和线程的异同;
·相同点:都是在子线程完成特定操作,线程在run()方法中,异步任务在doInBackground()方法中;
·不同点:
·异步任务提供了更多的过程回调,分别为:预执行回调onPreExecute()、进度更新回调onProgressUpdate()、提交结果回调onPostExecute();
·异步任务的上述三个回调是执行在主线程的(封装了主线程的handler),因此可以直接操作UI;






58 同样是在后台执行耗时操作,使用服务和线程的区别是什么?
·服务中的代码默认是执行在主线程的;
·服务是不易被杀死的(即使被杀死也有复活机制),因此(一定程度上)能确保业务被完成;
·而线程在活动退出后,一来不便提交执行结果,二来在失去引用的情况下,有被提前杀死的风险;
****************************
·服务本身是上下文对象,因此可以方便地调取资源、启动活动、发送广播等,服务中能做的操作更灵活多变;
·服务本身就能够开辟和维护线程;








59 服务的两种启动方式有何异同?
·服务的两种启动方式为startService()和bindService();
@相同点:
·都只会生死一次:onCreate(),onDestory()只会执行一次;
@启动式服务:
·启动之后的Service对象是独立存在的;
·主调者不易获得Service对象;
·onStartCommand()会不厌其烦地响应startService();
·要想结束服务,必须显式地停止服务stopService(),或stopService()、stopSelf()、stopSelfResult()
----------------------------------------
@绑定式服务:
·启动之后的Service对象会与主调者同生死——即主调者退出,服务亦会随之解绑和销毁;
·主调者可以通过IBinder和ServiceConnection得到Service对象实例;
·onBind()响应bindService(),只能绑定一次;
·unbindService()或主调退出,都会导致服务死亡;
----------------------------------------
@交替着对同一服务类执行启动/停止、绑定/解绑动作:
·onCreate()只会执行一次,即初次的启动或绑定;
·一旦有绑定的动作,则服务的结束只能通过unbindService()或主调的退出;












61 dp、sp、px有何不同?
·px,Pixels,像素,一个物理像素点;
·dp,Density-Independent Pixels,密度无关的像素,在不同密度的设备上dp将以不同方式换算为px(而用户感觉它们的大小是相近的,所以称为“密度无关”);
·sp,Scale-independent Pixels,大小无关的像素,被用来在不同设备上兼容字体大小;






62 何为碎片化?说说你是如何进行屏幕适配的;
·所谓碎片化,主要指的是不同的安卓设备,其像素密度、屏幕尺寸各不相同;
·其次是指不同厂家对操作系统的不同定制,导致不同品牌和型号的安卓手机的用户体验差异较大;
·屏幕适配的方式可以概括为:针对不同属性(密度、尺寸、横竖屏、语言等)的设备,生成不同后缀名的资源文件夹,在运行时根据就近原则动态匹配资源;
·屏幕适配的常用技巧包括:
多用权重,少用具体值;
一套layout + 多套(不同密度的)dimen;






63 如何自定义View的属性?
·在res/values/attrs.xml中创建</declare-styleable>节点;
·声明控件名称、属性名称、属性类型;
·在布局文件中引用上述自定义属性时需要引入自定义的命名空间;
·在View的构造方法中,我们可以从AttributeSet参数中获取到布局文件中配置的自定义属性值,其形式为TypedArray对象;
·从TypedArray对象中逐个拿出自定义的属性值并做业务处理;






64 自定义View需要覆写哪几个方法?其职能分别是什么?
·覆写构造方法——获取和解析自定义属性值;
·覆写onMeasure()——根据父控件给出的建议宽高(封装在widthMeasureSpec和heightMeasureSpec),计算自己想要的宽高,即测量宽高;
  ——多数时候,主要是处理一下当宽高声明为wrap_content时,该设置多少宽高:
  ——如果是自定义ViewGroup,还需要向自己的孩子给出建议宽高,即widthMeasureSpec和heightMeasureSpec;
·覆写onDraw()——主要用于自定义View中,完成对自身的绘制;
·覆写onLayout()——主要用于自定义ViewGroup中,定义孩子的排列规则:






65 说说onMeasure()方法的两个参数widthMeasureSpec和heightMeasureSpec分别代表什么含义?
·这两个参数封装了【宽高模式】和【父控件建议的宽高值】(我们对onMeasure()的覆写即意味着我们不打算采用父控件建议的宽高值作为自己的测量宽高)
·宽高模式为以下三种之一:
MeasureSpec.EXACTLY——精确模式,即布局中指定了具体的尺寸:match_parent或具体值;
MeasureSpec.AT_MOST——至多模式,以父控件的宽高为上限,布局中指定的是wrap_content;
MeasureSpec.UNSPECIFIED——未指定,父控件对当前控件未加限制,想要多少给多少,用的很少;(一般声明于ScrollView条目或列表的条目中)
·当布局文件中的宽高配置为match_parent时,建议宽高值就是父控件的宽高;
·当布局文件中的宽高配置为具体值时,建议宽高值就是配置的具体值;
·当布局文件中的宽高配置为wrap_content时,建议宽高值因父控件而异,一般的实现为父控件的宽高;






66 如何刷新一个View,你能说出几种方式?分别有何异同?如何刷新一个ViewGroup?
·View的动态刷新API为:view.invalidate()和view.postInvalidate();
·上述两个方法功能相同,即触发View的onDraw()方法,但线程中只能调用postInvalidate();
·ViewGroup的刷新方式为:viewGroup.requestLayout()——这个方法会去调用VG的onLayout()使之重新排列孩子;






68 简述安卓的事件派发和消费原理(重要);


·事件:用户的触屏交互行为,可以细分为三个不同动作:MotionEvent.ACTION_DOWN、MotionEvent.ACTION_MOVE、MotionEvent.ACTION_UP
·派发:在Activity及其布局树(View Hirarchy)中的多级ViewGroup和View之间派发事件,决定事件该有谁(们)来处理;
·消费:对事件的处理称之为消费,同一事件可以有多次【二次消费】,直到某一级标注【消费干净】;
·滑动冲突:触屏事件发生在多个【可滚动控件】的交叉区域,【系统默认的事件派发和消费结果】不能令人满意的现象——如何令人满意?重写相关控件的派发、拦截和消费方法;
----------------------------------------
@派发:
·boolean dispatchTouchEvent(MotionEvent event)
·返回值含义:派发过程中,自己或下级【是否已将事件消费干净】,true=事件已消费干净
----------------------------------------
@拦截:
·boolean onInterceptTouchEvent(MotionEvent ev)
·返回值含义:派发过程中的每一级VG都有权决定是否拦截,拦截则【隧道式派发】终止,开始【冒泡式消费】,true=拦截
----------------------------------------
@消费:
·boolean onTouchEvent(MotionEvent event)
·返回值含义:true=事件已消费干净,上级不必再做【二次消费】
----------------------------------------
·派发和消费的流程可以归纳为:隧道式(即自上而下地:Activity-ViewGroup-View)派发,冒泡式(即自下而上地:View-ViewGroup-Activity)消费
·事件发生;
·Activity的dispatchTouchEvent开始派发事件(注意:返回值不是立即获得,而是在整个事件派发和消费的结尾才返回);
·事件逐级派发到ViewGroup,ViewGroup决定是否要拦截——拦截则从自己开始冒泡式消费,不拦截则继续向下派发;
·事件派发到终端节点View,开始冒泡式消费;
·每一级View或ViewGroup都可以通过onTouchEvent的返回值true或false标注【事件是否已被消费干净】;
·消费干净则再无二次消费,自下而上所有的dispatchTouchEvent全部返回true直至Activity的dispatchTouchEvent;
·没消费干净,则本级dispatchTouchEvent返回false,上级onTouchEvent将继续做二次消费;
·布局树中没人将事件消费干净,Activity的onTouchEvent将做最终的消费;
·最终消费结果为true,Activity的dispatchTouchEvent返回也是true,则继续接收和派发【本次事件的后续动作】;
·最终消费结果为false,Activity的dispatchTouchEvent返回也是false,则【本次事件的后续动作】将全部被丢弃,直至下次事件发生;






69 说说使用SVN需要注意的要点;
·提交之前一定要先Update,以使冲突暴露出来;
·处理冲突:要和冲突方队友取得一致的版本后(除非你自己很有把握),再删除冲突标记,标记为冲突已解决,再提交;
·勤提交,每日至少提交一次是多数团队的开发准则之一;
·尽量做原子提交,而非大面积的粗暴提交,这样便于冲突的发现处理,以使风险可控;
·避免犯一些常见的禁忌,例如:
擅自单方面地修改文件或文件夹名称;
擅自单方面地将文件或文件夹去版本控制;
以上两种操作都会使队友副本中对应的文件失去版本控制;
0 0
原创粉丝点击