Android面试题(四大组件篇)

window、进程、线程篇

Android面试题(数据存储、view篇)

 

数据存储


Q:Android中提供哪些数据持久存储的方法?

在Android中,可供选择的存储方式有SharedPreferences、文件存储、SQLite数据库方式、内容提供器(Content provider)和网络。


Q:Java中的I/O流读写怎么做?

https://blog.csdn.net/yueqi1125/article/details/78957174


Q:SharePreferences适用情形?使用中需要注意什么?

保存登录用户名密码等情形,应注意多进程并发读的时候数据可能不准确。

需要注意:getSharedPreferences(“User”, Context.MODE_PRIVATE)方法中第二个参数需要了解Android的四种枚举方式下面是详细的解释: 
私有模式 
Context.MODE_PRIVATE 的值是 0; 
①只能被创建这个文件的当前应用访问 
②若文件不存在会创建文件;若创建的文件已存在则会覆盖掉原来的文件

追加模式 
Context.MODE_APPEND 的值是 32768; 
①只能被创建这个文件的当前应用访问 
②若文件不存在会创建文件;若文件存在则在文件的末尾进行追加内容

可读模式 
Context.MODE_WORLD_READABLE的值是1; 
①创建出来的文件可以被其他应用所读取

可写模式 
Context.MODE_WORLD_WRITEABLE的值是2 
①允许其他应用对其进行写入。

 

Q:了解SQLite中的事务处理吗?是如何做的?

使用SQLiteDatabase的beginTransaction()方法可以开启一个事务,程序执行到endTransaction() 方法时会检查事务的标志是否为成功,如果程序执行到endTransaction()之前调用了setTransactionSuccessful() 方法设置事务的标志为成功则提交事务,如果没有调用setTransactionSuccessful() 方法则回滚事务。多用于大量数据操作时,能明显减少耗时。

https://blog.csdn.net/a443453087/article/details/7222247


Q:使用SQLite做批量操作有什么好的方法吗?

即使用事务处理进行优化,默认SQLite的数据库插入操作,如果没有采用事务的话,它每次写入提交,就会触发一次事务操作,而这样几千条的数据,就会触发几千个事务的操作,这就是时间耗费的根源


Q:如果现在要删除SQLite中表的一个字段如何做?

SQLite目前还不支持drop column,所以必须想出另外一种方法来进行表字段的删除。

如下sql语句会复制一个和record表一样表结构的temp表出来,但是我们想要的是去除某一个字段(例如去除record表中的name字段,就不要复制它就好了),所以sql语句如下:

create table temp as select recordId, customer, place, time from record where 1 = 1;  

这样复制出来的表就会缺少“name”字段,然后我们删除旧表并修改新表名即可。


Q:使用SQLite时会有哪些优化操作?

https://blog.csdn.net/phenixyf/article/details/70597232

 

View


Q:MotionEvent是什么?包含几种事件?什么条件下会产生?

https://blog.csdn.net/vansbelove/article/details/78416791


Q:scrollTo()和scrollBy()的区别?

scrollBy()也调用了scrollTo()方法,实现了基于当前位置的滑动,而scrollTo()是基于所传参数的绝对滑动


Q:Scroller中最重要的两个方法是什么?主要目的是?

1、public void startScroll(int startX, int startY, int dx, int dy, int duration)

函数功能说明:开始一个动画控制,由(startX , startY)在duration时间内前进(dx,dy)个单位(dx正值向左滑,负值向右滑),到达坐标为 (startX+dx , startY+dy)处。

2、

/**     * 在其内部完成平滑滚动的逻辑 。在整个后续的平滑滚动过程中,computeScroll()方法是会一直被调用的,     * 我们需要不断调用Scroller的computeScrollOffset()方法来进行判断滚动操作是否已经完成了     * 如果还没完成的话,那就继续调用scrollTo()方法,并把Scroller的curX和curY坐标传入,然后刷新界面从而完成平滑滚动的操作。     */    @Override    public void computeScroll() {        if (mScroller.computeScrollOffset()) {            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());            invalidate();        }    }


