Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
ShiHaoyang committed Aug 26, 2016
0 parents commit 09b0527
Show file tree
Hide file tree
Showing 134 changed files with 4,336 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
_book
*.pdf
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Introduction

本文档使用 Gitbook 制作,[Github](https://github.com/AstaYang/interview.git) 仓库地址。

所有引用内容版权归原作者所有。
67 changes: 67 additions & 0 deletions SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Summary

* [Introduction](README.md)
* [计算机基础](basic/README.md)
* [计算机网络](basic/net/README.md)
* [网络分层](basic/net/osi.md)
* [底层网络协议](basic/net/base_protocol.md)
* [TCP](basic/net/tcp.md)
* [IP](basic/net/ip.md)
* [HTTP](basic/net/http.md)
* [面试题](basic/net/questions.md)
* [数据结构与算法](basic/algo/README.md)
* [](basic/algo/tree.md)
* [Hash](basic/algo/hash.md)
* [最小生成树算法](basic/algo/mst.md)
* [最短路径算法](basic/algo/path.md)
* [KMP算法](basic/algo/kmp.md)
* [查找算法](basic/algo/search.md)
* [排序算法](basic/algo/sort.md)
* [常用算法](basic/algo/algo.md)
* [面试题](basic/algo/questions.md)
* [操作系统](basic/op/README.md)
* [计算机体系结构](basic/op/arch.md)
* [操作系统基础](basic/op/os.md)
* [并发](basic/op/concurrency.md)
* [内存管理](basic/op/memory.md)
* [磁盘与文件](basic/op/disk.md)
* [Linux系统](basic/op/linux.md)
* [面试题](basic/op/questions.md)
* [数据库系统](basic/database/README.md)
* [事务](basic/database/transaction.md)
* [索引](basic/database/index.md)
* [SQL语句](basic/database/sql.md)
* [连接](basic/database/join.md)
* [面试题](basic/database/questions.md)
* [Java基础](java/README.md)
* [面向对象基础](java/oop.md)
* [集合框架](java/collection.md)
* [Java分派机制](java/dispatcher.md)
* [Java异常](java/exception.md)
* [Java泛型](java/generics.md)
* [Java线程](java/thread.md)
* [JVM架构](java/jvm-architecture.md)
* [类加载器](java/jvm-class-loader.md)
* [JVM类加载三步走](java/jvm-class-load-init.md)
* [JVM垃圾回收](java/jvm-gc.md)
* [Java对象生命周期](java/jvm-object-life-cycle.md)
* [Volatile原理](java/volatile.md)
* [Synchronized原理](java/synchronized.md)
* [面试题](java/questions.md)
* [Android开发](android/README.md)
* [Android系统架构](android/arch.md)
* [Activity && Service生命周期](android/lifecicle.md)
* [Activity四种启动模式](android/launchmod.md)
* [ListView原理及优化](android/listview.md)
* [Android中Handler机制](android/handler.md)
* [Android广播机制](android/broadcast.md)
* [View绘制过程](android/draw.md)
* [事件分发机制](android/event.md)
* [Binder](android/binder.md)
* [OOM && ANR 优化](android/optimize.md)
* [推送机制](android/push.md)
* [进程保活](android/keep-live.md)
* [Activity、View及Window之间关系](android/activity-view-window.md)
* [EventBus](android/eventbus.md)
* [面试题](android/questions.md)

Binary file added android/EventBus.Post.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added android/EventBus.register.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions android/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Introduction

4 changes: 4 additions & 0 deletions android/SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Summary

* [Introduction](README.md)

47 changes: 47 additions & 0 deletions android/activity-view-window.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Activity、View及Window之间关系

## View

View(包括ViewGroup)使用的是组合模式,将View组成成树形结构,以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。View主要是用于绘制我们想要的结果,是一个最基本的UI组件。

## Window

简单地说,`Window`表示一个窗口,一般来说,`Window`大小取值为屏幕大小。但是这不是绝对的,如对话框、Toast等就不是整个屏幕大小。你可以指定`Window`的大小。`Window`包含一个`View tree`和窗口的`layout`参数。

感觉Window的理解比较抽象,Window相当于一个容器,里面“盛放”着很多View,这些View是以树状结构组织起来的。

> 如果还是无法理解的话,就把Window当成是显示器,显示器有大有小(对应Window有大有小),View是显示器里面具体显示的内容。
### Window对象存在的必要性

`Window`能做的事情,`View`对象基本都能做:像什么触摸事件啊、显示的坐标及大小啊、管理各个子View啊等等。View已经这么强大了,为什么还多此一举,加个`Window`对象。可能有人会说因为`WindowManager`管理的就是`Window`对象呀,那我想问,既然这样,Android系统直接让`WindowManager`去管理`View`不就好了?让View接替`Window`的工作,把`Window`所做的事情都封装到`View`里面不好嘛?。或许又有人说,`View`负责绘制显示内容,`Window`负责管理`View`,各自的工作职责不同。可是我想说,`Window`所做的大部分工作,`View`里面都有同样(或类似)的处理。

关于`Window`存在的必要,我查了国内外各种资料,最后有了我个人的理解。在后面小节里面,我会结合我个人的理解来解释。在解释之前,我们需要了解Window绘制过程。

### Window绘制过程

在理解`Window`绘制过程之前,首先,我们需要知道`Surface`,在`Window`中持有一个`Surface`,那么什么是`Surface`呢?

`Surface`其实就是一个持有像素点矩阵的对象,这个像素点矩阵是组成显示在屏幕的图像的一部分。**我们看到显示的每个Window(包括对话框、全屏的Activity、状态栏等)都有他自己绘制的`Surface`**。而最终的显示可能存在`Window`之间遮挡的问题,此时就是通过`Surface Flinger对`象渲染最终的显示,使他们以正确的`Z-order`显示出来。一般`Surface`拥有一个或多个缓存(一般2个),通过双缓存来刷新,这样就可以一边绘制一边加新缓存。

`WindowManager`为每个`Window`创建`Surface`对象,然后应用就可以通过这个`Surface`来绘制任何它想要绘制的东西。而对于`WindowManager`来说,这只不过是一块矩形区域而已。

前面我们说过,`View``Window`里面用于交互的UI元素。`Window`只attach一个`View Tree`,当`Window`需要重绘(如,当View调用`invalidate`)时,最终转为`Window``Surface``Surface`被锁住(locked)并返回Canvas对象,此时View拿到Canvas对象来绘制自己。当所有View绘制完成后,`Surface`解锁(unlock),并且post到绘制缓存用于绘制,通过`Surface Flinger`来组织各个Window,显示最终的整个屏幕。

### 总结

现在我们知道了`Window`绘制过程,其实,站在系统的角度来考虑,一个Window对象代表一块显示区域,系统不关心Window里面具体的绘制内容,也不管你`Window`怎么去绘制,反正只给你提供可以在这块区域上绘制图形的`Surface`对象,你`Window`对象怎么画是你的事情!

换句话说,站在系统的角度上看,系统是“不知道”有View对象这个说法的!作为系统,我有自己的骄傲,不去管你Window如何搬砖、如何砌墙,只给你地皮。而这时,Window为了绘制出用户想要的组件(按钮、文字、输入框等等),系统又不给我!没事,那我自己定义,于是就定义了View机制,给每个View提供Canvas,让不同的View自己绘制具有自己特色的组件。同时,为了更好的管理View,通过定义ViewGroup,等等。

## Activity

对于开发人员来说,一个`Activity`就“相当于”一个界面(通过`setContentView`指定具体的View)。我们可以直接在Activity里处理事件,如`onKeyEvent`,`onTouchEvent`等。 并可以通过Activity维护应用程序的生命周期。

### Activity和Window

前面我们知道,`Window`已经是系统管理的窗口界面。那么为什么还需要`Activity`呢?我们把`Activity`所做的事情,全部封装到`Window`不就好了?

其实,本质上讲,我们要显示一个窗口出来,的确可以不需要Activity。悬浮窗口中不就是没有使用Activity来显示一个悬浮窗吗?既然如此,Window(以及View)能处理点击事件以及封装各种逻辑,那为啥还需要Activity呢?

`Android`中的应用中,里面对各个窗口的管理相当复杂(任务栈、状态等等),Android系统当然可以不用Activity,让用户自己直接操作Window来开发自己的应用。但是如果让用户自己去管理这些Window,先不说工作量,光让用户自己去实现任务栈这点,有几个人能写的出来。**为了让大家能简单、快速的开发应用,Android通过定义Activity,让Activity帮我们管理好,我们只需简单的去重写几个回调函数,无需直接与Window对象接触**。各种事件也只需重写Activity里面的回调即可。无需关注其他细节,默认都帮我们写好了,针对需要定制的部分我们重写(设计模式为:模板方法模式)。
Binary file added android/activity_life.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added android/android-lanchmode-singleinstance.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added android/android-lanchmode-singletask.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added android/android-lanchmode-singletop.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added android/android-lanchmode-standard.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added android/android-listview.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added android/android-radio-state.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
46 changes: 46 additions & 0 deletions android/arch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Android系统架构

![](arch.png)

## 应用程序(Applications)

Android会同一系列核心应用程序包一起发布,该应用程序包包括email客户端,SMS短消息程序,日历,地图,浏览器,联系人管理程序等。所有的应用程序都是使用JAVA语言编写的。通常开发人员就处在这一层。

## 应用程序框架(Application Frameworks)

提供应用程序开发的各种API进行快速开发,也即隐藏在每个应用后面的是一系列的服务和系统,大部分使用Java编写,所谓官方源码很多也就是看这里,其中包括:

- **丰富而又可扩展的视图(Views)**:可以用来构建应用程序, 它包括列表(lists),网格(grids),文本框(text boxes),按钮(buttons), 甚至可嵌入的web浏览器。
- **内容提供器(Content Providers)**:使得应用程序可以访问另一个应用程序的数据(如联系人数据库), 或者共享它们自己的数据
- **资源管理器(Resource Manager)**:提供 非代码资源的访问,如本地字符串,图形,和布局文件( layout files )。
- **通知管理器 (Notification Manager)**:使得应用程序可以在状态栏中显示自定义的提示信息。
- **活动管理器( Activity Manager)**:用来管理应用程序生命周期并提供常用的导航回退功能。

## 系统运行库与Android运行环境(Libraris & Android Runtime)

### 系统运行库

Android 包含一些C/C++库,这些库能被Android系统中不同的组件使用。它们通过 Android 应用程序框架为开发者提供服务。以下是一些核心库:
- **Bionic系统 C 库** - 一个从 BSD 继承来的标准 C 系统函数库( libc ), 它是专门为基于 embedded linux 的设备定制的。
- **媒体库** - 基于 PacketVideo OpenCORE;该库支持多种常用的音频、视频格式回放和录制,同时支持静态图像文件。编码格式包括MPEG4, H.264, MP3, AAC, AMR, JPG, PNG 。
- **Surface Manager** - 对显示子系统的管理,并且为多个应用程序提 供了2D和3D图层的无缝融合。这部分代码
- **Webkit,LibWebCore** - 一个最新的web浏览器引擎用,支持Android浏览器和一个可嵌入的web视图。鼎鼎大名的 Apple Safari背后的引擎就是Webkit
- **SGL** - 底层的2D图形引擎
- **3D libraries** - 基于OpenGL ES 1.0 APIs实现;该库可以使用硬件 3D加速(如果可用)或者使用高度优化的3D软加速。
- **FreeType** -位图(bitmap)和矢量(vector)字体显示。
- **SQLite** - 一个对于所有应用程序可用,功能强劲的轻型关系型数据库引擎。

### Android运行环境

该核心库提供了JAVA编程语言核心库的大多数功能。<br />每一个Android应用程序都在它自己的进程中运 行,都拥有一个独立的Dalvik虚拟 机实例。Dalvik被设计成一个设备可以同时高效地运行多个虚拟系统。 Dalvik虚拟机执行(.dex)的Dalvik可执行文件,该格式文件针对小内存使用做了 优化。同时虚拟机是基于寄存器的,所有的类都经由JAVA编译器编译,然后通过SDK中 的 "dx" 工具转化成.dex格式由虚拟机执行。

## HAL--硬件抽象层

其实Android并非讲所有的设备驱动都放在linux内核里面,而是实现在userspace空间,这么做的主要原因是GPL协议,Linux是遵循该协议来发布的,也就意味着对linux内核的任何修改,都必须发布其源代码。而现在这么做就可以避开而无需发布其源代码,毕竟它是用来赚钱的。而在linux内核中为这些userspace驱动代码开一个后门,就可以让本来userspace驱动不可以直接控制的硬件可以被访问。而只需要公布这个后门代码即可。一般情况下如果要将Android移植到其他硬件去运行,只需要实现这部分代码即可。包括:显示器驱动,声音,相机,GPS,GSM等等

## Linux内核(Linux Kernel)

Android的核心系统服务依赖于Linux 2.6 内核,如安全性,内存管理,进程管理, 网络协议栈和驱动模型。 Linux 内核也同时作为硬件和软件栈之间的抽象层。其外还对其做了部分修改,主要涉及两部分修改:

1. Binder (IPC):提供有效的进程间通信,虽然linux内核本身已经提供了这些功能,但Android系统很多服务都需要用到该功能,为了某种原因其实现了自己的一套。
2. 电源管理:主要是为了省电,毕竟是手持设备嘛,低耗电才是我们的追求。
Binary file added android/arch.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added android/binder.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 26 additions & 0 deletions android/binder.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Binder

## 简介

Binder使用`Client-Server`通信方式。Binder框架定义了四个角色:`Server`,`Client`,`ServiceManager`以及`Binder驱动`。其中`Server`,`Client`,`ServiceManager`运行于用户空间,驱动运行于内核空间。Binder驱动程序提供设备文件`/dev/binder`与用户空间交互,`Client``Server``Service Manager`通过`open``ioctl`文件操作函数与Binder驱动程序进行通信。

![](binder.gif)

## Binder原理简述

1. Server创建了Binder实体,为其取一个字符形式,可读易记的名字。
2. 将这个Binder连同名字以数据包的形式通过Binder驱动发送给`ServiceManager`,通知`ServiceManager`注册一个名字为XX的Binder,它位于Server中。
3. 驱动为这个穿过进程边界的Binder创建位于内核中的实体结点以及ServiceManager对实体的引用,将名字以及新建的引用打包给ServiceManager。
4. `ServiceManager`收数据包后,从中取出名字和引用填入一张查找表中。但是一个Server若向ServiceManager注册自己Binder就必须通过这个引用和`ServiceManager`的Binder通信。
5. Server向`ServiceManager`注册了Binder实体及其名字后,Client就可以通过名字获得该Binder的引用了。Clent也利用保留的引用向`ServiceManager`请求访问某个Binder:我申请名字叫XX的Binder的引用。
6. `ServiceManager`收到这个连接请求,从请求数据包里获得Binder的名字,在查找表里找到该名字对应的条目,从条目中取出Binder引用,将该引用作为回复发送给发起请求的Client。

当然,不是所有的Binder都需要注册给`ServiceManager`广而告之的。Server端可以通过已经建立的Binder连接将创建的Binder实体传给Client,当然这条已经建立的Binder连接必须是通过实名Binder实现。由于这个Binder没有向ServiceManager注册名字,所以是 **匿名Binder**。Client将会收到这个匿名Binder的引用,通过这个引用向位于Server中的实体发送请求。匿名Binder为通信双方建立一条私密通道,只要Server没有把匿名Binder发给别的进程,别的进程就无法通过穷举或猜测等任何方式获得该Binder的引用,向该Binder发送请求。

## Binder的数据拷贝

Linux内核实际上没有从一个用户空间到另一个用户空间直接拷贝的函数,需要先用`copy_from_user()`拷贝到内核空间,再用`copy_to_user()`拷贝到另一个用户空间。**为了实现用户空间到用户空间的拷贝,`mmap()`分配的内存除了映射进了接收方进程里,还映射进了内核空间**。所以调用`copy_from_user()`将数据拷贝进内核空间也相当于拷贝进了接收方的用户空间,这就是Binder只需一次拷贝的"秘密"。

最底层的是Android的`ashmen(Anonymous shared memory)`机制,它负责辅助实现内存的分配,以及跨进程所需要的内存共享。AIDL(android interface definition language)对Binder的使用进行了封装,可以让开发者方便的进行方法的远程调用,后面会详细介绍。Intent是最高一层的抽象,方便开发者进行常用的跨进程调用。

使用共享内存通信的一个显而易见的好处是效率高,因为 **进程可以直接读写内存,而不需要任何数据的拷贝**。对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而共享内存则只拷贝两次内存数据:一次从输入文件到共享内存区,另一次从共享内存到输出文件。实际上,进程之间在共享内存时,并不总是读写少量数据后就解除映射,有新的通信时,再重新建立共享内存区域,而是保持共享区域,直到通信完成为止,这样,数据内容一直保存在共享内存中,并没有写回文件。共享内存中的内容往往是在解除内存映射时才写回文件的。因此,采用共享内存的通信方式效率是非常高的。
16 changes: 16 additions & 0 deletions android/broadcast.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Android广播机制

广播(Broadcast)机制用于进程/线程间通信,广播分为广播发送和广播接收两个过程,其中广播接收者BroadcastReceiver便是Android四大组件之一。

BroadcastReceiver分为两类:

- `静态广播接收者`:通过`AndroidManifest.xml`的标签来申明的BroadcastReceiver。
- `动态广播接收者`:通过`AMS.registerReceiver()`方式注册的BroadcastReceiver,动态注册更为灵活,可在不需要时通过`unregisterReceiver()`取消注册。

从广播发送方式可分为三类:

- `普通广播`:通过Context.sendBroadcast()发送,可并行处理
- `有序广播`:通过Context.sendOrderedBroadcast()发送,串行处理
- `Sticky广播`:通过Context.sendStickyBroadcast()发送,发出的广播会一直滞留(等待),以便有人注册这则广播消息后能尽快的收到这条广播。

Android 中的 Broadcast 实际底层使用Binder机制。
Loading

0 comments on commit 09b0527

Please sign in to comment.