Skip to content

Commit 0e23acc

Browse files
committed
add architecture components
1 parent 874e2aa commit 0e23acc

8 files changed

+1460
-10
lines changed

AdavancedPart/ART与Dalvik.md

+17-10
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,33 @@
11
ART与Dalvik
22
===
33

4-
ART
5-
---
64

7-
`Android 4.4`提供了一种与`Dalvik`截然不同的运行环境`ART`支持,`ART`源于`google`收购的`Flexycore`的公司。
8-
`ART`模式与`Dalvik`模式最大的不同在于,启用`ART`模式后,系统在安装应用的时候会进行一次预编译,将字节码转换为机器语言存储在本地,
9-
这样在运行程序时就不会每次都进行一次编译了,执行效率也大大提升。
10-
`ART`代表`Android Runtime`,其处理应用程序执行的方式完全不同于`Dalvik``Dalvik`是依靠一个`Just-In-Time` (`JIT`)编译器去解释字节码。
11-
开发者编译后的应用代码需要通过一个解释器在用户的设备上运行,这一机制并不高效,但让应用能更容易在不同硬件和架构上运行。
12-
`ART`则完全改变了这套做法,在应用安装时就预编译字节码到机器语言,这一机制叫`Ahead-Of-Time`(`AOT`)编译。
13-
在移除解释代码这一过程后,应用程序执行将更有效率,启动更快。总体的理念就是空间换时间。
145

156
Dalvik
167
---
178

189
`Dalvik``Google`公司自己设计用于`Android`平台的`Java`虚拟机。它可以支持已转换为`.dex`(即`Dalvik Executable`)格式的`Java`应用程序的运行,
1910
`.dex`格式是专为`Dalvik`设计的一种压缩格式,适合内存和处理器速度有限的系统。`Dalvik`经过优化,允许在有限的内存中同时运行多个虚拟机的实例,
2011
并且每一个`Dalvik`应用作为一个独立的`Linux`进程执行。独立的进程可以防止在虚拟机崩溃的时候所有程序都被关闭。
12+
很长时间以来,`Dalvik`虚拟机一直被用户指责为拖慢安卓系统运行速度不如`IOS`的根源。
13+
`2014``6``25`日,`Android L`正式亮相于召开的谷歌`I/O`大会,`Android L`改动幅度较大,谷歌将直接删除`Dalvik`,代替它的是传闻已久的`ART`
14+
15+
16+
ART
17+
---
18+
19+
`Android 4.4`提供了一种与`Dalvik`截然不同的运行环境`ART`支持,`ART`源于`google`收购的`Flexycore`的公司。
20+
`ART`模式与`Dalvik`模式最大的不同在于,启用`ART`模式后,系统在安装应用的时候会进行一次预编译,将字节码转换为机器语言存储在本地,
21+
这样在运行程序时就不会每次都进行一次编译了,执行效率也大大提升。
22+
23+
`ART`使用`AOT(Ahead Of Time)`(静态编译)而`Dalvik`使用`JIT(Just In Time)`(动态编译)
24+
`JIT`方式会在程序执行时将`Dex bytecode`(`java`字节码)转换为处理器可以理解的本地代码,这种方式会将编译时间计入程序的执行时间,程序执行会显得慢一些。`AOT`方式会在程序执行之前(一般是安装时)就编译好本地代码,因此程序执行时少了编译的过程会显得快一些,但占用更多存储空间,安装时也会更慢。但没针对ART优化的程序反而会运行得更慢,随着`Android L`的普及这个问题迟早会解决。`ART`拥有改进的`GC`(垃圾回收)机制:`GC`时更少的暂停时间、`GC`时并行处理、某些时候`Collector`所需时间更短、减少内存不足时触发GC的次数、减少后台内存占用。
25+
在移除解释代码这一过程后,应用程序执行将更有效率,启动更快。总体的理念就是空间换时间。
26+
2127

2228
`AOT`的编译器分两种模式:
2329
- 在开发机上编译预装应用;
24-
- 在设备上编译新安装的应用,在应用安装时将dex字节码翻译成本地机器码
30+
- 在设备上编译新安装的应用,在应用安装时将`dex`字节码翻译成本地机器码
2531

2632
ART优点:
2733
- 系统性能的显著提升。
@@ -34,6 +40,7 @@ ART缺点:
3440
- 更长的应用安装时间。
3541

3642

43+
3744
3845
---
3946

