Android面试题二

转载地址:http://blog.csdn.net/cyp331203/article/details/44985087
                  http://blog.sina.com.cn/staratsky
                  http://blog.csdn.net/sam_linux/article/details/16902361

16.设计一个图片缓存加载机制

图片三级缓存机制
(1).内存缓存,优先加载,速度最快(使用LruCache  least recently use最近最少使用算法)
(2).本地缓存,次优先加载,速度快(使用File)
(3).网络缓存,不优先加载,速度慢,浪费流量


17.Fragment嵌套多个Fragment会出现bug吗?
(1)突变的动画效果
Fragments有一个嵌套的生命周期,导致嵌套的Fragment会在宿主Fragment前执行相应的生命周期,比如onStop。由于宿主Fragment的FragmentManager无法识别嵌套的Fragment。在动画开始执行的时候,嵌套的Fragment的视图树会直接跳过动画阶段,但是由于宿主Fragment的动画还在执行。所以宿主Fragment和嵌套Fragment动画的步调是完全不一致的。

(2)嵌套的Fragment会继承宿主Fragment的instance状态

(3)错乱的onActivityResult传递
问题:onActivityResult回调不会走到嵌套的Fragment里面
解决:宿主Fragment向其内部嵌套的Fragment发送onActivityResult回调。


18.Activity中如何动态添加Fragment

(1).获得FragmentManager实例
FragmentManager fm = getFragmentManager();
(2).获得FragmentTransaction实例,开启事务
FragmentTransaction ft = fm.beginTransaction();
(3).进行碎片的添加/删除等操作
ft.add();
(4).提交
ft.commit();

FragmentManager:能够管理Activity中Fragment

(1)使用findFragmentById()或者findFragmentByTag()获取Activity中的Fragment

(2)使用popBackStack(),将fragment从后台堆栈中弹出

(3)使用addOnBackStackChangeListener()注册一个监听后台堆栈变化的listener

FragmentTransaction:对fragment进行添加,移除,替换,以及执行其它操作

每一个事务都是同时要执行的一套变化,可以在一个给定的事务中设定你想要执行的所有变化,例如:add(),remove(),replace()。然后,要给Activity应用事务,必须调用commit()。

调用commit()并不能立即执行transaction中包含的改变动作,commit()将transaction添加到activity的UI线程队列中,也可以调用executePendingTransaction()来立即执行commit()提供的transaction。



19.内存不足时,怎么保持Activity的一些状态,在那个方法里面做具体操作?

短时间操作可以在onPause()中保存

如果是长时间操作,则可以在onSaveInstanceState(Bundle)中保存。
onSaveInstanceState()在activity转入后台状态之前被调用,也就是在onStop()之前,在onPause()之后。
但是onSaveInstanceState()并不是activity生命周期中的回调方法之一,所以,在activity中被杀死时,并不能保证百分之百执行。


20.ScrollView怎么判断是否滑到底部

滚动到顶部判断:
getScrollY()==0

滚动到底部判断:
View childView = getChildAt(0);
childrenView.getMeasuredHeight() <= getScrollY()+getHeight();

childrenView.getMeasuredHeight()表示子view的高度(实际内容总高度)
getScrollY:当前滚动的y位置
getHeight:scrollview的高度

ScrollView的子view只能有一个。如果有多个view,可以添加一个布局框架,使其子view只有一个。
整个滚动的过程,就好像拿着一个高度为v.getHeight的窗口,从上到下去扫描高度为childrenView.getMeasuredHeight的书本。



21.ViewPager的怎么做性能优化

(1)重用item,在destroyItem中保存被销毁的Item,在instantiateItem中复用item,直接绑定数据即可。

(2)Fragment轻量化
如果ViewPager加载的Fragment都比较轻量,适当精简Fragment的布局,可提高Fragment加载的速度,从而减缓卡顿现象

