Fighting!

潜行者的沉默

Teach you to recognize MVC, MVP AND MVVM

I believe we are no stranger to MVC, MVP and MVVM, as the three most familiar Android framework. Their applications can be very extensive, but for some novice, it can be difficult to distinguish between them three.

Article focus:

  1. Learn and distinguish between MVC, MVP and MVVM.
  2. Know how these three models in the use of Android.
  3. Out of the DataBinding errors.
  4. Understand the development model of MVP data binding.

MVC

MVC means Model View Controller, is the most common framework in the software architecture, simply through the control of controller to operate the modle layer of data, and return to view layer display.

Alt text

Use the traditional MVC, which View, corresponding to a variety of layout files, but these layout files are not as powerful as the Web Side, can do very limited. Controller correspods to the Activity, but Activity has the function of operating UI. We in the actual project will hava a lot of UI operations, and also do a lot of View should be dong in the layer

MVC there is an important flaw, we look at the picture above, view layer and the model layer is mutual konw, which means that there is coupling between the two layers. The Coupling is very fatal for large program, beacuse it means that development, testing, maintenance need to spend a lot of energy.

MVP

MVP as MVC evolution, to solve a lot of MVC shortcommings. For Android, MVP model layer relative to the MVC is the same, but activity and fragment is no longer the controller layer, but the pure view layer.And all fordwarding of user events is handled by the presenter layer.
Alt text

It can be seen from the figure that the most obvious difference is that the view and model layer are no longer mutual konw and complete descoupling. Instead of the precenter layer acts as bridge, the events used to manipulate the view layer are passed to the presenter layer, the presenter layer to mainpulate the model layer, and the data is returned to the view layer. the view layer and the model layer are completely unconnected throughout the process.

MVVM

MVVM最早是由微软提出的
Alt text

From the figure to see that it is similiar to MVP, but the presenter layer
be replaced by ViewModel layer. And the view layer and the viewmodel are bound to each other, the means that when you update the data of the viewmodel layer, the view layer changes accordingly ui.

Last: MVP + Databinding

We use the data binding framework to save similar findViewById and data binding time, and the use of presenter to separate the business logic and view layer.

  1. 性能优化之布局
    重用
    减少视图层级
    需要时加载,懒加载布局
    使用工具:Hierarchy View
  2. Android 性能优化方法
    使用Dalvik提供的 dalvik.system.VMRuntime类来设置最小堆内存为例:
  3. bitmap 设置图片尺寸
    避免 内存溢出 OutOfMemoryError的优化方法
    options.inSampleSize = 2;//图片宽高都为原来的二分之一,即图片为原来的四分之一
  4. Android 还有一些性能优化的方法:
    首先内存方面,可以参考 Android堆内存也可自己定义大小 和 优化Dalvik虚拟机的堆内存分配
    基础类型上,因为Java没有实际的指针,在敏感运算方面还是要借助NDK来完成。这点比较有意思的是Google 推出NDK可能是帮助游戏开发人员,比如OpenGL ES的支持有明显的改观,本地代码操作图形界面是很必要的。
    图形对象优化,这里要说的是Android上的Bitmap对象销毁,可以借助recycle()方法显示让GC回收一个Bitmap对象,通常对一个不用的Bitmap可以使用下面的方式。
  5. 从代码角度进行优化
    静态变量引起内存泄露
    使用Application的Context
    及时关闭资源
    使用Bitmap及时调用recycle()
    对Adapter进行优化
    代码“微优化”
  6. 使用软引用和弱引用
  7. Android 中的Activity、Window、View之间的关系
    Activity在onCreate时调用attach方法,在attach方法中会创建window对象。window对象创建时并没有创建 DocerView 对象。用户在Activity中调用setContentView,然后调用window的setContentView,这时会检查DecorView是否存在,如果不存在则创建DecorView对象,然后把用户自己的 View 添加到 DecorView 中。
  8. Activity的几种LaunchMode及使用场景
    Android关于Task的一些实践
  9. Android 设计模式之MVC模式
    MVC模式下,系统框架的类库被划分为3种:模型(Model)、视图(View)、控制器(Controller)。模型对象负责建立数据结构和相应的行为操作处理。视图对象负责在屏幕上渲染出相应的图形信息展示给用户看。控制器对象负责截获用户的按键和屏幕触摸等事件,协调Model对象和View对象。
      用户与视图交互,视图接收并反馈用户的动作;视图把用户的请求传给相应的控制器,由控制器决定调用哪个模型,然后由模型调用相应的业务逻辑对用户请求进行加工处理,如果需要返回数据,模型会把相应的数据返回给控制器,由控制器调用相应的视图,最终由视图格式化和渲染返回的数据,对于返回的数据完全可以增加用户体验效果展现给用户。
  10. 教你认清MVC,MVP和MVVM
    如何设计MVP中的Presentation层
    google 官方mvp实例的实践之mvp-databinding-Rxjava(一)
  11. Netty 4.0在Android 上的使用,长连接断线自动重连

