安卓知识点自我梳理

1、面向对象三大特性:封装、继承、多态

2、四大组件:Activity、Service、BroadcastReceiver、ContentProvider


Acticity 生命周期

启动(包括杀死重启):onCreate()—>onStart()—>onResume()

后台(包括锁屏):onPause()—>onStop()

返回前台:onRestart()—>onStart()—>onResume()

解锁:onStart()—>onResume()

Acticity 启动模式

standard 标准模式:无论存在与否,创建新实例,压入栈顶

singleTop 栈顶复用:若位于栈顶,不重新创建实例,并调用onNewIntent();否则新建实例走标准模式

singleTask 栈内复用:一个任务栈中该实例唯一;当有任务栈且存在实例,则调起实例并调用onNewIntent(),任务栈清除此实例上的所有Activity;否则新建实例

singleTask 栈内独占:一个任务栈中只能存在这一个实例,不允许其他Acitivty存在;


Service的启动和生命周期

startService:不依赖context,除非该服务被杀死则一直存在

bindService:依赖context,和context共存亡

防杀策略:

Service设置成START_STICKY,会在kill后5s重启,重传intent

提升优先级,清单中设置android:priority,1000为最高

提升进程优先级,startForeground()

onDestroy方法里重启service


BroadcastReceiver的注册方法及其效果异同

静态注册:在清单文件中注册,app退出后仍可收到广播

动态注册:在代码中注册,当app退出后,广播接收停止


ContentProvider

用于将数据共享给其他应用,需要继承ContentProvider;

其他应用使用getContentResolver进行调用

3、Fragment

在项目中目前主要采用的单Activity + 多Fragment架构


生命周期:和Acitivty的大部分都是相似的

比Acitivty生命周期多出的函数

onAttach(Activity)

当Activity与Fragment发生关联时调用

onCreateView(LayoutInflater,ViewGroup,Bundle);

创建该Fragment的视图

onActivityCreate(bundle);

当Activity的onCreate();方法返回时调用

onDestoryView();

与onCreateView相对应,当改Fragment被移除时调用

onDetach();

与onAttach()相对应,当Fragment与Activity的关联被取消时调用


使用方法:

android.app.Fragment 主要用于定义Fragment

android.app.FragmentManager Fragment管理器

android.app.FragmentTransaction Fragment事务

事务操作:add、remove、replace、hide、show、detach(移除view)、attach(重建view)、commit

4、handler机制

为了避免ANR,我们会通常把 耗时操作放在子线程里面去执行,因为子线程不能更新UI,所以当子线程需要更新的UI的时候就需要借助到安卓的消息机制,也就是Handler机制了。

三个关键:

handler、looper、MessageQueue

Handler 是一个消息分发对象,而消息分发依赖于消息循环 Looper;在一个线程中,Looper 阻塞线程,等待Message消息构成循环,有了消息,分配到对应的 Handler,让他进一步分发处理。

工作过程:

主线程创建时就会创建looper,而looper会开启消息队列;

当handler发送消息时,是调用MessageQueue插入一条消息;looper在不断轮询发现message,交给handler处理。

5、AsyncTask机制

AsyncTask是对Handler和Thread的封装,使用它编码更简洁,效率更高。

AsyncTask封装了ThreadPool线程池,实现了线程的复用,比直接使用Thread效率更高。

AsyncTask是定义异步任务在后台线程(子线程中)运行的,而结果更新UI在UI线程中;

接收三个参数,Params(传入的值)Progress(进度) Result(返回的结果);

有四步onPreExecute(在UI线程中执行,准备操作)doInBackground(子线程中耗时操作)onProgressUpdate (进度更新)onPostExecute(结果返回)

6、事件分发机制

android事件分发机制 就是一个触摸事件发生了,从一个窗口传递到一个视图,再传递到另外一个视图,最后被消费的过程。


dispatchTouchEvent:负责事件分发

return true:消费事件,停止传递;

return false:回归到父View的onTouchEvent进行处理

super:

调用 onInterceptTouchEvent拦截处理(viewgroup);

调用自己的onTouchEvent(View)


interceptTouchEvent:负责事件拦截(只有viewgroup中有)