Q:谈一谈View的事件分发机制?

https://blog.csdn.net/mountain_hua/article/details/81545490


Q:如何解决View的滑动冲突?

外部拦截:可以在父布局中将onInterceptTouchEvent的返回值设为true进行拦截

内部拦截:类似反射的方式进行拦截,稍显复杂。需要配合requestDisallowInterceptTouchEvent进行拦截


Q:谈一谈View的工作原理?

https://www.cnblogs.com/cr330326/p/6340973.html

View的工作流程

View的工作流程主要是指measure、layout、draw这三大流程,即测量、布局、绘制,其中measure确定View的测量宽/高,layout确定View的最终宽/高和四个顶点的位置,而draw则将View绘制到屏幕上。

measure过程

measure过程要分情况来看,如果是一个原始的View,那么通过measure方法就完成了其测量过程,如果是一个ViewGroup,除了完成自己的测量过程外,还会遍历去调用所有子元素的measure方法,各个子元素再递归去执行这个流程。

Layout过程

Layout的作用是ViewGroup用来确定子元素的位置,当ViewGroup的位置被确定后,它在onLayout中会遍历所有的子元素并调用其layout方法,在layout方法中onLayout方法又会被调用。

draw过程

draw过程就比较简单了,它的作用是将View绘制到屏幕上面,View的绘制过程循序以下几步:

  1. 绘制背景background.draw(canvas)
  2. 绘制自己(onDraw)
  3. 绘制children(dispatchDraw)
  4. 绘制装饰(onDrawScrollBars)


Q:MeasureSpec是什么?有什么作用?

https://www.jianshu.com/p/647913c11673

https://blog.csdn.net/xxdw1992/article/details/81128900

总结

  1. View的measureSpec由其父容器的measureSpec及自身的LayoutParams共同决定
  2. 若子View为具体的大小(如100px),则不管其父容器的specMode为哪种,子View对应的specMode均为EXACTLY,specSize均为childSize
  3. 若子View的LayoutParams中的宽或高为wrap_content,则不管其父容器的specMode为哪种,子View对应的specMode均为AT_MOST,specSize均为parentLeftSize
  4. 子View的前期measure过程实际上在其父容器的onMeasure中就基本完成了,父容器会把计算好的measureSpec传递给子View,子View在自己的onMeasure中可以得到这些值,子View可以根据这些值设置自己的大小,当然也可以不参考它们。最终在onMeasure方法通过调用
    setMeasuredDimension方法设置view的最终measureSize。但View的真实大小是在Layout阶段才确定下来的,通过child.layout(left,top,right,bottom).View的measure size与 layout size不必相等,但绝大多数情况下是相等的。
  5. 总的来说就是计算出来的父View的MeasureSpec不断往子View传递,结合子View的LayoutParams 一起再算出子View的MeasureSpec,然后继续传给子View,不断计算每个View的MeasureSpec,子View有了MeasureSpec才能更测量自己和自己的子View。


Q:自定义View/ViewGroup需要注意什么?

https://blog.csdn.net/myth13141314/article/details/81449109

自定义View的分类:

  • 继承View重写onDraw方法

主要用于实现不规则的效果,即这种效果不方便通过布局的组合方式来实现。相当于就是得自己“画”了。采用这种方式需要自己支持wrap_content,padding也需要自己处理

  • 继承ViewGroup派生特殊的Layout

主要用于实现自定义的布局,看起来很像几种View组合在一起的时候,可以使用这种方式。这种方式需要合适地处理ViewGroup的测量和布局,并同时处理子元素的测量和布局过程。比如自定义一个自动换行的LinerLayout等。

  • 继承特定的View,比如TextView

这种方法主要是用于扩展某种已有的View,增加一些特定的功能。这种方法比较简单,也不需要自己支持wrap_content和padding。

  • 继承特定的ViewGroup,比如LinearLayout

这种方式也比较常见,和上面的第2种方法比较类似,第2种方法更佳接近View的底层。

自定义View需要注意的地方:

  • 让View支持wrap_content

