Activity
问:Activity异常退出了怎么办(怎么保存数据)?
重写onSaveInstanceState和onRestoreInstanceState 两个方法
在onSaveInstanceState 用Bundle参数putString
在onRestoreInstanceState 用Bundle参数getString OK
问:Activity是如何显示视图的(源码|亮点)?
每一个Activity都有一个Phone Window对象,
Phone Window中mContentParent为空的时候(如果为空说明我们还没有DecorView,然后调用installDecor,之后我们的DecorView就准备好了)
DecorView就准备好了mContentParent就指向了我们的ContentView(由于是新建的,我们的mContentParent中肯定没有子View,如果不是新建的,我们要先把mContentParent中的子View全部清干净。)
接下来通过反射加载到我们传入的布局,接着下面会通过调用getCallBack得到一个CallBack对象cb,其实这个cb就是我们的Activity
接着会调用Activity的onContentChanged方法,这个方法是一个空实现,然而View已经悄然显示了
问:Activity的回退栈(或启动模式或launchMode)?
Standard 标准模式,没什么好说的每个Activity都进栈先进后出,是我们默认的模式
SingleTop 栈顶复用模式,须要创建的Activity已经处于栈顶时,此时会直接复用栈顶的Activity,我们{占位符}项目中的APP内支付页面是使用的SingleTop,就怕支付页面会因为用户快速连点出现多个支付页的问题,我们{占位符}页面朋友圈也是使用的栈顶复用模式|我们{占位符}页面搜索也是使用的栈顶复用模式。
SingleTask 栈内复用模式,若须要创建的Activity已经处于栈中时,此时不会创建新的Activity,而是将存在栈中的Activity上面的其他Activity所有销毁,使它成为栈顶。我们{占位符}项目返回首页就是用的这种方式,不但省力还省内存。我们{占位符}页面大转盘也是使用SingleTask。
SingleInstance 单栈模式,会创建一个新的任务栈并且站内只有一个Activity并不常用,如果我们把一个Activity设置为singleInstance模式,你会发现它启动时会慢一些,切换效果不好,影响用户体验。它往往用于多个应用之间,例如一个电视launcher里的Activity,通过遥控器某个键在任何情况可以启动,这个Activity就可以设置为singleInstance模式,当在某应用中按键启动这个Activity,处理完后按返回键,就会回到之前启动它的应用,不影响用户体验。
问:你们(项目中)是如何管理Activity的(如何安全退出指定的Activity或如何退出所有Activity|小细节|小亮点)?
创建一个ActivityManager管理类,搞一个ArrayList
给每个Activity添加一个TAG
填加删除都通过ActivityManager里的ArrayList就OK了
动画
问:插值器用过没(插值器的种类有哪些|怎么自定义插值器)?
插值器(Interpolator)决定值的变化模式。
默认种类有:
AccelerateDecelerateInterpolator :在动画开始与结束的地方速率改变比较慢,在中间的时候加速
AccelerateInterpolator:在动画开始的地方速率改变比较慢,然后开始速率变化加快
LinearInterpolator:以常量速率改变
AnticipateInterpolator:开始的时候向后然后向前甩
CycleInterpolator:动画循环播放特定的次数,速率改变沿着正弦曲线
PathInterpolator:动画执行的效果按贝塞尔曲线
anticipateOvershootInterpolator:开始的时候向后然后向前甩一定值后返回最后的值
OvershootInterpolator:向前甩一定值后再回到原来位置
BounceInterpolator:动画结束的时候有弹起效果
自定义自己的动画插值器:写一个类实现Interpolator接口,Interpolator是一个空的接口继承了TimeInterpolator接口,定义getInterpolation方法即可。
问:属性动画是如何实现的(Property Animation或属性动画出现的版本或者关于属性动画的其他问题)?
Android 3.0(API 11)后才提供的一种全新动画模式。
其出现原因为作用对象局限于View,没有改变View的属性,只是改变视觉效果,动画效果单一。
ValueAnimator、ObjectAnimator是其重要的两个类。
ValueAnimator有ofInt、ofFloat、ofObject三个重要的方法。
这三个方法的作用有两个 1. 创建动画实例/ 2. 将传入的多个参数进行平滑过渡:此处传入0和1,表示将值从0平滑过渡到1 ,如果传入了3个Int参数 a,b,c ,则是先从a平滑过渡到b,再从b平滑过渡到c,以此类推,他们内置了估值器。
插值器(Interpolator)决定值的变化模式。
估值器(TypeEvaluator)决定值的具体变化数值。
ObjectAnimator封装了ValueAnimator,自动赋值 给对象的属性从而实现动画;是直接对对象属性进行操作。
ObjectAnimator.ofFloat();至少传三个参数,第一个是需要操作的view,第二个是需要操作的view的属性,第三个不固定,传2个就是a过度到b,传三个就a到b到c,以此类推。
当然了我们还可以将动画组合在一起使用AnimatorSet,AnimatorSet.play() 播放当前动画的同时可以.with() :将现有动画和传入的动画同时执行.after() :将现有动画插入到传入的动画之后执行 .before() : 将现有动画插入到传入的动画之前执行。
问:ObjectAnimator需要操作的view的属性(Property)有
Alpha 控制View的透明度
float TranslationX 控制X方向的位移
float TranslationY 控制Y方向的位移
float ScaleX 控制X方向的缩放倍数
float ScaleY 控制Y方向的缩放倍数
float Rotation 控制以屏幕方向为轴的旋转度数
float RotationX 控制以X轴为轴的旋转度数
float RotationY 控制以Y轴为轴的旋转度数
问:补间动画都有哪些(Tween动画有哪些|怎么旋转、平移、缩放、透明度)?
补间动画由Animation类来实现具体效果,包括平移(TranslateAnimation)、缩放(ScaleAnimation)、旋转(RotateAnimation)、透明度(AlphaAnimation)四个子类,四种变化。
问:项目实现过哪些动画、怎么实现的?
帧动画、补间动画、属性动画都用过
例如下拉刷新时头布局里我们使用了帧动画
{发现}页面有个弹出窗口使用了补间动画,还加入了BounceInterpolator插值器的效果
{下载进度条}使用了属性动画
ViewPager指示器
问:ViewPager指示器你们怎么做的(小细节|小亮点)?
用MagicIndicator这个(库或lib),里面包含了市面上绝大部分效果,实例化以后直接设置就OK了。
或者用NavigationTabStrip这个view做的,导包后,直接在布局里设置就好了,里面包含了市面上绝大部分效果。
问:ViewPager指示器你们怎么做的,不用库的情况下自定义过吗(自定义View|小细节|小亮点)?
首先在values文件夹下新建attrs定义一些参数:
指示器的文字和横线颜色(文字颜色包括被选中的和未被选中的)
文字大小以及横线的高度
tag之间的距离
布局模式,分为平衡模式和间距布局模式。平衡模式是为了所有tag的长度和不足以填满指示器时,将tags平均地进行分布
除此之外,还包括其他的一些常规view的熟悉,比如padding等等等
写一个类继承ViewGroup,用TypedArray对象拿到之前定义的参数,重写onMeasurec用固定写法MeasureSpec的getMode() 和getSize()方法获取父view传递给我们的宽和高的SpecMode和SpecSize后测量
然后就onDraw画layout
计算view的顶部到指示器顶部的距离和底部到横线顶部的距离
追问:怎么计算的?
getMeasuredWidth()减去getPadding左再减去getPadding右
getMeasuredHeight()减去getPadding上再减去getPadding下
计算横向所剩余的空间,再将这些空间平分,作为tag之间的间距和tag与指示器前端和后端的距离 追问:怎么计算的 答:减去view的宽然后平均除就OK了
布局子view
Svn、Git
问:项目里用的SVN还是Git?
svn/git都用
问:代码冲突了怎么办?
改,在AS把冲突的部分解决了再上传,如果没用AS还不是用的SVN,git冲突会包留在文件中,两个部分被==================分割开,去修改整合就OK了。
问:怎么创建分支?
SVN的话直接右键选择Team然后选择创建。合并分支,和切换分支直接右键Team选择
Git的话git checkout -b list 其中-b表示:创建并切换,切会主线就git checkout master
问:怎么代码回滚?
SVN的话就右键选择Revert to this revision 或者Revert 回到上次提交代码
Git的话就git revert HEAD 回到上次提交代码
问:怎么拉取和提交代码?
从服务端拉取代码到本地并自动合并到本地分支
//将新建的文件或者修改过的文件添加到索引库。
$ git add . //别忘记有个点,点前面有个空格
//本地分支代码保存到本地仓库
$ git commit -m " 提交的message"
//查询当前远程的版本
$ git remote -v
//直接拉取并合并最新代码
$ git pull origin master [示例1:拉取远端origin/master分支并合并到当前分支]
$ git pull origin dev [示例2:拉取远端origin/dev分支并合并到当前分支]
从本地提交代码到服务器
$ git push origin dev [示例2:将当前分支提交到远端origin/dev分支]
Fragment
问:Fragment的懒加载是怎么实现的?(为什么要用懒加载|小亮点)
ViewPager的每一个Fragment都需要通过网络拉取数据加载,而ViewPager是默认加载前两项的,很容易造成网络丢包或者网络堵塞等问题,使用懒加载是非常有必要的。
在Fragment中有一个setUserVisibleHint这个方法,它优于onCreate()方法,其中的setUserVisibleHint为ture的时候就说明Fragment可见,这个时候我们就可以进行网络加载,反之则不加载。这就是懒加载
问:Fragment嵌套Fragment容易出现什么问题?
一般不会出现问题
当然有需要注意的点,比如直接在父Fragment的onActivityCreated方法中调用子Fragment更新View的方法就会抛出异常!
因为在父Fragment的onActivityCreated方法中虽然实例化了子Fragment但是子Fragment的生命周期方法并没有被调用
在onStart方法中更新子Fragment View即可
Xutils
问:Xutis有几个模块?(技术选型为什么选)
xutils主要有4个模块:注解模块,网络模块,图片加载模块,数据库模块。
之前项目用过xutils,现在已经弃用几年了,后来出了xutils3又尝试了下还可以
选择它是因为强大而且包也不太大
数据库:而且拥有ORM, 不次于greenDao,当然说法很牵强
Http请求:有了强大的http及其下载缓存、支持超大文件(超过2G)上传
Image:模块的实现相当的简洁, 并且支持回收被view持有但被Mem Cache移除的图片, 减少页面回退时的闪烁,而且支持gif,支持圆角, 圆形, 方形等裁剪, 支持自动旋转...
绑定View:更多的事件注解支持且不受混淆影响...
最重要的是AbsTask和统一的回调接口Callback, 任何异常, 即使咱的回调方法实现有异常都会进入onError, 任何情况下onFinished总会让你知道任务结束了
问:Xutils怎么操作数据库?
用DButils增删改查更新数据库
问:Xutils怎么断点续传?
utils.download的第三个参数设为true
问:Xutils做项目时使用get请求的接口发现明明数据变更了,返回却是上一次的结果,连续好几次,过个一会才能请求到最新数据,遇到过这种情况吗?
没有遇到过。
一般可设置缓存默认过期时间和针对当前请求的过期时间。
sHttpUtils.configCurrentHttpCacheExpiry(0*1000);这样就是不缓存
这样就不会出现过一会子才请求到最新数据了
问:你使用Xutils做项目时就没有遇到过问题吗?
有一些不太方便的地方
有一次,项目{首页}的一个Web接口包含“&”这个特殊的字符
直接报了一个java.net.URISyntaxException
后来把String 直接转成URL就好了
当然以前用的时候也会莫名其妙的报EOFException,貌似是它源码的问题,后来就没报过,应该是被修复掉了
Json
问:可以手写Json吗?
{"firstName": "ba", "lastName": "wei"}
问:会原生解析Json吗?
使用JSONObject 和JSONArray一层一层解析
当然一般都用Gson 或Jackson 和FastJson
ContentProvider
问:你们一般用它来做什么?
进程间进行数据交互and共享,跨进程通信
当然包括跨进程操作某些系统自带进程,比如通讯录、相册等
就是用ContentProvider和ContentResolver增删改查
问:ContentProvider的底层原理是?
ContentProvider的底层是采用 Android中的Binder机制
问:当外部数据发生变化ContentProvider是如何知道的?
通过ContentObserver
它就是一个观察者
枚举类,工具类
问:使用过枚举类吗(Enum)?
不可否认enums会使得代码更易读更安全
当然在编写高效Android代码时避免使用枚举
特别是大型的App中,能不用则不用
因为它会牺牲执行的速度和并大幅增加文件体积
Android官方已经说明了最好不用enums
问:使用过工具类吗(项目中用到了哪些工具类)?
屏幕工具类、
时间获取转换类、
加密工具类、
键盘监听工具类、
图片处理工具类、
网络工具类、
Log日志打印工具类、
SD卡文件处理工具类、
正则验证工具类、
数不胜数,当然也可以依赖最为流行的万能工具类
Retrofit+RxJava
问:使用过Retrofit+RxJava实现网络请求吗?
用过,先说Retrofit吧,先定义一个接口,然后实例化异步请求就OK
常有的操作符有:
GET查找资源
POST 修改资源
PUT ----------上传文件
DELETE ----删除文件
再说RxJava,其实是一个在Java VM上使用可观测的序列来组成异步的、基于事件的程序的库,就是个实现异步的库。Retrofit+RxJava就是再创建Retrofit对象的时候多点出一个方法:addCallAdapterFactory(RxJavaCallAdapterFactory.create(),然后在定义的Retrofit接口里把Call改为Observable,也就是被观察者。然后再创建一个rxjava中的observable,再弄一个观察者subscribe订阅就OK了,当然Retrofit RxJava都是2.0的。
问:能简单说几个Rxjava操作符吗?
创建操作的话有create、from、just、empty、timer等等
合并操作的话有concat、startWith、merge等等,还有zip
过滤操作的话有filter、ofType等
条件操作有all什么的
聚合操作有reduce等
转换操作有toList、toMap
变换操作有map、window
错误处理的话:
处理所有错误用onErrorResumeNext
如果只处理异常用onExceptionResumeNext
阻塞操作的话用forEach
缓存Observable发射的数据序列并发射相同的数据序列给后续的订阅者的话用cache
GreenDao
问:为什么要选择GreenDao?
使用简单、快、还能加密
问:GreenDao怎么使用?
直接在实体类里加注解就OK,每个实体类都会生产一个与之对应的Dao类
用DaoMaster下的DevOpenHelper增insert删delete改update查load
问:GreenDao的注解有哪些呢?
实体@Entity注解:
schema:告知GreenDao当前实体属于哪个schema
active:标记一个实体处于活跃状态,活动实体有更新、删除和刷新方法
nameInDb:在数据库中使用的别名,默认使用的是实体的类名 indexes:定义索引,可以跨越多个列
createInDb:标记创建数据库表
基础属性注解:
@Id:主键 Long 型,可以通过@Id(autoincrement = true)设置自增长
@Property:设置一个非默认关系映射所对应的列名,默认是使用字段名,例如:@Property(nameInDb = "name")
@NotNull:设置数据库表当前列不能为空
@Transient:添加此标记后不会生成数据库表的列
索引注解:
@Index:使用@Index作为一个属性来创建一个索引,通过name设置索引别名,也可以通过unique给索引添加约束
@Unique:向数据库添加了一个唯一的约束 关系注解
@ToOne:定义与另一个实体(一个实体对象)的关系
@ToMany:定义与多个实体对象的关系
问:使用GreenDao遇到哪些问题呢?
更新数据时,一直无法插入
解决办法:如果想要进行数据更新,则必须在创建表时,添加addIdProperty属性,否则会报错抛出异常无法进行数据更新。
进行单条数据查询时uniqueOrThrow()方法会抛出异常导致退出:
解决办法:GreenDao 此方法未对异常进行处理,查询结果为空时会异常退出程序,使用unique()方法,然后对结果为空的情况进行判断。
当使用unique()方法进行数据查询时如果有多条数据存在,则会抛出异常,退出程序:
解决办法:unique()方法别查多条数据
webView
问:JS跟Android怎么互调?
首先Android调用JS的方法
写一个WebView
WebView.getSettings()得到WebSettings
webSettings.setJavaScriptEnabled(true);得到和JS交互的权限
WebView.loadUrl("url");加载JS代码
使用WebView.post(new Runnable() {})
在其中WebView.loadUrl("javascript:JS代码中的方法名()");
第6步也可以替换为WebView.evaluateJavascript()
Android4.4以后使用evaluateJavascript效率更高
可以写个判断4.4之前使用loadUrl,之后使用evaluateJavascript
JS调用Android中的JAVA代码
定义JS需要调用的方法,被JS调用的方法必须加入@JavascriptInterface注解,将JS方法中的对象通过addJavascriptInterface映射进来,WebView.addJavascriptInterface(new 方法名(), "JS中的对象");当然也需要开启JS交互和加载JS布局,之后JS就可以正常调用Android中的方法了,注意方法名和JS中的方法名必须一致。我们也可以用其他方式,Android通过 WebViewClient 的回调方法shouldOverrideUrlLoading ()拦截 url,解析该 url 的协议,如果检测到是预先约定好的协议,就调用相应方法。
问:JS跟Android互调需要注意什么?
Java 调用 Js 里面的函数、效率并不是很高、估计要200ms左右吧、做交互性很强的事情、这种速度很难让人接受、而js去调Java的方法、速度很快、50ms左右、所以尽量用js调用Java方法
Java 调用 Js 里面的函数、没有返回值、调用了就控制不到了
Js 调用 Java 的方法、返回值如果是字符串、你会发现这个字符串是 native的、转成 locale 的才能正常使用、使用 toLocaleString() 函数就可以了、不过这个函数的速度并不快、转化的字符串如果很多、将会很耗费时间
对Web同事的要求网页中尽量不要使用jQuery、执行起来需要5-6秒、最好使用原生的JS写业务脚本、以提升加载速度、改善用户体验
问:为什么要加@JavascriptInterface注解?
4.4之后调用需要在调用方法加入加入@JavascriptInterface注解
如果代码无此申明,那么也就无法使得js生效,也就是说这样就可以避免恶意网页利用js对安卓客户端的窃取和攻击。
问:为什么要用WebViewJavascriptBridge框架?
我们很多时候需要在js记载本地代码的时候,要做一些判断和限制,或者有可能也会做些过滤和对用户友好提示
因此JavascriptInterface也就无法满足我们的需求了,特此有大神就写出了WebViewJavascriptBridge框架
问:怎么加快HTML网页装载完成的速度?
默认情况html代码下载到WebView后,webkit开始解析网页各个节点,发现有外部样式文件或者外部脚本文件时,会异步发起网络请求下载文件,但如果在这之前也有解析到image节点,那势必也会发起网络请求下载相应的图片。网络情况较差的情况下,过多的网络请求就会造成带宽紧张,影响到css或js文件加载完成的时间,造成页面空白loading过久,解决的方法就是告诉WebView先不要自动加载图片,等页面finish后再发起图片加载。
问:怎么解决ViewPager里非首屏WebView点击事件不响应?
继承WebView类,在子类覆盖onTouchEvent方法
ACTION_DOWN的时候写onScrollChanged就OK了
Pulltorefresh
问:使用过Pulltorefresh吗?
项目里用到了PullToRefreshScrollView,在ScrollView下拉刷新时去服务端获取数据并展示,获取数据的过程采用线程池管理线程,进行到该步发现一下拉刷新APP就闪退了,查看Log错误显示ThreadPoolExecutor队列满了RejectedExecutionException,怀疑我的ThreadPoolExecutor容量不够大,虽扩大至20,再次测试依然闪退,仍然是队列已满错误。之后层层源码追看,发现了端倪,onPullDownToRefresh该方法一直不断的在调用,导致ThreadPoolExecutor里面的任务一直变多,导致容量急剧增加,进而闪退。这样问题就很容易解决了在SmoothScrollRunnable当中增加一个标志位,标志我当次已经在初始化中就OK了。
问:使用PullToRefreshScrollView应该不多吧?
一般项目里都是用PullToRefreshListView多一些,现在都用XRecyclerView了,支持下拉上拉,而且还没有List View的错位问题,当然了之前还是用PullToRefresh比较多一点,也会自定义PullToRefresh,不过在定义PullToRefresh的时候也经常遇到一些问题比如写项目的时候,自已定义的时候继承了PullToRefreshBase类实现了相关方法,为recyclerView添加了上拉和下拉功能后。发现正在刷新的时候recyclerView不能滑动。根据事件分发的顺序,我首先想到的就是正在刷新的时候PullToRefreshBase把事件给拦截了,所以查看PullToRefreshBase源码的onInterceptTouchEvent方法,可以看到switch里第一个if条件如果正在刷新并且!mScrollingWhileRefreshingEnabled的时候就对事件进行拦截,所以我们可以尝试看看有没有提供可以改变mScrollingWhileRefreshingEnabled变量的方法。果然,提供了setScrollingWhileRefreshingEnabled方法,所以如果要让自定义的view刷新的时候可以滑动,只需要在初始化的时候setScrollingWhileRefreshingEnabled(true)就ok了。
问:有没有遇到过pullToRefresh数据未充满界面的bug?
项目里的某些遇到过:
Item大于15个的时候
使ListView或RecyclerView设置模式setMode为Mode.BOTH
Item大于等于15个的时候
使ListView或RecyclerView设置模式setMode为Mode.PULL_FROM_START就OK了