return true:将事件给自己的onTouchEvent处理

return false、super:继续向下传递事件


onTouchEvent:负责事件处理

return true:消费事件,停止传递;

return false、super:回归到父View的onTouchEvent进行处理


安卓知识点自我梳理_第1张图片

7、自定义控件


view的绘制流程:

onMeasure:计算大小

onLayout:计算位置

onDraw:绘制


自定义控件的实现方法:

通过继承已有的控件来实现:适用于对原生控件的扩展需求

通过引用布局文件来实现:做组合控件可以用此方法

继承View实现:实现完全自定义的控件


增加属性:

通过构造函数中引入的AttributeSet 去查找XML布局的属性名称,然后找到它对应引用的资源ID去找值;

通过XML为View注册属性,与Android提供的标准属性写法一样

8、ANR问题


容易出现的情况:

高耗时的操作,如图像变换

磁盘读写,数据库读写操作

大量的创建新对象


此问题避免:

UI线程尽量只做跟UI相关的工作

耗时的操作(比如数据库操作,I/O,连接网络或者别的有可能阻塞UI线程的操作)把它放在单独的线程处理

尽量用Handler来处理UIThread和别的Thread之间的交互


如何解决:

使用AsyncTask

在doInBackground()方法中执行耗时操作

在onPostExecuted()更新UI

使用Handler实现异步任务

在子线程中处理耗时操作

处理完成之后,通过handler.sendMessage()传递处理结果

在handler的handleMessage()方法中更新UI

或者使用handler.post()方法将消息放到Looper中

9、Andrid oom和图片的三级缓存


Andrid oom原因:

加载对象过大

相应资源过多,来不及释放

在实际开发中经常在未作处理的加载过大图片时出现


关于内存引用:

强引用:一般垃圾回收器不回收被强引用的对象

软引用:内存不足的时候,对象被回收(一般用于允许被回收的对象,当内存不够时会回收)

弱引用:GC只要发现一个对象的引用是全部是弱引用,就会回收此对象、释放内存


Andrid oom解决方法:

尽量不加载过大的图片,可以压缩图片分辨率或大小再进行加载;

利用软引用声明图片对象并用map保存缓存,可以在内存吃紧的时候适当回收掉一些引用图片;

利用LruCache来进行图片的内存缓存。当缓存的图片达到了预先设定的值的时候,那么近期使用次数最少的图片就会被回收掉


图片三级缓存:

网络加载,仅第一次,不优先加载,速度慢,浪费流量

本地缓存,次优先加载,速度快

内存缓存,优先加载,速度最快

首次加载 Android App 时,肯定要通过网络交互来获取图片,之后我们可以将图片保存至本地SD卡和内存中

之后运行 App 时,优先访问内存中的图片缓存,若内存中没有,则加载本地SD卡中的图片

总之,只在初次访问新内容时,才通过网络获取图片资源

目前都是通过一些图片第三方框架来实现三级缓存,方便快捷效果好,例如frecro、picasso等。

10、RecyclerView和ListView的异同


ViewHolder是用来保存视图引用的类,无论是ListView亦或是RecyclerView;

只不过在ListView中,ViewHolder需要自己来定义,不过非必须,只不过不使用ViewHolder的话,ListView每次getView的时候都会调用findViewById(int),这将导致ListView性能展示迟缓。

而在RecyclerView中使用RecyclerView.ViewHolder则变成了必须,尽管实现起来稍显复杂,但它却解决了ListView面临的上述不使用自定义ViewHolder时所面临的问题。


ListView只能在垂直方向上滚动,Android API没有提供ListView在水平方向上面滚动的支持;

但是RecyclerView相较于ListView,在滚动上面的功能扩展了许多。它可以支持多种类型列表的展示要求,主要如下:

LinearLayoutManager,可以支持水平和竖直方向上滚动的列表。

StaggeredGridLayoutManager,可以支持交叉网格风格的列表,类似于瀑布流或者Pinterest。

GridLayoutManager,支持网格展示,可以水平或者竖直滚动,如展示图片的画廊。

11、java GC


发现无用信息对象;

回收被无用对象占用的内存空间,使该空间可被程序再次使用。