(3)防止fragment被销毁
ViewPager在切换的时候,如果频繁销毁和加载fragment,就容易产生卡顿现象,阻止fragment的销毁可有效减缓卡顿现象
在PagerAdapter里覆盖destroyItem方法可阻止销毁Fragment
通过PagerAdapter的setOffScreenPageLimit()可以设置保留几个fragment,适当增大参数可防止fragment频繁地被销毁和创建。

(4)Fragment内容延迟加载
在切换到当前Fragment的时候,并不立刻去加载Fragment的内容,而是先加载一个简单的空布局,然后启动一个延时任务,延时时长为T,当用户在该Fragment停留时间超过T时,继续执行加载任务;而当用户切换到其它fragment,停留时间低于T,则取消该延时任务。



22.AsyncTask具体用法

AsyncTask:异步执行任务,不需要子线程和Handler,就可以完成异步操作和刷新UI


(1)继承AsyncTask<Params,Progress,Result>

(2)实现以下几个方法
     onPreExecute():该方法在执行实际的后台操作前被UI thread调用,可以在该方法中做一些准备工作。
     doInBackground(Params...):在onPreExecute()执行后马上执行,该方法运行在后台线程中。主要负责执行那些很耗时的后台计算工作。可以调用publishProgress()来更新实时的任务进度
     onProgressUpdate(Progress...):在publishProgress()被调用后,UI thread将调用这个方法从而在界面展示任务的进展情况
     onPostExecute(Result):在doInBackground()执行完之后,被UI调用,后台的结果通过该方法传递到UI thread。

(3)调用自定义的AsyncTask类生成对象,然后调用execute()执行异步任务。

所以如果Activity被销毁了,onPostExecute()不会被执行。因为UI线程被销毁了,无法调用该方法。




23.View中onTouch, onTouchEvent, onClick的执行顺序

dispatchTouchEvent-->onTouch-->onTouchEvent-->onClick

事件分发的关系:dispatchTouchEvent方法中执行onTouch接口回调,然后根据onTouch方法的返回值判断是否执行onTouchEvent,onTouchEvent方法中执行了onClick接口回调。



24.不使用动画,怎么实现一个动态的View

自定义View,用线程重绘

在自定义View中复写draw(),然后利用postInvalidate()不断刷新自身,刷新时调用onDraw()进行重绘。



25.android的invalidate()和postInvalidate()的更新view的区别

Invalidate()不能直接在子线程中调用,因为它违背了单线程模型,必须在UI线程中调用
postInvalidate()在非UI线程中调用

当一个程序第一次启动时,Android会同时启动一个对应的主线程(main thread),主线程主要负责处理与UI相关的事件,如:用户的按键事件,用户触摸屏幕的事件以及屏幕绘图事件,并把相关的事件分发到对应的组件进行处理,所以主线程通常又被叫做UI线程。

在开发Android应用时必须遵守单线程模型的原则:Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行。(线程没有安全不安全这一说,而是更新UI的方法不是线程安全的,即只能在单线程中完成UI的更新,不能使用多线程。)



26.Assets和raw都能存放资源,它们有什么区别?

相同点:
两者目录下的文件在打包后会原封不动的保存在apk包中,不会被编译成二进制。

不同点:
(1).raw的文件会被映射到R.java文件中,访问的时候直接使用资源ID;assets文件夹下的文件不会被映射到R.java中,访问的时候需要使用AssetManager类。
(2).raw不可以有目录结构,而assets可以有目录结构,也就是assets目录下可以再创建文件夹。

读取文件资源:
(1).读取raw下的文件资源
InputStream is = getResou rces().openRawResource(R.id.filename);
(2).读取assets下的文件资源
AssetManager am = getAssets();
InputStream is = am.open("filename");

AssetManager不能处理超过1MB的文件,不然会报异常,而raw没有这个限制。



27.如何自定义ViewGroup

在Android中,控件可以分为ViewGroup控件和View控件。ViewGroup作为父控件可以包含多个View控件,并管理其中包含的View控件。

