Android

面向对象:


封装:隐藏实现细节,提高程序的复用性和维护性

继承:子类继承父类,表明子类拥有父类的属性和方法(注意是public protected修饰符的)

多态:父类引用指向子类对象


Android四大组件:


Activity、Service、ContentProvider、BroadcastReceiver。


Activity生命周期:


onCreate、onStart、onResume、onPause、onStop、onDestroy、onRestart


在Service的生命周期里,常用的有:


手动调用方法作用                                           

startService()启动服务

stopService()关闭服务

bindService()绑定服务

unbindService()解绑服务


内部自动调用的方法作用

onCreat()创建服务

onStartCommand()开始服务

onDestroy()销毁服务

onBind()绑定服务

onUnbind()解绑服务


ContentProvider 是如何实现数据共享的


我们可以定义⼀个类继承 ContentProvider,然后覆写该类的insert、delete、update 等⽅法,在 这些⽅法⾥访问数据库等资源。同时将我们 ContentProvider 注册在 AndroidManifest ⽂件中,其他应 ⽤需要使⽤的时候只需获取 ContentResolver,然后通过 ContentResolver进行对数据库的增删改查


BroadCastReceiver的理解


BroadCastReceiver为广播接收器,它用于接收广播intent。

广播是一种广泛运用在应用程序之间传输信息的机制。而 BroadcastReceiver 是对发送出来的广播进行过滤接收并响应的一类组件;BroadcastReceiver 自身并不实现图形用户界面,但是当它收到某个通知后,BroadcastReceiver可以启动Activity作为响应, 或者通过 NotificationMananger提醒用户,或者启动 Service 等等。


Android五大布局:


线性、相对、绝对、帧、网格

LinearLayout、RelativeLayout、FrameLayout、AbsoluteLayout、TableLayout


Android 的数据存储⽅式


SharedPreference、XML、SQLite、⽂件存储


Android动画:


属性动画:

Android 3.0(API 11)后才提供的一种全新动画模式

其出现原因为作用对象局限于View,没有改变View的属性,只是改变视觉效果,动画效果单一

{下载进度条}使用了属性动画

补间动画:

补间动画由Animation类来实现具体效果,包括平移(TranslateAnimation)、缩放(ScaleAnimation)、旋转(RotateAnimation)、透明度(AlphaAnimation)四个子类,四种变化。

帧动画:

下拉刷新时头布局里我们使用了帧动画


自定义View


自定义控件的实现有三种方式,分别是:组合控件、自绘控件和继承控件

自定义View的流程

1.自定义View的属性(非必需)

2.在View的构造方法中获得我们自定义的属性(非必需)

3.重写onMesure

4.重写onDraw


APP基本性能优化:


快、稳、省、小。

快:使用时避免出现卡顿,响应速度快,减少用户等待的时间,满足用户期望。

稳:减低 crash 率和 ANR 率,不要在用户使用过程中崩溃和无响应。

省:节省流量和耗电,减少用户使用成本,避免使用时导致手机发烫。

小:安装包小可以降低用户的安装成本。

卡顿优化

UI 绘制、应用启动、页面跳转、事件响应

优化建议

布局优化:

减少层级。合理使用 RelativeLayout 和 LinerLayout,合理使用Merge。

提高显示速度。使用 ViewStub,它是一个看不见的、不占布局位置、占用资源非常小的视图对象。

布局复用。可以通过 标签来提高复用。

尽可能少用wrap_content。wrap_content 会增加布局 measure 时计算成本,在已知宽高为固定值时,不用wrap_content 。

删除控件中无用的属性。


避免过度绘制:

布局上的优化。移除 XML 中非必须的背景,移除 Window 默认的背景、按需显示占位背景图片

自定义View优化。使用 canvas.clipRect()来帮助系统识别那些可见的区域,只有在这个区域内才会被绘制。


启动优化:

UI 布局。应用一般都有闪屏页,优化闪屏页的 UI 布局,可以通过 Profile GPU Rendering 检测丢帧情况。

启动加载逻辑优化。可以采用分布加载、异步加载、延期加载策略来提高应用启动速度。

数据准备。数据初始化分析,加载数据可以考虑用线程初始化等策略。


合理的刷新机制:

尽量减少刷新次数。

尽量避免后台有高的 CPU 线程运行。

缩小刷新区域。


内存优化:

在 Android 系统中有个垃圾内存回收机制,在虚拟机层自动分配和释放内存,因此不需要在代码中分配和释放某一块内存,从应用层面上不容易出现内存泄漏和内存溢出等问题,但是需要内存管理。Android 系统在内存管理上有一个 Generational Heap Memory 模型,内存回收的大部分压力不需要应用层关心, Generational Heap Memory 有自己一套管理机制,当内存达到一个阈值时,系统会根据不同的规则自动释放系统认为可以释放的内存,也正是因为 Android 程序把内存控制的权力交给了 Generational Heap Memory,一旦出现内存泄漏和溢出方面的问题,排查错误将会成为一项异常艰难的工作。除此之外,部分 Android 应用开发人员在开发过程中并没有特别关注内存的合理使用,也没有在内存方面做太多的优化,当应用程序同时运行越来越多的任务,加上越来越复杂的业务需求时,完全依赖 Android 的内存管理机制就会导致一系列性能问题逐渐呈现,对应用的稳定性和性能带来不可忽视的影响,因此,解决内存问题和合理优化内存是非常有必要的。

内存分配

在 Android 系统中,内存分配实际上是对堆的分配和释放。当一个 Android 程序启动,应用进程都是从一个叫做 Zygote 的进程衍生出来,系统启动 Zygote 进程后,为了启动一个新的应用程序进程,系统会衍生 Zygote 进程生成一个新的进程,然后在新的进程中加载并运行应用程序的代码。其中,大多数的 RAM pages 被用来分配给Framework 代码,同时促使 RAM 资源能够在应用所有进程之间共享。

但是为了整个系统的内存控制需要,Android 系统会为每一个应用程序都设置一个硬性的 Dalvik Heap Size 最大限制阈值,整个阈值在不同设备上会因为 RAM 大小不同而有所差异。如果应用占用内存空间已经接近整个阈值时,再尝试分配内存的话,就很容易引起内存溢出的错误。

内存回收机制

我们需要知道的是,在 Java 中内存被分为三个区域:Young Generation(年轻代)、Old Generation(年老代)、Permanent Generation(持久代)。最近分配的对象会存放在 Young Generation 区域。对象在某个时机触发 GC 回收垃圾,而没有回收的就根据不同规则,有可能被移动到 Old Generation,最后累积一定时间在移动到 Permanent Generation 区域。系统会根据内存中不同的内存数据类型分别执行不同的 GC 操作。GC 通过确定对象是否被活动对象引用来确定是否收集对象,进而动态回收无任何引用的对象占据的内存空间。但需要注意的是频繁的 GC 会增加应用的卡顿情况,影响应用的流畅性,因此需要尽量减少系统 GC 行为,以便提高应用的流畅度,减小卡顿发生的概率。


常见内存泄漏场景

如果在内存泄漏发生后再去找原因并修复会增加开发的成本,最好在编写代码时就能够很好地考虑内存问题,写出更高质量的代码,这里列出一些常见的内存泄漏场景,在以后的开发过程中需要避免这类问题。

资源性对象未关闭。比如Cursor、File文件等,往往都用了一些缓冲,在不使用时,应该及时关闭它们。

注册对象未注销。比如事件注册后未注销,会导致观察者列表中维持着对象的引用。

类的静态变量持有大数据对象。

非静态内部类的静态实例。

Handler临时性内存泄漏。如果Handler是非静态的,容易导致 Activity 或 Service 不会被回收。

容器中的对象没清理造成的内存泄漏。

WebView。WebView 存在着内存泄漏的问题,在应用中只要使用一次 WebView,内存就不会被释放掉。


优化内存空间

没有内存泄漏,并不意味着内存就不需要优化,在移动设备上,由于物理设备的存储空间有限,Android 系统对每个应用进程也都分配了有限的堆内存,因此使用最小内存对象或者资源可以减小内存开销,同时让GC 能更高效地回收不再需要使用的对象,让应用堆内存保持充足的可用内存,使应用更稳定高效地运行。常见做法如下:

对象引用。强引用、软引用、弱引用、虚引用四种引用类型,根据业务需求合理使用不同,选择不同的引用类型。

减少不必要的内存开销。注意自动装箱,增加内存复用,比如有效利用系统自带的资源、视图复用、对象池、Bitmap对象的复用。

使用最优的数据类型。比如针对数据类容器结构,可以使用ArrayMap数据结构,避免使用枚举类型,使用缓存Lrucache等等。

图片内存优化。可以设置位图规格,根据采样因子做压缩,用一些图片缓存方式对图片进行管理等等。


稳定性优化

Android 应用的稳定性定义很宽泛,影响稳定性的原因很多,比如内存使用不合理、代码异常场景考虑不周全、代码逻辑不合理等,都会对应用的稳定性造成影响。其中最常见的两个场景是:Crash 和 ANR,这两个错误将会使得程序无法使用,比较常用的解决方式如下:

提高代码质量。比如开发期间的代码审核,看些代码设计逻辑,业务合理性等。

代码静态扫描工具。常见工具有Android Lint、Findbugs、Checkstyle、PMD等等。