引用计数法(Reference Counting Collector)

引用计数法是唯一没有使用根集的垃圾回收的法,该算法使用引用计数器来区分存活对象和不再使用的对象。一般来说,堆中的每个对象对应一个引用计数器。当每一次创建一个对象并赋给一个变量时,引用计数器置为1。当对象被赋给任意变量时,引用计数器每次加1当对象出了作用域后(该对象丢弃不再使用),引用计数器减1,一旦引用计数器为0,对象就满足了垃圾收集的条件。

两个对象相互引用存在问题,这时引用计数法则不会进行gc。

另外有根集的算法对此情况进行解决,若两个相互引用的对象没有被根对象间接或直接的引用,那么会被回收

12、SharedPreferences原理


getSharedPreferences()

初始化映射对象:

ContextImpl 包含了一个比较复杂的内部全局私有变量sSharedPrefs,类型是ArrayMap,就是从包名映射到preference的集合。

创建包名下的一个preference集合映射

创建SharedPrefs文件:

根据文件名构建一个File的prefsFile对象,通过此对象创建一个SharedPreferencesImpl实例


SharedPreferencesImpl()

构建函数中调用makeBackupFile和startLoadFromDisk

makeBackupFile生成一个prefsFile的备份文件

startLoadFromDisk将文件异步读取到内存

至此,SharedPreferences创建成功


获取原理

SharedPreferencesImpl中的getString()方法,通过key拿取map中的值


修改原理

edit()

SharedPreferencesImpl的edit()函数返回的是一个新建EditorImpl类的对象。

SharedPreferencesImpl.EditorImpl类里面有一个关键的变量mModified,这是一个Map,它会将以后要修改的值都放到里面去

editor.putString()

要保存的值存入EditorImpl类里的变量mModified里。

editor.commit()

提交修改,将map中的数据写入文件

步骤:

调用commitToMemory()

MemoryCommitResult类是一个封装了commitmemory结果的一个类,里面有许多信息。

commitToMemory首先创建一个MemoryCommitResult对象。接着将mMap对象赋值给MemoryCommitResult对象中的map,接下来我们就会对mMap里面的值进行修改,在修改完成后会把之前我们所进行修改临时保存的全局变量mModified进行清空处理。然后返回出去MemoryCommitResult对象。

在commitToMemory返回一个结果类后会将它当作参数传入enqueueDiskWrite()函数里。

enqueueDiskWrite()

enqueueDiskWrite()函数里面执行的是一个异步操作,在外部commit()函数会做一个await操作等待异步的完成。

在这个函数里会开启一个writeToDiskRunnable的线程,该线程做的事情是将传进来的MemoryCommitResult 里的数据写入到文件里。

writeToFile()

此函数首先会判断mFile文件是否存在,如果存在就再判断备份文件是否存在,备份文件不在的话就创建一个备份文件,然后删除原文件。

接着创建一个mFile的文件,将数据写入,再添加权限,做完后将备份文件删除。

13、java排序理解


冒泡:

一趟比较的过程,从后往前,比较相邻数的大小,小的往前排;

小的数继续和前面相邻数比较,直到最前,一趟完成,最小的数已经在顶部;

以此类推,每一趟的小数都浮起来,再进行数趟,从小到大,排序完成。

一句话理解:每一次都是最轻的气泡从最下面浮上来。


选择:

一趟比较的过程,首先从全部数中找到最小的,将最小的与顶部交换位置,最小的已在顶部;

之后从剩下数组中继续挑选最小的,排到剩下数组的顶部,即为全部数组的第二位;

以此类推,每一趟的小数都向前排了,进行数趟,从小到大,排序完成。

一句话理解:每一次选择最小的数然后放在前面。


插入:

一趟比较的过程,从顶部开始,首先比较前两个数,然后小的数在前,这两个数排序完成;

之后让紧挨着已排序组的数,去已排序组中挨个比较大小,然后替换位置;

类似是这个数插入到已排序数组的效果。进行数趟,从小到大,排序完成。

一句话理解:每一次按照顺序拿数插入前面已经排序好的数里面。

你可能感兴趣的:(安卓知识点自我梳理)