+129
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
简介(一)
2+
===
3+
4+
应用开发者面临的常见问题
5+
---
6+
7+
在大多数情况下,桌面应用程序在启动器快捷方式中有一个单一的入口并且作为单独的独立进程运行,与桌面应用程序不同的是`Android`应用具有更复杂的结构。一个典型的`Android`应用是由多个应用程序组件构成的,包括`activity``fragment``service``content provider``broadcast receiver`
8+
这些应用程序组件中的大部分声明在`manifest.xml`文件中,用来决定如何将应用融入到用户设备的整体体验中。尽管如前所述,传统的桌面应用程序作为独立进程运行,但是正确的编写`Android`应用程序需要更加灵活,因为用户会同过设备上不同的应用程序组织成自己的方式不断切换流程和任务。
9+
例如,考虑下在你喜欢的社交网络应用中分享照片时会发生什么。该应用会触发一个启动相机的`intent`,从该`intent`会启动一个相机应用来处理这个请求。在此刻,用户离开社交网络应用但是用户的体验是无缝的。相机应用转而可能会触发其它的`intent`例如启动文件选择器,这可能会启动另一个应用。最终用户回到社交网络应用并且分享照片。此外,在这个过程中的任何时刻用户都有可能会被一个电话打断,并且在结束通话后再回来继续分享照片。
10+
`Android`中,这种应用切换行为很常见,所以你的应用程序必须正确处理这些流程。记住,移动设备的资源是有限的,所以在任何时候,操作系统都可能会杀死一些应用为新的应用腾出空间。
11+
其中的重点是应用程序组件可能会被单独和无序的启动,并且可能会被用户或系统在任何时候销毁。因为应用程序组件是短暂的,并且其声明周期(什么时候被创建和销毁)不受你控制,所以不应该在应用程序组件中存储任何应用数据或状态,同时应用程序组件不应该相互依赖。
12+
13+
通用的框架准则官方建议在架构`App`的时候遵循以下两个准则:
14+
15+
- 关注分离
16+
其中早期开发`App`最常见的做法是在`Activity`或者`Fragment`中写了大量的逻辑代码,导致`Activity``Fragment`中的代码很臃肿,十分不易维护。现在很多`App` 开发者都注意到了这个问题,所以前两年`MVP`结构就非常有市场,目前普及率也很高。
17+
18+
- 模型驱动UI
19+
模型持久化的好处就是:即使系统回收了`App`的资源用户也不会丢失数据,而且在网络不稳定的情况下`App`依然可以正常地运行。从而保证了`App`的用户体验。
20+
21+
22+
面对越来越复杂的`App`需求,`Google`官方发布了`Android`框架组件库`(Android Architecture Components)`使`App`的架构更加健壮。
23+
24+
25+
[Android Architecture Components](https://developer.android.com/topic/libraries/architecture/)
26+
[googlesamples/android-architecture-components](https://github.com/googlesamples/android-architecture-components)
27+
28+
> A collection of libraries that help you design robust, testable, and maintainable apps. Start with classes for managing your UI component lifecycle and handling data persistence.
29+
30+
31+
`Android Architecture Components`,简称`AAC`意思就是一个处理`UI`的生命周期 与数据的持久化更加牛逼的架构
32+
33+
- 一个全新的库集合,可帮助您设计强大,可测试和可维护的应用程序。用于管理UI组件生命周期和处理数据持久性。
34+
- 便捷管理App的声明周期:新的生命周期感知(`lifecycle-aware`)组件可帮助您管理`Activity``Fragment`的生命周期。存储配置改变,避免内存泄漏,并使用`LiveData``ViewModel``LifecycleObserver``LifecycleOwner`轻松将数据加载到UI中。
35+
- `Room`:一个`SQLite`对象映射库
36+
37+
38+
平时我们比较熟悉的的架构有`MVC`,`MVP``MVVM`.这些结构有各自的优缺点,以现在比较流行的`MVP`为例, 它将不是关于界面的操作分发到`Presenter`中操作,再将结果通知给`View`接口的实现(通常是 `Activity/Fragment`).
39+
40+
这些结构有各自的优缺点, 以现在比较流行的`MVP`为例, 它将不是关于界面的操作分发到`Presenter`中操作,再将结果通知给`View`接口的实现(通常是`Activity/Fragment`).
41+
`MVP`架构,当异步获取结果时,可能`UI`已经销毁,而`Presenter`还持有`UI`的引用,从而导致内存泄漏
42+
43+
44+
```kotlin
45+
fun getName() {
46+
ExecutorServiceManager.getInstance().execute(Runnable {
47+
try {
48+
TimeUnit.SECONDS.sleep(5)
49+
} catch (e: InterruptedException) {
50+
e.printStackTrace()
51+
}
52+
53+
if (iView != null) {
54+
iView.setName("siyehua")
55+
}
56+
})
57+
}
58+
```
59+
60+
以上代码,`iView`的具体实现是`Activity`,当`Activity`已经执行了`onDestroy()`方法,此时`Runnable`还在获取数据,就会导致内存泄漏.
61+
通常的做法是在给`Presenter`定义一个方法,当`Activity`销毁的时候同时移除对`iView`的引用,完整代码如下:
62+
```kotlin
63+
class PersonPresenter(private var iView: IView?) : IPresenter {
64+
fun getName() {
65+
ExecutorServiceManager.getInstance().execute(Runnable {
66+
try {
67+
TimeUnit.SECONDS.sleep(5)
68+
} catch (e: InterruptedException) {
69+
e.printStackTrace()
70+
}
71+
72+
if (iView != null) {
73+
iView!!.setName("siyehua")
74+
}
75+
})
76+
}
77+
78+
fun removeView() {
79+
iView = null
80+
}
81+
}
82+
```
83+
84+
`Activity`中,代码调用如下:
85+
86+
```kotlin
87+
override fun onDestroy() {
88+
//不移除 View 有可能导致内存泄漏
89+
personPresenter.removeView()
90+
super.onDestroy()
91+
}
92+
```
93+
94+
至此,即可解决`MVP`内存泄漏的问题,但是这么做不够优雅,需要手动管理`Presenter`,当然可以定义基类写入到`BaseActivity`中.
95+
除了有可能引发内存泄漏的风险, 数据持久化也是一个经常困扰我们的问题.通常在屏幕旋转后,`UI`的对象都会被销毁重建,这将导致原来的对象数据不得不重新创建和获取,浪费资源的同时也会影响用户的体验.
96+
通常的解决方法是,通过`SavedInstanceState`来存取数据,但`SavedInstanceState`存储的数据一般比较小,且数据对象还是必须重新构建.
97+
98+
99+
100+
上述两个问题可以通过使用`AAC`架构解决.
101+
102+
103+
`AAC`主要提供了`Lifecycle``ViewModel``LiveData``Room`等功能,下面依次说明:
104+
105+
- `Lifecycle`:生命周期管理,把原先`Android`生命周期的中的代码抽取出来,如将原先需要在`onStart()`等生命周期中执行的代码分离到`Activity`或者`Fragment`之外。
106+
- `LiveData`:一个数据持有类,持有数据并且这个数据可以被观察被监听,和其他`Observer`不同的是,它是和`Lifecycle`是绑定的,在生命周期内使用有效,减少内存泄露和引用问题。
107+
- `ViewModel`:用于实现架构中的`ViewModel`,同时是与`Lifecycle`绑定的,使用者无需担心生命周期。可以在多个`Fragment`之间共享数据,比如旋转屏幕后`Activity`会重新`create`,这时候使用`ViewModel`还是之前的数据,不需要再次请求网络数据。
108+
- `Room`:谷歌推出的一个`Sqlite ORM`库,不过使用起来还不错,使用注解,极大简化数据库的操作,有点类似`Retrofit`的风格。
109+
110+
<img src="https://raw.githubusercontent.com/CharonChui/Pictures/master/final-architecture.png" width="100%" height="100%">
111+
112+
113+
- `Activity/Fragment`
114+
`UI`层,通常是`Activity/Fragment`等,监听`ViewModel`,当`ViewModel`数据更新时刷新`UI`,监听用户事件反馈到`ViewModel`,主流的数据驱动界面。
115+
116+
- `ViewModel`
117+
持有或保存数据,向`Repository`中获取数据,响应`UI`层的事件,执行响应的操作,响应数据变化并通知到`UI`层。
118+
119+
- `Repository`
120+
`App`的完全的数据模型,`ViewModel`交互的对象,提供简单的数据修改和获取的接口,配合好网络层数据的更新与本地持久化数据的更新,同步等
121+
122+
- `Data Source`
123+
包含本地的数据库等,网络`api`等,这些基本上和现有的一些`MVVM`,以及`Clean`架构的组合比较相似
124+
125+
126+
---
127+
128+
- 邮箱 :charon.chui@gmail.com
129+
- Good Luck! `
+159
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
集成(一)
2+
===
3+
4+
5+
首先在`Project`目录中的`build.gradle`中添加`google()`仓库(大部分项目可能都已经有了):
6+
7+
```
8+
allprojects {
9+
repositories {
10+
jcenter()
11+
google()
12+
}
13+
}
14+
```
15+
16+
然后在`app``build.gradle`中添加对应的依赖,如:
17+
18+
```
19+
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
20+
```
21+
如果想要使用`kotlin`开发的话,可以在后面加上`-ktx`后缀就可以了,如下:
22+
```
23+
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
24+
```
25+
26+
`Lifecycle`依赖:
27+
---
28+
29+
`Lifecycle`依赖包括`LiveData``ViewModel`
30+
31+
```
32+
dependencies {
33+
def lifecycle_version = "1.1.1"
34+
35+
// ViewModel and LiveData
36+
implementation "android.arch.lifecycle:extensions:$lifecycle_version"
37+
// alternatively - just ViewModel
38+
implementation "android.arch.lifecycle:viewmodel:$lifecycle_version" // use -ktx for Kotlin
39+
// alternatively - just LiveData
40+
implementation "android.arch.lifecycle:livedata:$lifecycle_version"
41+
// alternatively - Lifecycles only (no ViewModel or LiveData).
42+
// Support library depends on this lightweight import
43+
implementation "android.arch.lifecycle:runtime:$lifecycle_version"
44+
45+
annotationProcessor "android.arch.lifecycle:compiler:$lifecycle_version"
46+
// alternately - if using Java8, use the following instead of compiler
47+
implementation "android.arch.lifecycle:common-java8:$lifecycle_version"
48+
49+
// optional - ReactiveStreams support for LiveData
50+
implementation "android.arch.lifecycle:reactivestreams:$lifecycle_version"
51+
52+
// optional - Test helpers for LiveData
53+
testImplementation "android.arch.core:core-testing:$lifecycle_version"
54+
}
55+
```
56+
57+
58+
`Room`依赖:
59+
---
60+
61+
`Room`的依赖包括`testing Room migrations``Room RxJava`
62+
63+
```
64+
dependencies {
65+
def room_version = "1.1.1"
66+
67+
implementation "android.arch.persistence.room:runtime:$room_version"
68+
annotationProcessor "android.arch.persistence.room:compiler:$room_version"
69+
70+
// optional - RxJava support for Room
71+
implementation "android.arch.persistence.room:rxjava2:$room_version"
72+
73+
// optional - Guava support for Room, including Optional and ListenableFuture
74+
implementation "android.arch.persistence.room:guava:$room_version"
75+
76+
// Test helpers
77+
testImplementation "android.arch.persistence.room:testing:$room_version"
78+
}
79+
80+
```
81+
82+
`Paging`依赖
83+
---
84+
85+
```
86+
dependencies {
87+
def paging_version = "1.0.0"
88+
89+
implementation "android.arch.paging:runtime:$paging_version"
90+
91+
// alternatively - without Android dependencies for testing
92+
testImplementation "android.arch.paging:common:$paging_version"
93+
94+
// optional - RxJava support, currently in release candidate
95+
implementation "android.arch.paging:rxjava2:1.0.0-rc1"
96+
}
97+
```
98+
99+
`Navigation`依赖
100+
---
101+
102+
> Navigation classes are already in the androidx.navigation package, but currently depend on Support Library 27.1.1, and associated Arch component versions. Version of Navigation with AndroidX dependencies will be released in the future.
103+
104+
```
105+
dependencies {
106+
def nav_version = "1.0.0-alpha02"
107+
108+
implementation "android.arch.navigation:navigation-fragment:$nav_version" // use -ktx for Kotlin
109+
implementation "android.arch.navigation:navigation-ui:$nav_version" // use -ktx for Kotlin
110+
111+
// optional - Test helpers
112+
androidTestImplementation "android.arch.navigation:navigation-testing:$nav_version" // use -ktx for Kotlin
113+
}
114+
```
115+
116+
117+
`Safe args`依赖
118+
---
119+
120+
想要使用`Safe args`,需要在`Project`顶层的`build.gradle`中配置以下路径:
121+
```
122+
buildscript {
123+
repositories {
124+
google()
125+
}
126+
dependencies {
127+
classpath "android.arch.navigation:navigation-safe-args-gradle-plugin:1.0.0-alpha02"
128+
}
129+
}
130+
```
131+
并且在`app``module``build.gradle`中:
132+
```
133+
apply plugin: "androidx.navigation.safeargs"
134+
```
135+
136+
`WorkManager`依赖
137+
---
138+
139+
> WorkManager classes are already in the androidx.work package, but currently depend on Support Library 27.1, and associated Arch component versions. Version of WorkManager with AndroidX dependencies will be released in the future.
140+
141+
142+
```
143+
dependencies {
144+
def work_version = "1.0.0-alpha03"
145+
146+
implementation "android.arch.work:work-runtime:$work_version" // use -ktx for Kotlin
147+
148+
// optional - Firebase JobDispatcher support
149+
implementation "android.arch.work:work-firebase:$work_version"
150+
151+
// optional - Test helpers
152+
androidTestImplementation "android.arch.work:work-testing:$work_version"
153+
}
154+
```
155+
156+
---
157+
158+
- 邮箱 :charon.chui@gmail.com
159+
- Good Luck! `

0 commit comments

Comments
 (0)