一般自定义ViewGroup的流程:
(1).onMeasure():循环遍历测量子view的大小,然后设置自身的大小
(2).onLayout():对子view的位置进行排列


28.什么是MVC模式,MVC模式的好处是什么?

MVC:model+view+control,模型+视图+控制。即把一个应用的输入,处理,输出流程按照model,view,control的方式进行分离,这样一个应用被分为三个层--模型层,视图层,控制层。MVC模式的目的就是实现Web系统的职能分工。

Model层:实现系统中的业务逻辑,通常可以用JavaBean和EJB来实现。
View层:用于与用户的交互,通常用JSP来实现。
Control层:是Model与View之间沟通的桥梁。它可以分派用户的请求并选择恰当的视图以用于显示,同时它也可以解 
                  释用户的输入并将它们映射为模型层可执行的操作。


MVC模式的好处:
(1).各施其职,互不干涉
在MVC模式中,三个层各施其职,所以如果一旦那一层的需求发生了变化,就只需要更改相应的层中的代码而不会影响到其他层中的代码。

(2).有利于开发中的分工

(3).有利于组件的重用
分层后更有助于组件的重用。如控制层可独立成一个能用的组件,视图层也可做成通用的操作界面。



29.JVM和Davlik虚拟机的区别

Davlik虚拟机是Google等厂商合作开发的Android移动设备平台的核心组成部分之一。它可以支持已转换为.dex(即Davlik Executable)格式的Java应用程序的运行,.dex格式是专为Dalvik设计的一种压缩模式,适合内存和处理器速度有限的系统。(dx是一套工具,可以将Java.class转换成.dex格式,一个dex档通常会有多个.class。由于dex有时必须进行最佳化,会使档案大小增加1-4倍,以ODEX结尾。)

(1).Davlik基于寄存器,而JVM基于栈。
基于寄存器的虚拟机对于更大的程序来说,在它们编译的时候,花费的时间更短。JVM字节码中,局部变量会被放入局部变量表中,继而被压入堆栈供操作码进行运算,当然JVM也可以只使用堆栈而不显式的将局部变量存入变量表中。Davlik字节码中,局部变量被赋给65536个可用的寄存器中的任何一个,Davlik指令直接操作这些寄存器,而不是访问堆栈中的元素。

(2).不同于Java虚拟机运行java字节码,Davlik虚拟机运行的是其专有的文件格式dex。
JVM字节码由.class组成,每个文件一个class。JVM在运行的时候为每一个类装载字节码。而Davlik只包含一个.dex文件,这个文件包含了程序中所有的类。Java编译器创建了字节码后,Davlik的dx编译器删除.class文件,重新把它们编译成Davlik字节码,然后把它们写进一个.dex文件中。

(3)Davlik经过优化,允许在有限的内存中同时运行多个虚拟机的实例,并且每一个Davlik应用作为一个独立的Linux进程执行。独立的进程可以防止在虚拟机崩溃的时候所有程序都被关闭。而JVM只能运行一个JVM实例,JVM因平台的不一样,进程也不一样。

(4)Davlik主要是完成对象生命周期管理,堆栈管理,线程管理,安全和异常管理,以及垃圾回收等等重要功能。?



30.应用程序常驻后台,避免被第三方杀掉的方法,讲讲你用过的方法(至少四种)

(1)按照系统那样,生成前台service,在notification栏可一直见到bar,这是系统提供的合法保活方式。

(2)在app的Manifest.xml中设置persistent为true,将app提升为系统核心级别,任何情况下都不会被killed。(只对System app有效)

(3)service设置成START_STICKY,kill后会被重启(等待5秒左右),重传intent,保持与重启前一样。

(4)通过startForeground将进程设置为前台进程,做前台服务,优先级和前台应用一个级别。除非系统内存非常缺,否则此进程不会被kill。(1==4大概)

(5)双进程service:让两个进程互相保护,其中一个service被清理后,另外没被清理的进程可以立即重启进程。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值