出发点

  由于在学习Android的时候并没有很系统地进行学习,知识点比较零碎,所以需要将自己的知识点进行系统的整理,那么首要的我需要将android的系统架构搞清楚,这样才能分清楚我所了解的知识点附属于哪个层面,是内核还是应用层,可以进行怎样的扩展,在哪些场景去运用。

Android架构解析

Google工程师多图详解Android系统架构
Android基础之Android系统架构
Android维基百科
Android对Linux内核的增强
Android系统架构详解(2)–Android Runtime

以上是我在这个课题下的一些参考博客或者网页链接。里面有对于android架构的一些较好的分析理解,接下来是阅读后自己的一些整理。

Android采用层次化系统架构,官方公布的标准架构如下图所示。

Alt text

Android由底层往上分为4个主要功能层,分别是Linux内核层(Linux Kernel),系统运行时库层(Libraries和Android Runtime),应用程序架构层(Application Framework)和应用程序层(Applications)。

接下来对这几个层面进行逐个分析:

Linux内核层

  Android以Linux操作系统内核为基础,借助Linux内核服务实现硬件设备驱动,进程和内存管理,网络协议栈,电源管理,无线通信等核心功能。Android4.0版本之前基于Linux2.6系列内核,4.0及之后的版本使用更新的Linux3.X内核,并且两个开源项目开始有了互通。Linux3.3内核中正式包括一些Android代码,可以直接引导进入Android。Linux3.4增添了电源管理等更多功能,以增加与Android的硬件兼容性,使Android在更多设备上得到支持。直到现在最新的android6.0仍然继续延用着linux3.4.0,而linux最新的版本已经到了4.3系列,那么为什么android没有继续去更新Linuxkernel的版本也是一个值得探讨的课题。

  Android内核 对Linux内核进行了增强,增加了一些面向移动计算的特有功能。例如,低内存管理器LMK(Low Memory Keller),匿名共享内存(Ashmem),以及轻量级的进程间通信Binder机制等。这些内核的增强使Android在继承Linux内核安全机制的同时,进一步提升了内存管理,进程间通信等方面的安全性。

硬件抽象层

  内核驱动和用户软件之间还存在所谓的硬件抽象层(Hardware Abstract Layer,HAL),它是对硬件设备的具体实现加以抽象。HAL没有在Android官方系统架构图中标明,下图标出了硬件抽象层在android系统中的位置:

Alt text

  鉴于许多硬件设备厂商不希望公开其设备驱动的源代码,如果能将android的应用框架层与linux系统内核的设备驱动隔离,使应用程序框架的开发尽量独立于具体的驱动程序,则android将减少对Linux内核的依赖。HAL由此而生,它是对Linux内核驱动程序进行的封装,将硬件抽象化,屏蔽掉了底层的实现细节。HAL规定了一套应用层对硬件层读写和配置的统一接口,本质上就是将硬件的驱动分为用户空间和内核空间两个层面;Linux内核驱动程序运行于内核空间,硬件抽象层运行于用户空间。

系统运行库层

  官方的系统架构图中,位于Linux内核层之上的系统运行库层是应用程序框架的支撑,为Android系统中的各个组件提供服务。系统运行库层由系统类库和Android运行时构成。

  • 系统类库
    系统类库大部分由C/C++编写,所提供的功能通过Android应用程序框架为开发者所使用。例如SQlite,WebKit,SSL都在会在日常开发中有用到

Alt text

  • 运行时
    Android运行时包含核心库和Dalvik虚拟机两部分。
    • 核心库:核心库提供了Java5 se API的多数功能,并提供Android的核心API,如android.os,android.net,android.media等。
    • Dalvik虚拟机:Dalvik虚拟机是基于apache的java虚拟机,并被改进以适应低内存,低处理器速度的移动设备环境。Dalvik虚拟机依赖于Linux内核,实现进程隔离与线程调试管理,安全和异常管理,垃圾回收等重要功能。

