作为从ROM开发转行到应用开发的我来说,本书真是为我打开了一扇大门。正如作者所说,ROM开发不能算作应用开发,我们空有扎实的Java语言功底,却在应用开发处处碰壁。书籍概括了整个应用开发的流程,并且以一定的高度分析App竞品。这让我大大的收益,在此感谢作者的无私奉献。
一,建立AndroidLib类库,将于业务无关的公用逻辑存放到库中.
com.infrastructure.activity
com.infrastructure.cache
com.infrastructure.net
com.infrastructure.ui
com.infrastructure.utils
BaseActivity
业务无关的的公用逻辑二,将主项目中的类按照一定的规则划分,放入主项目的包中
- activity :分模块继续化包
- adapter
- db :SQLite相关的逻辑
- entity :实体
- engine : 业务先关的类
- ui : 自定义控件
- utils : 公用方法
- interfaces : 接口(intercace)
- listener : 基于Listener的接口
原则上是不出现嵌套类的形式,这个跟我做ROM开发时很不一样,在底层开发中的高内聚的特点,内部类很常用,所以不能完全否定内部类的用法。
在菜单File -> New Module…选择Android Library
此时已经生成了目录以及相应的gradlew脚本
settings.gradle会成为
include ':app', ':baselib'
最后在app的build.gradle中添加依赖项
compile project(path: ':baselib')
完成
四大组件的生命周期是由AMS通过handler机制去hook周期函数。重新定义生命周期并不是改变这一生命周期的调用函数或顺序。而是将生命周期中的工作模块化(方法化)。
示例
public abstract class BaseActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initVariables();
initView(savedInstanceState);
loadData();
}
protected abstract void initVariables();
protected abstract void initView(Bundle savedInstanceState);
protected abstract void loadData();
}
此时集成父类的子类就可以不重写Activity的生命周期函数onCreate()
,保证了更细化的单一职责
的设计模式。在编写代码的过程中,向”父类层次抽象“能有效的提高代码的可读性,降低冗余。
public class AppBaseActivity extends BaseActivity {
@Override
protected void initVariables() {
}
@Override
protected void initView(Bundle savedInstanceState) {
}
@Override
protected void loadData() {
}
}
/* 面向对象的Click写法 */
btnLogin = (Button) findViewById(R.id.btn_Login);
btnLogin.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
//避免代码臃肿
gotoLoginActivity();
}
}
);
AndroidStudio导入GSON,只需要在项目设置中添加Lib依赖项就可以了
compile 'com.google.code.gson:gson:2.7'
Gson gson = new Gson();
WeatherEntity weatherEntity = gson.fromJson(content, WeatherEntity.class);
WeatherInfo weatherInfo = weatherEntity.getWeatherInfo();
if (weatherInfo != null) {
tvCity.setText(weatherInfo.getCity());
tvCityId.setText(weatherInfo.getCityId);
}
在组件之中传递实体需要用到序列化,实现Serializable接口或者Parcel接口
intent.putExtra("String", entity);//发送
getIntent().getSerializableExtra("String");//接受
利用实体化编程以及面向对象的编程的思想,将ListView的显示分装,作为普通的View去显示,而点击事件的处理等,操作,应该放到ListView的外部。符合单一职责
。
提供一个工具函数,转换失败就返回默认值
convertToInt
public final static int convertToInt(Object value, int defaultValue) {
if (value == null || "".equals(value.toString().trim())) {
return defaultValue;
}
try {
return Integer.valueOf(value.toString());
} catch (NumberFormatException e) {
try {
return Double.valueOf(value.toString()).intValue();
} catch (NumberFormatException e1) {
return defaultValue;
}
}
}
substring()函数的越界问题
String convertStr = "T";
String needStr = "";
if (convertStr.length() > 1) {
needStr = convertStr.substring(1, 2);
}
参考自:Android开发进阶,从小工到专家 ————何红辉
优化代码
无论什么时候,代码的规范性,合理性是程序员入职的首先要求,作用自然不言而喻。而现实是代码一直在演化,在改进。而改进的过程就可以成为重构的过程。而改进的过程是需要随时进行的。
常见重构手法
提取子函数
我们在第二节的时候所用到的手法的第一步,就是将代码符合单一职责
,提取并封装成一个个单独方法。
上移函数,字段到父类
这是一个继承原则的最好体现,将子类公用的代码上移到父类。改变父类就改变了所有子类。
下移函数,字段到子类
这个过程并不是与上面的相反,而是提取出差异,新建父类继承共性添加差异,组成新的共性父类。
封装固定的调用逻辑
这个很好理解,类似于链式启动
,将固定的逻辑封装为方法。
泛型编程
泛型编程适用于操作逻辑一样,但是具体的操作对象不一样。
避免使用过多参数(实体化编程)
总而言之,实体化编程更容易让人理解,同样更容易操作,上边1.4节就是最好的体现
转移函数
转移函数解决了类型之间的过度耦合问题,类A频繁的调用类B中的一个或一组方法,而类B调用此方法不频繁。这时候需要将B中的方法转移到A中。
将类型码转换为状态模式
基本原则多态
的简单应用,这涉及到一个java的涉及模式状态模式(对象行为型)
。简单的介绍:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
适用性:
1,一个对象的行为取决于它的状态, 并且它必须在运行时刻根据状态改变它的行为。
2,代码中包含大量与对象状态有关的条件语句:一个操作中含有庞大的多分支的条件(if else(或switch case)语句,且这些分支依赖于该对象的状态。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。
什么也不做的对象—NullObject
空指针异常(NullPointException)是非常常见的异常,我们为了避免空指针异常,通常在使用这个某个对象的时候要进行判空判断(在我的一个项目中,一个线程新New出来对象,传入另一个线程执行却报了空指针,复现率很低。最终原因是因为Java虚拟机允许CPU乱序执行,导致线程中对象可能还未创建成功,已经换了线程。最终引入volatile或者单例才能解决。)所以,空指针是防不胜防的。如何良好的处理空指针是代码重构的很重要的一环。
实现方式:创建一个空的对象实现功能接口,在获取这个的时候,判断是否为空,如果为空,则返回空对象的实例。1.6 节的思想也是类似的。
其实我们对代码的重构,本质上遵循了六大设计原则。这是编码的根本准则,只有遵循这些准则,才会让代码避免恶化
的脚步。拥有更好的扩展性,易读性和便于维护。
作者 [@PirateBrook]
2016 年 10月 20日