直接继承View和ViewGroup的控件需要在onMeasure方法中处理wrap_content的方法。处理方法是在wrap_content的情况下设置一个固定的尺寸

  • 让View支持padding

直接继承View的控件需要在onDraw方法中处理padding,否则用户设置padding属性就不会起作用。直接继承ViewGroup的控件需要在onMeasure和onLayout中考虑padding和子元素的margin对其造成的影响,不然将导致padding和子元素的margin失效。

  • 尽量不要在View中使用Handler

View中已经提供了post系列方法,完全可以替代Handler的作用。

  • View中如果有线程或者动画,需要及时停止

在View的onDetachedFromWindow方法可以停止线程和动画,因为当View被remove或是包含此View的Activity退出时,就会调用View的onDetachedFromWindow方法。如果不处理的话很可能会导致内存泄漏

  • View带有滑动嵌套时,需要处理好滑动冲突问题

  • 在View的onDraw方法中不要创建太多的临时对象,也就是new出来的对象。因为onDraw方法会被频繁调用,如果有大量的临时对象,就会引起内存抖动,影响View的效果


Q:onTouch()、onTouchEvent()和onClick()关系?

public boolean dispatchTouchEvent(MotionEvent event) {    if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&            mOnTouchListener.onTouch(this, event)) {        return true;    }    return onTouchEvent(event);}

从源码中可以看出,这两个方法都是在View的dispatchTouchEvent中调用的,onTouch优先于onTouchEvent执行。如果在onTouch方法中通过返回true将事件消费掉,onTouchEvent将不会再执行。

另外需要注意的是,onTouch能够得到执行需要两个前提条件,第一mOnTouchListener的值不能为空,第二当前点击的控件必须是enable的。因此如果你有一个控件是非enable的,那么给它注册onTouch事件将永远得不到执行。对于这一类控件,如果我们想要监听它的touch事件,就必须通过在该控件中重写onTouchEvent方法来实现。

onTouch()中的ACTION_UP执行之后,会执行onClick()方法。onClick()方法在onTouchEvent()里面执行。


Q:SurfaceView和View的区别?

https://www.cnblogs.com/dubo-/p/6638094.html

view在UI线程去更新自己;而SurfaceView则在一个子线程中去更新自己

surfaceView是在一个新起的单独线程中可以重新绘制画面,而View必须在UI的主线程中更新画面

在UI的主线程中更新动画,时间一旦太长就会出现问题

surfaceView 在新的线程中更新画面所以不会阻塞你的UI主线程,但是涉及到线程同步,需要surfaceView中 thread处理,一般就需要有一个event queue的设计来保存touch event


Q:invalidate()和postInvalidate()的区别?

invalidate()用于在主线程中更新UI,postInvalidate()用与在子线程中更新UI,其内部也是使用了handler。

 

Bitmap


Q:加载图片的时候需要注意什么?

https://blog.csdn.net/caoxiao90/article/details/51545560

https://blog.csdn.net/mountain_hua/article/details/82696065

尽量不要使用setImageBitmap或setImageResource或BitmapFactory.decodeResource来设置一张大图,
因为这些函数在完成decode后,最终都是通过java层的createBitmap来完成的,需要消耗更多内存。
因此,改用先通过BitmapFactory.decodeStream方法,创建出一个bitmap,再将其设为ImageView的 source,
decodeStream最大的秘密在于其直接调用JNI>>nativeDecodeAsset()来完成decode,
无需再使用java层的createBitmap,从而节省了java层的空间。


Q:LRU算法的原理?

LRU全称是Least Recently Used,即最近最久未使用的意思。

LRU算法的设计原则是:如果一个数据在最近一段时间没有被访问到,那么在将来它被访问的可能性也很小。也就是说,当限定的空间已存满数据时,应当把最久没有被访问到的数据淘汰。也是利用了程序的局部性原理。


Q:Android中缓存更新策略?

https://blog.csdn.net/u014732103/article/details/78592476

