1. 项目中如何设置页面跳转动画
使用属性动画,在清单文件中application目录下设置Android:theme="@style/AppTheme"
使用style方式item下定义activity切换动画
2. NDK,JDK,ADT,ANT
JDK: Java语言的软件开发工具包,Java核心,包括Java运行环境、类库、Java开发工具,简单的说JDK就是面向Java开发人员使用的SDK
NDK:(Native Development Kit)跟android SDK差不多也是一个开发工具包,是用来给安卓手机开发软件用的,但是和SDK不同的是它用的是C语言,而android SDK用的是Java语言
ADT :(Android Developer Tools),安卓开发工具,Google研发的一个插件,集成在eclipse中,为安卓开发提供专属开发环境,简单的说ADT就是Android在Eclipse上的开发工具,在Eclipse和SDK之间起到了一个桥梁的作用;
ANT:是Apache的一个项目管理工具,是一个可将软件编译、测试、部署等步骤联系在一起加以自动化的工具,大多用于Java环境中的软件开发。
3. AsyncTask异步任务
和handler一样是用来处理异步任务的,不过相对于handler,AsyncTask的代码更加轻量级,AsyncTask的后台是一个线程池,在异步任务数据比较庞大的时候,线程池的结构优势就体现出来了。
相关方法:
三个重写方法:
doInBackground
onPreExecute
onProgressUpdate
注意事项:
4. 如何捕获未捕获的异常:
Bug 收集工具Crashlytics
1.Crashlytics 不会漏掉任何应用崩溃信息。
2.Crashlytics 可以象Bug 管理工具那样,管理这些崩溃日志。
3.Crashlytics 可以每天和每周将崩溃信息汇总发到你的邮箱,所有信息一目了然。
5. ScrollView嵌套ListView出现的问题
这种情况是当ScrollView嵌套ListView时,ListView的高度设置为wrap_content时会产生,一般情况下ListView只显示的第一个Item。
解决方法一:覆写ListView的onMeasure方法:
解决方法二:在Activity中动态修改ListView的高度,注意当ListView的子item需要根布局是LinearLayout,或需要为一个View,因为有些布局中没有measure这个方法,比如RelativeLayout。
6.序列化和反序列化
序列化:把Java对象转换为字节序列的过程
反序列化:把字节序列恢复为Java对象的过程
序列化最重要的作用:
在传递和保存对象时.保证对象的完整性和可传递性。对象转换为有序字节流,以便在网络上传输或者保存在本地文件中。
反序列化的最重要的作用:
根据字节流中保存的对象状态及描述信息,通过反序列化重建对象。
实现过程:
1、实现序列化的必备要求:
只有实现了Serializable或者Externalizable接口的类的对象才能被序列化为字节序列。(不是则会抛出异常)
2、JDK中序列化和反序列化的API:
- java.io.ObjectInputStream:对象输入流。
该类的readObject()方法从输入流中读取字节序列,然后将字节序列反序列化为一个对象并返回。- java.io.ObjectOutputStream:对象输出流。
该类的writeObject(Object obj)方法将将传入的obj对象进行序列化,把得到的字节序列写入到目标输出流中进行输出。
3、实现序列化和反序列化的三种实现:
① 若Student类仅仅实现了Serializable接口,则可以按照以下方式进行序列化和反序列化。
ObjectOutputStream采用默认的序列化方式,对Student对象的非transient的实例变量进行序列化。
ObjcetInputStream采用默认的反序列化方式,对Student对象的非transient的实例变量进行反序列化。② 若Student类仅仅实现了Serializable接口,并且还定义了readObject(ObjectInputStream
in)和writeObject(ObjectOutputSteam out),则采用以下方式进行序列化与反序列化。
ObjectOutputStream调用Student对象的writeObject(ObjectOutputStream
out)的方法进行序列化。
ObjectInputStream会调用Student对象的readObject(ObjectInputStream
in)的方法进行反序列化。③ 若Student类实现了Externalnalizable接口,且Student类必须实现readExternal(ObjectInput
in)和writeExternal(ObjectOutput out)方法,则按照以下方式进行序列化与反序列化。ObjectOutputStream调用Student对象的writeExternal(ObjectOutput
out))的方法进行序列化。 ObjectInputStream会调用Student对象的readExternal(ObjectInput
in)的方法进行反序列化。
7. RecyclerView与listView
ListView
不强制我们实现ViewHolder的,但是后来google建议我们实现ViewHolder模式
原因: 避免每次getView都进行findViewById()操作,因为findViewById()利用的是DFS算法(深度优化搜索),是非常耗性能的
缓存机制: itemView
ListView的缓存有两级,在ListView里面有一个内部类 RecycleBin,RecycleBin有两个对象Active View和Scrap View来管理缓存,Active View是第一级,Scrap View是第二级。Active View:是缓存在屏幕内的ItemView,当列表数据发生变化时,屏幕内的数据可以直接拿来复用,无须进行数据绑定。
Scrapview:缓存屏幕外的ItemView,这里所有的缓存的数据都是’脏的’,也就是数据需要重新绑定,也就是说屏幕外的所有数据在进入屏幕的时候都要走一遍getView()方法。
当Active View和Scrap View中都没有缓存的时候就会直接create view。
ListView的缓存机制相对比较好理解,它只有两级缓存,一级缓存Active View是负责屏幕内的ItemView快速复用,而Scrap View是缓存屏幕外的数据,当该数据从屏幕外滑动到屏幕内的时候需要走一遍getView()方法。
RecyclerView
强制实现ViewHolder
原因:
- 避免多次进行findViewById()的处理。
- 一个ViewHolder对应一个ItemView。这个ViewHolder当中持有对应的ItemView的所有信息,比如说:position;view;width等等,拿到了ViewHolder基本就拿到了ItemView的所有信息,而ViewHolder使用起来相比itemView更加方便
缓存机制: ViewHolder
RecyclerView的缓存分为四级Scrap
Cache
ViewCacheExtension
RecycledViewPool
Scrap对应ListView 的Active View,就是屏幕内的缓存数据,就是相当于换了个名字,可以直接拿来复用。
Cache
刚刚移出屏幕的缓存数据,默认大小是2个,当其容量被充满同时又有新的数据添加的时候,会根据FIFO原则,把优先进入的缓存数据移出并放到下一级缓存中,然后再把新的数据添加进来。Cache里面的数据是干净的,也就是携带了原来的ViewHolder的所有数据信息,数据可以直接来拿来复用。需要注意的是,cache是根据position来寻找数据的,这个postion是根据第一个或者最后一个可见的item的position以及用户操作行为(上拉还是下拉)。
举个栗子:当前屏幕内第一个可见的item的position是1,用户进行了一个下拉操作,那么当前预测的position就相当于(1-1=0),也就是position=0的那个item要被拉回到屏幕,此时RecyclerView就从Cache里面找position=0的数据,如果找到了就直接拿来复用。ViewCacheExtension是google留给开发者自己来自定义缓存的,这个ViewCacheExtension我个人建议还是要慎用,因为我扒拉扒拉网上其他的博客,没有找到对应的使用场景,而且这个类的api设计的也有些奇怪,只有一个public
abstract View getViewForPositionAndType(@NonNull Recycler recycler,
int position, int
type);让开发者重写通过position和type拿到ViewHolder的方法,却没有提供如何产生ViewHolder或者管理ViewHolder的方法,给人一种只出不进的赶脚,还是那句话慎用。RecycledViewPool刚才说了Cache默认的缓存数量是2个,当Cache缓存满了以后会根据FIFO(先进先出)的规则把Cache先缓存进去的ViewHolder移出并缓存到RecycledViewPool中,RecycledViewPool默认的缓存数量是5个。RecycledViewPool与Cache相比不同的是,从Cache里面移出的ViewHolder再存入RecycledViewPool之前ViewHolder的数据会被全部重置,相当于一个新的ViewHolder,而且Cache是根据position来获取ViewHolder,而RecycledViewPool是根据itemType获取的,如果没有重写getItemType()方法,itemType就是默认的。因为RecycledViewPool缓存的ViewHolder是全新的,所以取出来的时候需要走onBindViewHolder()方法。
小结:
ListView有两级缓存,分别是Active View和Scrap View,缓存的对象是ItemView;而RecyclerView有四级缓存,分别是Scrap、Cache、ViewCacheExtension和RecycledViewPool,缓存的对象是ViewHolder。Scrap和Cache分别是通过position去找ViewHolder可以直接复用;ViewCacheExtension自定义缓存,目前来说应用场景比较少却需慎用;RecycledViewPool通过type来获取ViewHolder,获取的ViewHolder是个全新,需要重新绑定数据。
8. Fragment中add与replace的区别
add不会重新初始化fragment,replace每次都会;
添加相同的fragment时,replace不会有任何变化,add会报IllegalStateException 异常;
replace 先 remove 掉相同 id 的所有 fragment,然后在add 当前的这个 fragment,而 add 是覆盖前一个fragment。所以如果使用 add 一般会伴随 hide()和show(),避免布局重叠;
使用 add,如果应用放在后台,或以其他方式被系统销毁,再打开时,hide()中引用的 fragment 会销毁,所以依然会出现布局重叠 bug,可以使用 replace 或使用 add时,添加一个 tag 参数;
9. FragmentPagerAdapter 与 与 FragmentStatePagerAdapter 的区别与使用场景?
FragmentPagerAdapter 的每个 Fragment 会持久的保存在 FragmentManager 中,只要用户可以返回到页面中,它都不会被销毁。因此适用于那些数据 相对静态的页,Fragment 数量也比较少的那种;FragmentStatePagerAdapter 只保留当前页面,当页面不可见时,该 Fragment 就会被消除,释放其资源。因此适用于那些 数据动态性较大、 占用内存较多,多 Fragment 的情况;
10. 说下 Activity 跟 window , view 之间的关系?
Activity 创建时通过 attach()初始化了一个 Window 也就是PhoneWindow,一个 PhoneWindow 持有一个DecorView 的实例,DecorView 本身是一个 FrameLayout,继承于 View,Activty 通过setContentView 将xml 布局控件不断 addView()添加到 View 中,最终显示到 Window 于我们交互;
11. AIDL
IPC的一个轻量级实现,用了对于Java开发者来说很熟悉的语法。Android也提供了一个工具,可以自动创建Stub(类构架,类骨架)。当我们需要在应用间通信时,我们需要按以下几步走:
- 定义一个AIDL接口
- 为远程服务(Service)实现对应Stub
- 将服务“暴露”给客户程序使用
12.