Dalvik和标准Java虚拟机有以下主要区别:

  • Dalvik基于寄存器,而JVM基于栈。一般认为,基于寄存器的实现虽然更多依赖于具体的CPU结构,硬件通用性稍差,但其使用等长指令,在效率速度上较传统JVM更有优势。
  • Dalvik经过优化,允许在有限的内存中同时高效地运行多个虚拟机的实例,并且每一个Dalvik应用作为一个独立的Linux进程执行,都拥有一个独立的Dalvik虚拟机实例。Android这种基于Linux的进程“沙箱”机制,是整个安全设计的基础之一。
  • Dalvik虚拟机从DEX(Dalvik Executable)格式的文件中读取指令与数据,进行解释运行。DEX文件由传统的,编译产生的CLASS文件,经dx工具软件处理后生成。
  • Dalvik的DEX文件还可以进一步优化,提高运行性能。通常,OEM的应用程序可以在系统编译后,直接生成优化文件(.ODEX); 第三方的应用程序则可在运行时在缓存中优化与保存,优化后的格式为DEY(.dey文件)。

  这部分内容,即从android4.4开始就出现了ART(android runtime),但是这个ART并不是指这一节的主题,而是一种用来代替Dalvik的新型运行环境。当然在4.4的正式环境中用的还是Dalvik,真正开始用ART取代Dalvik是从android5.0开始的。(todo:针对这个改动,楼主会专门另开一个篇幅的文章去探究ART和Dalvik之间的区别)

另外这一节中有提到NDK,相信对于开发者而言SDK和NDK都是必要要接触和了解的东西,那么先从下图来看看sdk和ndk的关系。

Alt text

  很显然地,ndk可以通过native code跨过使用dalvik runtime,直接调用到android内核资源,而sdk则需要在dalvik runtime环境下才能调用到内核资源。然而两者并不是各司其职,各不相关。android提供了JNI(Java native interface)使两者可以进行相互调用和通信。

应用程序框架层

  应用程序框架层提供开发Android应用程序所需的一系列类库,使开发人员可以进行快速的应用程序开发,方便重用组件,也可以通过继承实现个性化的扩展。

Alt text

应用层

  Android平台的应用层上包括各类与用户直接交互的应用程序,或由java语言编写的运行于后台的服务程序。例如,智能手机上实现的常见基本功能 程序,诸如SMS短信,电话拨号,图片浏览器,日历,游戏,地图,web浏览器等程序,以及开发人员开发的其他应用程序。

  将android的基本架构进行了一个总体的分析和罗列,我们可以发现,平时开发中最常接触和用到的一定是application层,但是我们也不难发现,一些application层应用到的东西都能在系统层找到对应的踪迹,例如sqlite,webkit,甚至alarm。他们是怎么从底层到达application层供我们日常开发所用,这个也是需要去了解和研究的。本篇文章的目的在开篇已经阐述过,是为了能更好地将自己的知识对号入座,并且去补充一些自己在某些层面上缺乏的知识,最终可以将自己的知识形成一个整体的体系结构。

MarkdownEditing