目前常用的一种缓存算法是Least Recently Used,简称:LRU,LRU是近期最少使用算法,它的核心机制是当缓存控件满时,会优先淘汰那些近期最少使用的缓存对象。采用LRU算法的缓存有:LruCache以及DiskLruCache,LruCache用于实现内存缓存,DiskLruCache用于实现存储设备缓存,因此通过这二者的结合使用,就可以很方便地实现一个高效的ImageLoader。

 

Animation


Q:Android中有哪几种类型的动画?

View动画,帧动画,属性动画。


Q:帧动画在使用时需要注意什么?

帧动画使用比较简单,但比较容易引起OOM,因此在使用帧动画时要尽量避免使用过多尺寸过大的图片。


Q:View动画和属性动画的区别?

View动画不能真正改变View的位置,而属性动画可以


Q:View动画为何不能真正改变View的位置?而属性动画为何可以?

属性动画改变的是对象的属性,比如真正的X,Y坐标属性,而不仅仅是view。


Q:属性动画插值器和估值器的作用?

https://www.jianshu.com/p/b117c974deaf

时间插值器(TimeInterpolator)的作用是根据时间流逝的百分比计算出动画进度的百分比。

类型估值器(TypeEvaluator)的作用是根据属性值改变的百分比计算出改变后的属性值。

 

Drawable等资源


Q:了解哪些Drawable?适用场景?

https://blog.csdn.net/mp624183768/article/details/79289561


Q:mipmap系列中xxxhdpi、xxhdpi、xhdpi、hdpi、mdpi和dpi存在怎样的关系?

名称 像素密度(dpi)范围
mdpi 120dpi~160dpi
hdpi 160dpi~240dpi
xhdpi 240dpi~320dpi
xxhdpi 320dpi~480dpi
xxxhdpi 480dpi~640dpi


Q:dp、dpi、px的区别?

https://blog.csdn.net/xgdtale/article/details/71774247

https://www.aliyun.com/jiaocheng/7722.html

px : pixels(像素),是屏幕的像素点

ppi : pixels per inch(像素密度,所表示的是每英寸所拥有的像素数量);一个基于density的抽象单位,如果一个160dpi的屏幕,1dp=1px

dpi : dots per inch(每英寸的点数)

dp/dip : device independent pixels(设备独立像素)又叫Density Independent Pixels,即密度无关像素

sp : scaled pixels(放大像素)同dp相似,但还会根据用户的字体大小偏好来缩放(建议使用sp作为文本的单位,其它用dip)


Q:res目录和assets目录的区别?

https://blog.csdn.net/lichaoxin16/article/details/79314427


1. res会在R.java生成索引ID,在打包的时候判断资源有没有用到,没用到的时候不会被打包进apk中(res/raw文件夹除外),而assets不会。 
2. res用getResource()访问,assets用AssetsManager访问。 
3. res/raw与assets里的文件在打包的时候都不会被系统二进制编译,都被原封不动打包进APK,通常用来存放游戏资源、脚本、字体文件等。但res/raw不可以创建子文件夹,而assets可以。 
4. res/xml会被编译成二进制文件。res/anim存放动画资源。

更多相关文章

  1. Android(安卓)ItemTouchHelper实现RecyclerView交互动画
  2. android实现数据库和UI同步更新
  3. Android(安卓)Service 介绍
  4. android 自动弹起键盘
  5. 恢复出厂设置的两种方法,亲测可行
  6. 解决Android(安卓)应用方法数不能超过65K的问题
  7. Android动画:alpha、scale、translate、rotate、set的xml属性及用
  8. Android培训班(73)Dex文件里类定义dvmDefineClass
  9. Picasso源码分析

随机推荐

  1. android之JSON解析(二)
  2. Ubuntu13.04环境下载、编译Android源代码
  3. node.js+android(使用HttpURLConnection
  4. Android(安卓)Activty使用示例【慢慢更新
  5. [cocos2dx] cocosdx编译工程那些事
  6. receiver定制自动启动一个程序
  7. Android(安卓)使用RadioGroup和RadioButt
  8. Android驱动入门-在Android系统上运行JAV
  9. android网络层实现实例
  10. Android(安卓)Adapter 异步图片请求诡异