- 自定义View执行invalidate()方法,为什么有时候不会回调onDraw
自定义一个view时,重写onDraw。
调用view.invalidate(),会触发onDraw和computeScroll()。前提是该view被附加在当前窗口上
view.postInvalidate(); //是在非UI线程上调用的
自定义一个ViewGroup,重写onDraw。
onDraw可能不会被调用,原因是需要先设置一个背景(颜色或图)。
表示这个group有东西需要绘制了,才会触发draw,之后是onDraw。
因此,一般直接重写dispatchDraw来绘制viewGroup
自定义一个ViewGroupdispatchDraw会调用drawChild
-
- 要做一个尽可量流畅的ListView,你可以做到的优化手段是什么?越详细越多手段越好
- 复用convertView
- 使用ViewHolder
- item中有图片时,异步加载
- 快速滑动时,不加载图片
- item中有图片时,应对图片进行适当压缩
- 分批和分页加载
- 继承viewGroup后必须实现哪些方法,这些方法有谁调用
继承ViewGroup后,IDE会提示提供构造方法和实现onLayout()
方法。
onLayout()
,所以必须实现它;如果执行requestLayout()
请求重新调整位置会调用到onLayout()
- 如何保证Service不被杀死
Android 进程不死从3个层面入手:
- A.提供进程优先级,降低进程被杀死的概率
方法一:监控手机锁屏解锁事件,在屏幕锁屏时启动1个像素的 Activity,在用户解锁时将 Activity 销毁掉。
方法二:启动前台service。
方法三:提升service优先级:
在AndroidManifest.xml文件中对于intent-filter可以通过android:priority = "1000"这个属性设置最高优先级,1000是最高值,如果数字越小则优先级越低,同时适用于广播。 - B. 在进程被杀死后,进行拉活
方法一:注册高频率广播接收器,唤起进程。如网络变化,解锁屏幕,开机等
方法二:双进程相互唤起。
方法三:依靠系统唤起。
方法四:onDestroy方法里重启service:service +broadcast 方式,就是当service走ondestory的时候,发送一个自定义的广播,当收到广播的时候,重新启动service; - C. 依靠第三方
根据终端不同,在小米手机(包括 MIUI)接入小米推送、华为手机接入华为推送;其他手机可以考虑接入腾讯信鸽或极光推送与小米推送做 A/B Test。
- android中进程的优先级?
- 前台进程:即与用户正在交互的Activity或者Activity用到的Service等,如果系统内存不足时前台进程是最后被杀死的
- 可见进程:可以是处于暂停状态(onPause)的Activity或者绑定在其上的Service,即被用户可见,但由于失去了焦点而不能与用户交互
- 服务进程:其中运行着使用startService方法启动的Service,虽然不被用户可见,但是却是用户关心的,例如用户正在非音乐界面听的音乐或者正在非下载页面自己下载的文件等;当系统要空间运行前两者进程时才会被终止
- 后台进程:其中运行着执行onStop方法而停止的程序,但是却不是用户当前关心的,例如后台挂着的QQ,这样的进程系统一旦没了有内存就首先被杀死
- 空进程:不包含任何应用程序的程序组件的进程,这样的进程系统是一般不会让他存在的
- Serializable和Parcelable
序列化,表示将一个对象转换成可存储或可传输的状态。序列化后的对象可以在网络上进行传输,也可以存储到本地。
- Serializable(Java自带):
Serializable是序列化的意思,表示将一个对象转换成可存储或可传输的状态。序列化后的对象可以在网络上进行传输,也可以存储到本地。 - Parcelable(android 专用):
除了Serializable之外,使用Parcelable也可以实现相同的效果,
不过不同于将对象进行序列化,Parcelable方式的实现原理是将一个完整的对象进行分解,
而分解后的每一部分都是Intent所支持的数据类型,这样也就实现传递对象的功能了。
- Json
- JSON的全程是JavaScript Object Notation,也就是JavaScript 对象表示法
- JSON是存储和交换文本信息的语法,类似XML,但是比XML更小、更快,更易解析
- JSON是轻量级的文本数据交换格式,独立于语言,具有自我描述性,更易理解
对象可以包含多个名称/值对,比如:
{"name":"zhangsan" , "age":25}
使用谷歌的GSON包进行解析
在 Android Studio 里引入依赖:
compile 'com.google.code.gson:gson:2.7'
值得注意的是实体类中变量名称必须和json中的值名相同。
json1的解析
我们这里的实体类是Student.class
Gson gson = new Gson();
Student student = gson.fromJson(json1, Student.class);
json2的解析
我们可以解析成int数组,也可以解析成Integer的List。
解析成数组:
Gson gson = new Gson();
int[] ages = gson.fromJson(json2, int[].class);
解析成List:
Gson gson = new Gson();
List<Integer> ages = gson.fromJson(json2, new TypeToken<List<Integer>>(){}.getType);
json3的解析
同样可以解析成List或者数组,我们就直接解析成List.
Gson gson = new Gson();
List<Student> students = gson.fromJson(json3, new TypeToke<List<Student>>(){}.getType);
- Activity/Window/View三者的差别,fragment的特点
Activity像一个工匠(控制单元),Window像窗户(承载模型),View像窗花(显示视图) LayoutInflater像剪刀,Xml配置像窗花图纸。
在Activity中调用attach,创建了一个Window
创建的window是其子类PhoneWindow,在attach中创建PhoneWindow
在Activity中调用setContentView(R.layout.xxx)
其中实际上是调用的getWindow().setContentView()
调用PhoneWindow中的setContentView方法
创建ParentView: \u2028作为ViewGroup的子类,实际是创建的DecorView(作为FramLayout的子类)
将指定的R.layout.xxx进行填充\u2028通过布局填充器进行填充【其中的parent指的就是DecorView】
调用到ViewGroup
调用ViewGroup的removeAllView(),先将所有的view移除掉
添加新的view:addView()
- JVM 和Dalvik虚拟机的区别
- JVM:
.java -> javac -> .class -> jar -> .jar
架构: 堆和栈的架构. - DVM:
.java -> javac -> .class -> dx.bat -> .dex
架构: 寄存器(cpu上的一块高速缓存)
- 怎么考虑数据传输的安全性
- HTTPS和HTTP的区别主要为以下五点:
-
https 用的 443 端口, http 用的 80 端口
-
https协议需要到ca申请证书,一般免费证书很少,需要交费。
-
http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议。
-
http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
-
http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
- SSL协议提供的服务主要有哪些
- 认证用户和服务器,确保数据发送到正确的客户机和服务器。
- 加密数据以防止数据中途被窃取
- 维护数据的完整性,确保数据在传输过正中不被改变。
SSL 证书种类CFCA,GlobalSign,VeriSign ,Geotrust ,Thawte
域名型 https 证书(DVSSL):信任等级一般,只需验证网站的真实性便可颁发证书保护网站;
企业型 https 证书(OVSSL):信任等级强,须要验证企业的身份,审核严格,安全性更高;
增强型 https 证书(EVSSL):信任等级最高,一般用于银行证券等金融机构,审核严格,安全性最高,同时可以激活绿色网址栏。
- 如何让程序自动启动
- Android各版本新特性
Android5.0新特性
- MaterialDesign设计风格
- 支持多种设备
- 支持64位ART虚拟机
Android6.0新特性
- 大量漂亮流畅的动画
- 支持快速充电的切换
- 支持文件夹拖拽应用
- 相机新增专业模式
Android7.0新特性
- 分屏多任务
- 增强的Java8语言模式
- 夜间模式
- Java设计模式- Singleton
1.懒汉(线程安全)
//懒汉public class Singleton {
private static Singleton singleton;
private Singleton() {
}
public static synchronized Singleton getSingleton() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
2.饿汉
//饿汉public class Singleton {
private static final Singleton singleton = new Singleton();
private Singleton () {
}
public static Singleton getSingleton() {
return singleton;
}
}
3.静态内部类
//静态内部类public class Singleton {
private static class SingletonHolder {
private static final Singleton singleton = new Singleton();
}
private Singleton() {
}
public static Singleton getSingleton() {
return SingletonHolder.singleton;
}
}
4.枚举
//枚举public enum Singleton {
INSTANCE;
public void whateverMethod() {
}
}
5.double-lock
//double-lockpublic class Singleton {
private volatile static Singleton singleton;
private Singleton() {
}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized(Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
Scroller原理
Scroller执行流程里面的三个核心方法
mScroller.startScroll()
mScroller.computeScrollOffset()
view.computeScroll()
1、在mScroller.startScroll()中为滑动做了一些初始化准备,比如:起始坐标,滑动的距离和方向以及持续时间(有默认值),动画开始时间等。
2、mScroller.computeScrollOffset()方法主要是根据当前已经消逝的时间来计算当前的坐标点。因为在mScroller.startScroll()中设置了动画时间,那么在computeScrollOffset()方法中依据已经消逝的时间就很容易得到当前时刻应该所处的位置并将其保存在变量mCurrX和mCurrY中。除此之外该方法还可判断动画是否已经结束。