MVC,MVP,MVVM的区别
-
MVC
软件可以分为三部分 视图(View):用户界面 控制器(Controller):业务逻辑 模型(Model):数据保存 各部分之间的通信方式如下: View传送指令到Controller Controller完成业务逻辑后,要求Model改变状态 Model将新的数据发送到View,用户得到反馈 Tips:所有的通信都是单向的。 互动模式 接受用户指令时,MVC可以分为两种方式。一种是通过View接受指令,传递给Controller。 另一种是直接通过Controller接受指令
-
MVP
MVP模式将Controller改名为Presenter,同时改变了通信方向。 各部分之间的通信,都是双向的 View和Model不发生联系,都通过Presenter传递 View非常薄,不部署任何业务逻辑,称为"被动视图"(Passive View),即没有任何主动性,而Presenter非常厚,所有逻辑都部署在那里。
-
MVVM
MVVM模式将Presenter改名为ViewModel,基本上与MVP模式完全一致。 唯一的区别是,它采用双向绑定(data-binding):View的变动,自动反映在ViewModel,反之亦然。
请解释下在单线程模型中Message,Handler,Message Queue,Looper之间的关系
Handler是Android官方给我们提供的一套更新UI线程的机制,也是一套消息处理机制,可以通过Handler来处理消息,更新UI等。
拿主线程来说,主线程启动时会调用Looper.prepare()方法,会初始化一个Looper,放入Threadlocal中,接着调用Looper.loop()不断遍历Message Queue,
Handler的创建依赖与当前线程中的Looper,如果当前线程没有Looper则必须调用Looper.prepare()。Handler , sendMessage到MessageQueue,Looper不断
从MessageQueue中取出消息,回调handleMessage方法。
面试题:有没有用过自定义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进行处理。
怎么启动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退出后,也就没办法再接受广播了。
面试题:动画有哪些类型,动画的区别?
在Android3.0以前,动画有两种类型,一种是补间动画,即tween,他指的是通过自身的变形达到的效果,比如说透明度的变化,放大缩小等,
还有一种是帧动画,即Frame,是通过一针一针的对图片进行连贯起来播放的,Android3.0的时候定义了一个属性动画,即
PropertyAnimation,指的是控件的真实移动,就是不断的改变某些属性的值进行的。具体可以通过实现ValueAnimator等类进行实现。
如果后台的Activity由于某原因被系统回收了,如何在被系统回收之前保存当前状态?
重写onSaveInstanceState()方法,在此方法中保存需要保存的数据,该方法将会在activity被回收之前调用。通过重写
onRestoreInstanceState()方法可以从中提取保存好的数据
描述一下android的系统架构
android系统架构分从下往上为linux 内核层、运行库、应用程序框架层、和应用程序层。
简述 android 应用程序结构是哪些
1)main code
2) unit test
3)mianifest
4)res->drawable,drawable-xxhdpi,layout,value,mipmap
mipmap 是一种很早就有的技术了,翻译过来就是纹理映射技术.
google建议只把启动图片放入。
5)lib
6)color
什么是ANR 如何避免它?
1). KeyDispatchTimeout(5 seconds) --主要类型按键或触摸事件在特定时间内无响应
2). BroadcastTimeout(10 seconds) --BroadcastReceiver在特定时间内无法处理完成
3). ServiceTimeout(20 seconds) --小概率类型 Service在特定的时间内无法处理完成
答:ANR:Application Not Responding。在Android中,活动管理器和窗口管理器这两个系统服务负责监视应用程序的响应,当用户
操作的在5s内应用程序没能做出反应,BroadcastReceiver在10秒内没有执行完毕,就会出现应用程序无响应对话框,这既是ANR。
避免方法:Activity应该在它的关键生命周期方法(如onCreate()和onResume())里尽可能少的去做创建操作。潜在的耗时操作,例如
网络或数据库操作,或者高耗时的计算如改变位图尺寸,应该在子线程里(或者异步方式)来完成。主线程应该为子线程提供一个
Handler,以便完成时能够提交给主线程。
1)避免在activity里面做耗时操作,oncreate & onresume
2)避免在onReceiver里面做过多操作
3)避免在Intent Receiver里启动一个Activity,因为它会创建一个新的画面,并从当前用户正在运行的程序上抢夺焦点。
4)尽量使用handler来处理UI thread & workthread的交互。
如何避免 OOM 异常
首先OOM是什么?
当程序需要申请一段“大”内存,但是虚拟机没有办法及时的给到,即使做了GC操作以后
这就会抛出 OutOfMemoryException 也就是OOM
Android的OOM怎么样?
如何避免OOM
减少内存对象的占用(减少bitmap的内存占用)
内存对象的重复利用(listView的复用)
ListView的优化方案
1、如果自定义适配器,那么在getView方法中要考虑方法传进来的参数contentView是否为null,如果为null就创建contentView并返回,
如果不为null则直接使用。在这个方法中尽可能少创建view。
2、给contentView设置tag(setTag()),传入一个viewHolder对象,用于缓存要显示的数据,可以达到图像数据异步加载的效果。
3、如果listview需要显示的item很多,就要考虑分页加载。比如一共要显示100条或者更多的时候,我们可以考虑先加载20条,等用户拉到列
表底部的时候再去加载接下来的20条。
屏幕适配的方式:
xxxdpi, wrap_content,match_parent. 获取屏幕大小,做处理。
dp来适配屏幕,sp来确定字体大小
weight,这是权重的适配。
AndroidAutoLayout和百分百布局
AsyncTask原理
AsyncTask是对Handler与线程池的封装
BroadcastReciver和EventBus区别
EventBus又是什么鬼呢?EventBus是一个发布 / 订阅的事件总线。
EventBus通过反射来调用订阅
事件分发机制
我们知道事件拦截的顺序,父ViewGroup先接收到拦截,再传递给子ViewGroup 或子View。事件的处理顺序是,子ViewGroup 或子View先处理,若子ViewGroup处理了,父ViewGroup就不用处理,若子ViewGroup未处理,则传给父ViewGroup处理。
其实当你触摸到控件时,就会调用dispatchTouchEvent方法,以前面点击Button为例,当我们点击该按钮时,应用会去Button的类中寻找该方法,发现没有,就会继续往上找,找到容纳该button的TextView时,发现该类中仍没有该方法,最后继续往上寻找,找到View这时发现了该方法:
dispatchTouchEvent->onInterceptTouchEvent->onTouchEvent
首先我们必须了解三个方法
1.dispatchTouchEvent
2interceptTouchEvent
3.TouchEvent
下面先介绍第一个:dispatchTouchEvent
public boolean diapatchTouchEvent
当返回true //执行自己
返回 false //执行 onTouchEvent
默认 是执行 interceptTouchEvent
public boolean interceptToouchEvent
当返回 true //由他自己的OnTouchEvent处理
返回 false //继续分发
public boolean OnTouchEvent
返回 true 自己处理
返回 false 继续传递分发
默认继续传递
在view类中有dispatchTouchEvent和onTouchEvent两个方法
而ViewGroup是继承View,包含这两个方法,并且还包含onInterceptTouchEvent方法
从用户点击屏幕开始触发一个系列的点击事件时,事件真正的传递流程是:Activity(PhoneWindow)->DecorView->ViewGroup->View,在到达ViewGroup之前还有一个DecorView,事件是从Activity传过来的,但这些东西其实和ViewGroup的原理是一样的,Activity能看做一个大的ViewGroup,当它的DecorView包含的所有子View没有人能够消耗事件的时候(这样说有漏洞,大家懂我的意思就行了)最后还是会交给Activity处理。
-
如何不被拦截
如果ViewGroup的onInterceptTouchEvent(ev) 当ACTION_MOVE时return true ,即拦截了子View的MOVE以及UP事件;
此时子View希望依然能够响应MOVE和UP时该咋办呢?
Android给我们提供了一个方法:requestDisallowInterceptTouchEvent(boolean) 用于设置是否允许拦截,我们在子View的dispatchTouchEvent中直接这么写:
前面我们了解到了我们的View是树形结构的,基于这样的结构,我们的事件可以进行有序的分发。
事件收集之后最先传递给 Activity, 然后依次向下传递,大致如下:
Activity -> PhoneWindow -> DecorView -> ViewGroup -> ... -> View
这样的事件分发机制逻辑非常清晰,可是,你是否注意到一个问题?如果最后分发到View,如果这个View也没有处理事件怎么办,就这样让事件浪费掉?
当然不会啦,如果没有任何View消费掉事件,那么这个事件会按照反方向回传,最终传回给Activity,如果最后 Activity 也没有处理,本次事件才会被抛弃:
Activity <- PhoneWindow <- DecorView <- ViewGroup <- ... <- View