Crash监控。把一些崩溃的信息,异常信息及时地记录下来,以便后续分析解决。

Crash上传机制。在Crash后,尽量先保存日志到本地,然后等下一次网络正常时再上传日志信息。


ListView优化:


ListView 的优化有多种多样的策略。在我们的项⽬中主要做了如下优化。

1、重⽤ ConvertView,2、给 ConvertView 绑定ViewHolder,3、分页加载数据,4、使⽤缓存。前两个是通⽤的解决⽅案,后两个是针对我们业务的个性化解决⽅案。我们的数据来⾃服务端,如果服务端有 1000 条数据 的话,我们客户端不可能傻⽠式的⼀次性⽤ ListView 把这些数据全部加载进来,因此我们就⽤分页加载 数据,每次加载 20 页,当⽤户请求更多的时候再获取更多数据,⽹络的访问就算⽹速再快也多多少少会有 ⼀定的延迟,因此我们的⽹络请求是异步处理的,同时从⽹络加载来的数据使⽤了 2 级缓存来处理,第⼀级 是内存级别的缓存,第⼆级是本地⽂件的缓存。当 ListView 加载数据的时候⾸先从内存中找,如果找不 到再去本地⽂件中找,只有都找不到的情况下才去请求⽹络。


MVP模式


MVP 模式将Activity 中的业务逻辑全部分离出来,让Activity 只做 UI 逻辑的处理,所有跟Android API无关的业务逻辑由 Presenter 层来完成。

将业务处理分离出来后最明显的好处就是管理方便,但是缺点就是增加了代码量。

在MVP 架构中跟MVC类似的是同样也分为三层。

Activity 和Fragment 视为View层,负责处理 UI。

Presenter 为业务处理层,既能调用UI逻辑,又能请求数据,该层为纯Java类,不涉及任何Android API。

Model 层中包含着具体的数据请求,数据源。

三层之间调用顺序为view->presenter->model,为了调用安全着想不可反向调用!不可跨级调用!


Android多线程:


1. Handler+Thread

2. AsyncTask

3. ThreadPoolExecutor

4. IntentService


Handler+Thread

Android主线程包含一个消息队列(MessageQueue),该消息队列里面可以存入一系列的Message或Runnable对象。通过一个Handler你可以往这个消息队列发送Message或者Runnable对象,并且处理这些对象。每次你新创建一个Handle对象,它会绑定于创建它的线程(也就是UI线程)以及该线程的消息队列,从这时起,这个handler就会开始把Message或Runnable对象传递到消息队列中,并在它们出队列的时候执行它们。

Handler可以把一个Message对象或者Runnable对象压入到消息队列中,进而在UI线程中获取Message或者执行Runnable对象,Handler把压入消息队列有两类方式,Post和sendMessage:

Post方式:

Post允许把一个Runnable对象入队到消息队列中。它的方法有:

post(Runnable)/postAtTime(Runnable,long)/postDelayed(Runnable,long)

对于Handler的Post方式来说,它会传递一个Runnable对象到消息队列中,在这个Runnable对象中,重写run()方法。一般在这个run()方法中写入需要在UI线程上的操作。

sendMessage:

sendMessage允许把一个包含消息数据的Message对象压入到消息队列中。它的方法有:sendEmptyMessage(int)/sendMessage(Message)/sendMessageAtTime(Message,long)/sendMessageDelayed(Message,long)

Handler如果使用sendMessage的方式把消息入队到消息队列中,需要传递一个Message对象,而在Handler中,需要重写handleMessage()方法,用于获取工作线程传递过来的消息,此方法运行在UI线程上。Message是一个final类,所以不可被继承。

优缺点:

1. Handler用法简单明了,可以将多个异步任务更新UI的代码放在一起,清晰明了

2. 处理单个异步任务代码略显多

适用范围:

1. 多个异步任务的更新UI


AsyncTask

AsyncTask是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI主线程。

AsyncTask通过一个阻塞队列BlockingQuery存储待执行的任务,利用静态线程池THREAD_POOL_EXECUTOR提供一定数量的线程,默认128个。在Android 3.0以前,默认采取的是并行任务执行器,3.0以后改成了默认采用串行任务执行器,通过静态串行任务执行器SERIAL_EXECUTOR控制任务串行执行,循环取出任务交给THREAD_POOL_EXECUTOR中的线程执行,执行完一个,再执行下一个。

IntentService

IntentService继承自Service,是一个经过包装的轻量级的Service,用来接收并处理通过Intent传递的异步请求。客户端通过调用startService(Intent)启动一个IntentService,利用一个work线程依次处理顺序过来的请求,处理完成后自动结束Service。

特点

1. 一个可以处理异步任务的简单Service

你可能感兴趣的:(Android)