<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
	<title>Votbar</title>
	<link href="http://supern.github.com/atom.xml" rel="self" />
	<link href="http://supern.github.com/" />
	<updated>2026-10-16T12:53:24+00:00</updated>
	<id>http://supern.github.com/</id>
	<author>
		<name>supern</name>
		<email>supern.lee@gmail.com</email>
	</author>
	
	<entry>
		<title>android中的数据管理</title>
		<link href="http://mytharcher.github.com/posts/android-data-mgr.html" />
		<updated>2012-07-18T00:00:00+00:00</updated>
		<id>http://supern.github.com/posts/android-data-mgr.html</id>
		<content type="html"><![CDATA[<h2 id="概述">概述</h2>

<p>我们知道，一个应用无非是由UI、逻辑、数据所构成，数据在应用中的地位举足重轻。我们讨论数据需要讨论数据的来源，数据保持（存储），数据的销毁等生命周期的管理。数据是有时效性的，也就是说，数据存在的时间是不同的，有的可以持久保存，比如说历史登录账户，有的是跟应用周期等同，比如应用的配置数据，有的只在应用的部分时期内，比如用户登录后的sessionId等。</p>

<p>本文将介绍数据的存储管理，根据数据存储的介质，可以分为ram cache（内存缓存），以及persistence store（持久化存储），我们主要讨论下数据在内存中的缓存。</p>

<p>在android中，我们根据平台的特性以及数据的生命周期，一般划分局部数据和全局数据。</p>

<h2 id="局部数据">局部数据</h2>

<p>一般跟android的组件生命周期等同的数据，我们把它归属为局部数据。比如activity中的数据，service中的数据等。局部数据伴随着组件的消亡而消亡。</p>

<h2 id="全局数据">全局数据</h2>

<p>全局数据是application生命周期的数据，它一般是跨几个组件的数据，比如说是多个activity共享的数据。比如说用户的sessionId，其中一个组件改变了数据，其他组件应当立马得到新的数据，这就需要保证全局数据只应该有一份拷贝。</p>

<p>一般的，我们可以使用单例，或者直接在Application中持有全局数据。但实际上，全局数据也不完全是整个应用生命周期都需要存在的数据，比如很多用户的数据是需要用户登录后才需要存在的，这样的数据使用单例就不是特别的好了（因为单例的生命周期是跟类加载器一致的，也就是说和dalvik实例一致，当然如果显式的去管理生命周期也没什么问题），所以，我们一般会通过application来引用全局数据。</p>

<h2 id="当进程被重启的时候">当进程被重启的时候</h2>

<p>在android环境中，我们知道有许多第三方的应用（比如进程查杀器，360安全卫士等）可以直接kill进程，特别的，在4.0的系统里，更是在开发人员设置里增加了一些设置（比如不保存当前活动），这样数据的生命周期管理更增加了许多的复杂度。</p>

<p>在android中，一个进程被重启后，它的数据将会被重新的初始化。但对于activity以及一些View，android提供了onSaveInstanceState，onRestoreInstanceState等回调方法来处理数据的连贯性，因为对于android来说，进程被kill了，但activity records会被保存，也就是说应用重启后还可以回到最后停留的activity，保持用户体验的连贯性。这些机制，类似于wp7的墓碑化。</p>

<p>下面分别来讨论下局部数据和全局数据的保存和恢复。</p>

<h3 id="局部数据的保存和恢复">局部数据的保存和恢复</h3>

<p>如果是activity组件中的局部数据，我们完全可以遵循android的机制，也就是在onSaveInstanceState中保存数据，在onRestoreInstanceState恢复数据。如果是service的局部数据，就不需要保存了吧，直接全部重新初始化。</p>

<h3 id="全局数据的保存和恢复">全局数据的保存和恢复</h3>

<p>全局数据的保存和恢复比较棘手。因为目前我们没法感知application的墓碑化，也就是说android没有提供相应的回调方法。有以下思考：</p>

<ul>
  <li>持久化全局数据，每次写（set）数据的时候，都及时同步到persistence store，每次读（get）数据的时候都需要保证数据不是脏数据，必须是最新的数据</li>
  <li>对应用需要有显式的退出，在退出的时候清除相应的全局数据</li>
  <li>数据的安全？比如说sessionId是否可以持久化存储</li>
</ul>

<h2 id="缓存">缓存</h2>

<p>此处说的缓存是只内存的缓存。</p>

<p>对于android的数据缓存，我们需要对数据类型做不同的区分对待。比如说文本，多媒体（图片对android来说有独立的存储空间，而且非常容易造成OOM），可以分别对他们做个缓存池（LRU），当内存不足的时候可以把使用的少的一些数据持久化。缓存应该对使用者透明。</p>

<h2 id="持久化">持久化</h2>

<p>android支持的持久化方式有sqlite,shareprefrence,file。对于k-v的，而且数据量不大的尽量考虑shareprefrence。</p>

<h2 id="content-provider">content provider</h2>

<p>可以考虑用content provider来做数据提供者，把网络请求什么的都封装起来。</p>

<p>-EOF-</p>
]]></content>
	</entry>
	
	<entry>
		<title>android编码规范</title>
		<link href="http://mytharcher.github.com/posts/code_standards.html" />
		<updated>2012-06-28T00:00:00+00:00</updated>
		<id>http://supern.github.com/posts/code_standards.html</id>
		<content type="html"><![CDATA[<h2 id="为什么需要编码规范">为什么需要编码规范</h2>
<ul>
  <li>一个软件的生命周期中，80%的花费用于维护</li>
  <li>没办法保证开发人员和维护人员是同一个人</li>
  <li>如果将源码作为作品发布，他不但是给机器理解的，更需要给人理解</li>
  <li>编码规范可以改善软件的可理解性，并保持软件的清晰无误</li>
</ul>

<h2 id="原则">原则</h2>
<ul>
  <li>编码前想清楚代码的逻辑结构，必要时可借助图形图表来帮助思考</li>
  <li>切勿简单的Copy-Paste编码</li>
  <li>随手重构有“坏味道”的代码</li>
  <li>保持代码的简单清晰</li>
</ul>

<h2 id="格式布局">格式布局</h2>
<ul>
  <li>缩进排版，4个空格作为一个缩进的单位</li>
  <li>行长度，尽量避免一行的长度超过120个字符</li>
  <li>换行，当一个表达式无法在一行内书写时，可以依据如下规则断行：</li>
  <li>在一个逗号后面断开</li>
  <li>在一个操作符号前面断开</li>
  <li>宁可选择高级别的断行，而非低级别的断行</li>
  <li>新的一行应该与上一行同级别的表达式开头对齐</li>
  <li>如果以上规则导致你的代码混乱或者使你的代码堆积在右边，就代之缩进2个单位（8空格）</li>
  <li>语句块的“{”不要另起新行</li>
  <li>尽量使用圆括号来避免运算符优先级问题</li>
  <li>代码编码使用utf-8</li>
</ul>

<p>例如：</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>	private static synchronized horkingLongMethodName(int anArg, 
			Object anotherArg, String yetAnotherArg, 
			Object andStillAnother) { 
			... 
	} 
</code></pre></div></div>

<h2 id="注释">注释</h2>
<ul>
  <li>代码本身应该包含软件的大部分信息，通过代码便可以理解它的意思</li>
  <li>好的注释为了说明软件的意图或者总结程序的功能，而不是简单的重复代码，他解释的是“为什么”而不是“是什么”</li>
  <li>对使人困惑的代码进行重写而不是注释</li>
  <li>对过期的注释要进行更新修正，删除冗余和自相矛盾的注释，确保注释清晰正确</li>
  <li>对以下情况须注释：</li>
  <li>每个类的功能</li>
  <li>方法的功能（存取方法外）</li>
  <li>类变量的功能</li>
  <li>“令人惊异”的代码</li>
  <li>冗长或复杂的控制结构</li>
  <li>输入数据的限制</li>
  <li>去掉自动生成的“// TODO Auto-generated method stub”</li>
  <li>待改进的代码用“//FIXME:”进行注释</li>
</ul>

<p>例如：</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>	/**
	 * @author sanping.li
	 * AST节点接口
	 *
	 */
	public interface Node {
	
		/**
		 *  节点创建完成之后，准备添加子节点
		 */
		public void open();
		...
	}
</code></pre></div></div>

<h2 id="命名">命名</h2>
<ul>
  <li>命名采用驼峰命名法</li>
  <li>变量名或函数名首字母小写，后面单词的首字母大写</li>
  <li>常量名全部大写</li>
  <li>类名首字母大写</li>
  <li>包名全部小写</li>
  <li>命名是为了区分标识，如果相同级别所有的元素都有相同的名字“装饰”，就可以去掉（比如布局文件，类名前面的Alipay）</li>
  <li>变量名要准确描述变量的含义，不要使用没意义的名字，不要随意使用缩写，特别是有歧义的缩写</li>
  <li>命名不要过长也不要过短，不要超过4个单词</li>
</ul>

<p>例如：</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>	package com.alipay.android.core;//包
	public class ActivityShell extends RootActivity {//类
	private int mType;//变量
	private boolean checkRequisite();//方法
	public static final int STATE_NOMARL = 0;//常量
</code></pre></div></div>

<h2 id="变量">变量</h2>
<ul>
  <li>推荐每行只声明一个变量</li>
  <li>不要将不同类型的变量声明放在一块</li>
  <li>变量声明可以使用制表符对齐</li>
  <li>显式的声明变量的作用域</li>
  <li>尽量缩小变量的作用域，加强封装性。若没足够理由，不要使用public类的变量</li>
</ul>

<p>例如：</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>	private int 					mState;
	private String 					mName;
	private Map&lt;String,Object&gt; 		mCache;
</code></pre></div></div>

<h2 id="语句">语句</h2>
<ul>
  <li>每行只包含一条语句</li>
  <li>避免在一个语句中给多个变量赋值</li>
  <li>语句块尽管只有一行语句，也尽量加上“{}”</li>
  <li>switch语句的每个case后面需要有break或者return语句</li>
  <li>switch语句必须要default语句</li>
</ul>

<p>例如：</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>	if (mType == TYPE_XML){
		...
	}
	
	switch (mState) {
		case STATE_PAUSE:
			...
			break;
		case STATE_INSTALLING:
			...
			break;
		default:
			throw new Exception("error msg");
	}
</code></pre></div></div>

<h2 id="方法">方法</h2>
<ul>
  <li>每个方法只做一件事并做好</li>
  <li>每个方法的长度不要超过47行</li>
  <li>方法的参数个数尽量少，不要超过5个</li>
  <li>逻辑嵌套层次不要大于三层</li>
  <li>一个方法只有一个出口</li>
</ul>

<p>例如：</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>	public int doSomething(int arg1,int arg2){
		int retVal = 0;
		...
		return retVal;
	}
</code></pre></div></div>

<h2 id="类">类</h2>
<ul>
  <li>一个类不但要封装数据，还要封装操作</li>
  <li>使用常量来代替“魔法数字”</li>
  <li>每个类的长度不要超过1000行</li>
  <li>不要使用对象来访问静态变量和方法</li>
</ul>

<p>例如：</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>	public class Sample{
		private static final int TYPE_XML = 0;
		...
		Processor.parser(argument);//不要new Processor().parser(argument)访问静态方法和变量
		...
		if(mType == TYPE_XML){//用常量来替换“魔法数字”，而不是if(mType == 0){
	}
</code></pre></div></div>

<h2 id="包">包</h2>
<ul>
  <li>包不要划分的过粗也不要过细</li>
  <li>包的划分按段来区分功能及子功能的模块</li>
</ul>

<h2 id="异常处理">异常处理</h2>
<ul>
  <li>尽量减小try块的体积，不要嵌套try块。</li>
  <li>捕获了异常就需要对它进行适当的处理，而不是丢弃，否则应该向上抛</li>
  <li>在catch语句中尽可能指定具体的异常类型，必要时使用多个catch，不要试图处理所有可能出现的异常。</li>
  <li>充分运用finally，保证所有资源都被正确释放</li>
  <li>不要在finally中出现return语句</li>
  <li>在异常处理模块中提供适量的错误原因信息，组织错误信息使其易于理解和阅读。</li>
  <li>全面考虑可能出现的异常以及这些异常对执行流程的影响，不要使用异常来做流程控制。</li>
  <li>异常捕获不是万能的，不要出现问题全套进来</li>
</ul>

<p>例如：</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>	try {
		...
	} catch (FileNotFoundException fe) {
		Log.e(TAG,fe.getMessage());//组织错误信息
	} catch (IOException ie) {
		Log.e(TAG,ie.getMessage());//组织错误信息
	} catch (Exception e){
		...//不处理应该向上抛
	} finally {
		...
	}
</code></pre></div></div>

<h2 id="资源">资源</h2>
<ul>
  <li>尽量使用资源而不是代码来完成功能</li>
  <li>布局文件要尽量简洁，且模块清晰</li>
  <li>尽量使用样式来控制布局元素的外观</li>
  <li>字符常量要放到strings.xml</li>
  <li>9png的四个区域最好画全</li>
  <li>一定不要忘记关闭流</li>
  <li>游标使用方切记关闭游标</li>
</ul>

<h2 id="生命周期">生命周期</h2>
<ul>
  <li>应用程序生命周期的对象关联的应该是Application Context</li>
  <li>Activity生命周期的数据关联的才是Activity Context</li>
  <li>要考虑Activity被回收时候的数据保存和恢复，不单是Activity的数据还有Application的数据</li>
</ul>

<h2 id="内存管理">内存管理</h2>
<ul>
  <li>同样的数据只保存一个副本</li>
  <li>列表类的数据尽量使用AdapterView来展示</li>
  <li>使用Adapter的时候注意convertView的处理，并可以考虑ViewHolder</li>
  <li>尽量不要去处理（合成，拷贝）bitmap</li>
  <li>bitmap对象过多的时候考虑使用软引用</li>
  <li>尽量使用android的activity而非view</li>
  <li>尽量少用静态变量，否则需要显示的去释放它所占的内存</li>
</ul>

<p>例如：</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>	public View getView(int position, View convertView, ViewGroup parent) {
		if (convertView == null) {
			...//创建视图
		}
		...//做数据处理
	}
</code></pre></div></div>

<h2 id="操作习惯">操作习惯</h2>
<ul>
  <li>常格式化代码（eclipse使用ctrl+shift+F）</li>
  <li>去除不必要的包导入（eclipse使用ctrl+o）以及不用的变量和方法</li>
  <li>代码提交</li>
  <li>提交代码前用版本控制工具查看所做的修改</li>
  <li>提交代码前要先做update</li>
  <li>提交代码的需要写备注，本次修改的详细信息，如果是fix bug，需要给出bug的headline或链接</li>
</ul>

<p>-EOF-</p>
]]></content>
	</entry>
	
	<entry>
		<title>新的开始</title>
		<link href="http://mytharcher.github.com/posts/fresh-start.html" />
		<updated>2012-05-26T00:00:00+00:00</updated>
		<id>http://supern.github.com/posts/fresh-start.html</id>
		<content type="html"><![CDATA[<p>那些年，写过的HTML。<br />
一个轮回啊，又回到静态页面了。<br />
感谢github，让我这土鳖知道还可以这么玩，自己真的是有些跟不上了。<br />
好吧，重新开始。<br /><br /></p>

<p>-EOF-</p>
]]></content>
	</entry>
	
</feed>