MarkdownEditing是Markdown写作者必备的插件,它可以不仅可以高亮显示Markdown语法还支持很多编程语言的语法高亮显示。

  1. 安装插件
    安装插件之前,我们需要首先安装一个Sublime 中最不可缺少的插件 Package Control, 以后我们安装和管理插件都需要这个插件的帮助。
  2. 安装”Package Control”
    使用快捷键 “ ctrl + `” 打开Sublime的控制台 ,或者选择 View > Show Console
    在控制台的命令行输入框,把下面一段代码粘贴进去,回车 就可以完成Pacakge Control 的安装了。
    1
    import urllib.request,os,hashlib; h = 'eb2297e1a458f27d836c04bb0cbaf282' + 'd0e7a3098092775ccb37ca9d6b2e4b7d'; pf = 'Package Control.sublime-package'; ipp = sublime.installed_packages_path(); urllib.request.install_opener( urllib.request.build_opener( urllib.request.ProxyHandler()) ); by = urllib.request.urlopen( 'http://packagecontrol.io/' + pf.replace(' ', '%20')).read(); dh = hashlib.sha256(by).hexdigest(); print('Error validating download (got %s instead of %s), please try manual install' % (dh, h)) if dh != h else open(os.path.join( ipp, pf), 'wb' ).write(by)
  3. 安装MarkdownEditing
    Package Control 安装成功后我们就可以使用它方便的管理插件了,首先使用快捷键 ‘command + shift + p ‘ 进入到Sublime 命令面板,输入 “package install” 从列表中选择 “install Package” 然后回车。这时候Sublime开始请求远程插件仓库的索引,所以第一次使用可能会有一些小的延时。
    Alt text
    看到列表的更新之后输入 “markdown ed” 关键字,选择“MarkdownEditing” 回车。 插件安装完毕后需要重新启动Sublime插件才能生效。下面是我使用sublime编辑代码片断的显示效
    Alt text

输入 “mdi + tab” 会自动插入下面的图片标记

1
![Alt text](/path/to/img.jpg "Optional title")

输入 “mdl + tab” 会自动生成下面的链接标记

1
[](link)

Markdown Preview 插件

Mardown Preview不仅支持在浏览器中预览markdown文件,还可以导出html代码。

  1. 安装
    通过按组合键Ctrl+Shift+P或是点击Preference->Package Control调出命令面板,然后再输入 install,选择 Package Control: install package。
    Alt text
    在插件安装面板输入markdown找到Markdown Preview并点击安装即可。
    Alt text
  2. 使用
    通过按组合键Ctrl+Shift+P或是点击Preference->Package Control调出命令面板,输入mdp,下图中红框圈出的就是在浏览器中预览markdown文件。
    Alt text
    选中后,你将见到两个选项:GitHub和Mardown。GitHub选项意味着使用GitHub的在线API来解析.md文件。它的解析速度取决于你的联网速度。据称有每天60次访问的限制。[2]但能免费获得GFM格式的语法支持和EMOJI表情的支持。
    另外一个常用功能是图中第五个,Export HTML in Sublime Text,即导出html文件到sublime text。
  3. 快捷键设置
    Sublime Text支持自定义快捷键,markdown preview默认没有快捷键,我们可以自己为preview in browser设置快捷键。方法是在Preferences -> Key Bindings User打开的文件的中括号中添加以下代码(可在Key Bindings Default找到格式):
1
{ "keys": ["alt+m"], "command": "markdown_preview", "args": {"target": "browser", "parser":"markdown"}  }
这里:

“alt+m”可设置为自己喜欢的按键。
“parser”:”markdown”也可设置为”parser”:”github”,改为使用Github在线API解析markdown。

阿里云Centos7 搭建Git服务器仓库,记录过程

1.首先需要安装Git,可以使用yum源在线安装:

1
[root@localhost Desktop]# yum install -y git

这里写图片描述

2.创建一个git用户,用来运行git服务

1
# adduser git  

这里写图片描述

3.初始化git仓库:这里我们选择/usr/local/tomcat7/webapps/baby_android/来作为我们的git仓库

1
# git init

仓库路径 /usr/local/tomcat7/webapps/baby_android/

这里写图片描述
执行以上命令,会创建一个裸仓库,裸仓库没有工作区,因为服务器上的Git仓库纯粹是为了共享,所以不让用户直接登录到服务器上去改工作区,并且服务器上的Git仓库通常都以.git结尾。然后,设置权限:

1
[root@localhost webapps]# chown - Rh git:users baby 

5.创建SSH Key

首先在用户主目录下,看看有没有.ssh目录,如果有,再看看这个目录下有没有id_rsa和id_rsa.pub这两个文件,如果已经有了,可直接跳到下一步。如果没有,打开Shell(Windows下打开Git Bash),创建SSH Key:

1
$ ssh-keygen -t rsa -C "youremail@example.com"

你需要把邮件地址换成你自己的邮件地址,然后一路回车,使用默认值即可,由于这个Key也不是用于军事目的,所以也无需设置密码。
如果一切顺利的话,可以在用户主目录里找到.ssh目录,里面有id_rsa和id_rsa.pub两个文件,这两个就是SSH Key的秘钥对,id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心地告诉任何人。

6.Git服务器打开RSA认证

然后就可以去Git服务器上添加你的公钥用来验证你的信息了。在Git服务器上首先需要将/etc/ssh/sshd_config中将RSA认证打开,即:

1
2
3
1.RSAAuthentication yes    
2.PubkeyAuthentication yes
3.AuthorizedKeysFile .ssh/authorized_keys

这里我们可以看到公钥存放在.ssh/authorized_keys文件中。所以我们在/home/git下创建.ssh目录,然后创建authorized_keys文件,并将刚生成的公钥导入进去。
创建文件夹 mkdir 路径/文件夹名
创建文件 vi 路径/文件名
然后再次clone的时候,或者是之后push的时候,就不需要再输入密码了:

7.禁用git用户的shell登陆

出于安全考虑,第二步创建的git用户不允许登录shell,这可以通过编辑/etc/passwd文件完成。找到类似下面的一行:

1
git:x:1001:1001:,,,:/home/git:/bin/bash 

最后一个冒号后改为:
这里写图片描述

1
git:x:1001:1001:,,,:/home/git:/usr/bin/git-shell  

git clone git@42.96.150.57: /usr/local/tomcat7/webapps/baby/

8. 客户端基本操作

git add .
git commit
git push

9.服务器自动更新部署

  1. 进入到 /usr/local/tomcat7/webapps/baby/.git 文件夹中,会发现 .git/hook 文件夹在里面,进入到 hook 中,里面有很多的 sample 脚本,这里我们只需要用到 post-update。
    post-update脚本
  2. 设置文件权限
    1
    chown -Rh git:users baby

10.创建git服务器远程仓库

1
2
$ mv post-update.sample post-update
$ vim post-update

注意:

  1. Git: push 出错的解决 master -> master (branch is currently checked out)
    这是由于git默认拒绝了push操作,需要进行设置,修改.git/config添加如下代码:
    1
    2
    [receive]
    denyCurrentBranch = ignore
    线上添加文件设置权限
    1
    chown -Rh git:users baby
0%