没想到要久违地学习安卓的知识了。
先来复习一下最基础的知识:
安卓的四大组件分别是:
Activity是安卓的四大组件之一,我们平时使用Activity的时候总是后来的Activity覆盖在先来的上面,撤销的时候会逐级返回,这非常容易让我们想到栈的数据结构,事实也正是如此,这个用于管理Activity的栈被称为返回栈。
每个Activity在其生命周期中一共有4中状态:
Activity类中定义了7个回调方法,覆盖了Activity生命周期的每一个环节。
上面说到,处于停止状态的Activity是会被系统回收的,那么当我们重新返回上一个Activity的时候,这个被回收的Activity还会显示吗?
答案是会显示,但是这是一个重新调用onCreate的Activity,所以并不会保存之前填入的一些信息,如果想要保存这些信息,可以调用onSaveInstanceState()方法暂时保存一下。
onSaveInstanceState()携带一个Bundle类的参数用于保存一些数据。
Activity一共有4种启动模式:
安卓的布局分为三种:LinearLayout、RelativeLayout以及FrameLayout。
Fragment,碎片,主要用于填充Activity。
由于各种手机、平板的尺寸大小各不相同,如果都采用相同的Activity会导致很多机型上的组件和视图被拉长,不太美观,这种情况下,安卓3.0引入了Fragment用于填充不同的屏幕。
和Activity一样,Fragment也存在生命周期。
由于Fragment是完全依赖于Activity的,所以生命周期也取决于Activity的生命周期。
Activity有的回调函数,Fragment也都有,并且Fragment增加了额外几种回调函数。
安卓中的广播机制是非常灵活的,每个应用都可以对自己关心的广播进行注册,一旦当一个事件发生的时候,就能接收到这个事件的广播。除此之外,应用程序也可以自己发送广播。
安卓中的广播主要分为两种:
ContentProvider主要用于在不同的进程之间实现数据共享的功能,由于是多个进程,所以他也是线程安全的,当然ContentProvider也涉及到一个权限的问题。
安卓有已经实现好的ContentProvider类,可以通过Context中的getContentResolver()
方法来获取该类的实例。ContentProvider提供了update()
、insert()
、delete()
、query()
用于增删改查,这和数据库非常相似(安卓其实也有一个内嵌的轻量级关系型数据库,叫做SQLite,操作方法也与之相似)。
ContentProvider通过URI(资源定位符,我们在http中已经见识过他了)定位想要查询的资源。
除了使用安卓自带的ContentProvider,我们也可以通过继承的方式覆盖他的增删改查和初始化函数,来自定义一个自己的ContentProvider。
终于到了最后一个组件了,Service是一个用于在后台执行任务的组件,所以很显然说到Service离不开多线程。
和我们熟悉的WPF一样,安卓应用虽然是一个支持多线程的进程,但是对于UI的更新操作只能由主线完成。所以子线程想要修改UI,就得异步地委托给主线程进行修改,在安卓中可以通过继承AsyncTask来完成。
说完了子线程更新UI,我们再回到Service上面来,想要实现一个Service也非常简单,只要继承Service类就行了,Service类中有一个抽象方法:onBind()
,这是一个必须由子类实现的方法,这个方法用于Activity和Service之间的通信。
除此之外,一般会覆盖Service的onCreate()
方法、onStartCommand()
方法和onDestory()
方法。第一个是创建Service时调用的方法,第二个是每次启动Service都会调用方法,最后一个则是在销毁的时候调用的方法。
当然Service除了可以在后台执行任务,它也可在前台执行一些任务。
从安卓8.0开始,如果一个应用不在前台的话,它的Service也是可能会被系统回收的,但是这样对于一些比如网易云音乐之类需要在后台运行的程序来说就没有那么友好了。
为了解决这个问题,Service还可以运行在前台,当一个前台Service运行的时候,他会像通知一样显示在状态栏里,可以通过下拉来显示更加详细的信息。
上面说到的Service其实都是在主线程里运行的,如果想要单独起一个线程来执行任务,可以使用IntentService。
说到多线程,那么不得不提到这些线程是如何通信的了。
在安卓中使用了一个叫做handler的机制进行消息的异步发送和接受,有点类似于消息队列,它一共分为4个部分:
使用Handler有一个需要注意的地方就是,它需要被声明为静态类,不然会引起OOM,因为非静态内部类和匿名类的Handler会使得引用的类无法被回收,从而导致OOM。
Kotlin是最近几年刚被声称为安卓开发一级语言,Kotlin起源于Java,它的原理就是把自己的代码编译(确切的说是解释)为虚拟机可以识别的Class文件,反正虚拟机并不关心它的Class文件是如何生成的,照着执行就是了。除此之外,Kotlin可以完美支持Java的第三方库,所以这个语言在国外迅速得到了青睐。
当然最重要的一点,Kotlin可以选择一个变量是否能为Null,所以这在一定程度上解决了很多空指针异常。
这边就简单介绍一下基本的语法:
//可变成员变量
//Kotlin不需要以;结尾
var a = 10
//不可变成员变量
val b = 10
//指定类型,并且声明是可以为null的
//在Kotlin不显示指定?的变量都是不能为null的
fun doStudy(study:Study?){
//?.判空工具
//let函数将变量本身传递进函数并且立即执行
//it是lambda表示式在单个变量的时候的替代关键字
study?.let{
it.readBook()
}
}
JetPack是一个开发组件工具集,在2018年由谷歌推出,可以帮助程序员编写出更加简洁的代码。
MVVM(Model-View-ViewModel)是谷歌官方推荐的架构,他也包含在JetPack中,和MVC类似,主要是对View(视图)和Model(模型)之间相互转化,只不过MVC中使用的是Controller,MVVM中使用的是ViewModel。
现在的Android采用了一个叫做ART的虚拟机,它基于JVM,但是缺不满足JVM的规范,所以算是一个魔改的JVM。
由于JVM中经常需要在栈中读取信息,这在性能较低的移动端上不太合适,所以ART不再采用栈的形式,而是把堆划分为4个不同的区域:
ART的GC也会根据具体情况的不同而选择不同的GC,一共有3种策略:
ART的GC分为3个不同的阶段:
除了对GC进行优化之外,ART还对代码编译进行了优化。在JVM中总是由前端编译器Javac编译成Class文件,然后再交由后端编译器转换为机器码,但是在ART中进行了优化。
Java文件在编译成class文件,然后经过Android平台的dx工具转换为Dex文件后,同Native code(JNI)和资源一起打包成apk,apk安装到手机后解压出Dex文件。Dalvik会通过dexopt工具将Dex优化,成为Odex文件,Odex文件的效率比Dex高,但其中大部分代码仍然需要每次执行时编译;而ART则会将Dex通过dex2oat工具编译得到一个ELF文件,它是一个可执行的文件。
安卓基础的部分先补充到这边,感觉网上很多人都瞎讲,根本不知道对不对,之后还是买本书慢慢学吧,这种东西也一口吃不成胖子。