1.零屏简介
零屏是一个独立apk应用,主要于卡片的形式来展示一些基本信息,比如天气、常用应用、新闻、壁纸和运用内容等。可以做外单独的apk应用,但是它更适合的地方是集成在Launcher里面作为Launcher的负一屏,方便用户快速查看。
2.使用技术
2.1 MVP架构
零屏整体框架采用MVP架构,MVP是从MVC演进过来的,将视图和逻辑分离降低耦合。
2.2 Dagger2使用
Dagger2是一个依赖注入框架,它利用 APT在编译时生成辅助类,这些类继承特定父类或实现特定接口,程序在运行时 Dagger 加载这些辅助类,调用相应接口完成依赖生成和注入。对于MVP架构是最好的解耦工具,能充分的降低模块之间的耦合。
3.Dagger2使用详解
3.1.添加依赖
在项目build.gradle修改如下配置
dependencies {
classpath 'com.android.tools.build:gradle:2.2.2'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
在需要使用的module修改build.gradle
apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'
...
dependencies {
compile 'com.google.dagger:dagger:2.5'
apt 'com.google.dagger:dagger-compiler:2.5'
compile 'org.glassfish:javax.annotation:10.0-b28'
}
3.2注解
Inject用来标注目标类所依赖的属性和这个属性的构造函数
目标类是实际操作的类,如:Activity引用Presenter,Activity就是目标类,Presenter是需要用Inject来标注的类
每一个被Inject标注的对象都有一个对应的工厂类
// 无参数
public class TestInfo {
@Inject
public TestInfo() {
}
}
// 引用
Inject
TestInfo testInfo;
// 有参数
public class NewsPresenter extends IPresenter<INewsView> {
@Inject
public NewsPresenter(INewsView view) {
super(view);
}
为NewsPresenter 添加@Inject注解
INewsView 需要通过Module来提供
Module用来解决三方库和构造函数有特定参数的类
Module
public class NewsModule {
INewsView mINewsView;
public NewsModule(INewsView iView) {
this.mINewsView = iView;
}
@LayoutScope
@Provides
public INewsView provideIPhiView() {
return mINewsView;
}
}
此类以@Module注解
提供INewsView ,返回INewsView 对象的方法需要通过@Provides来注解,方法名可以随便定义,但一般与provide开头
不能有相同返回值的函数,如果需要可以用@Named注解来区分
Component是一个桥梁,一端是目标类,一端是目标类的实例。负责将目标类依赖的实例注入到目标类
LayoutScope
Component(modules = {NewsModule.class}, dependencies = {AppComponent.class})
public interface NewsComponent {
public void inject(NewsLayout newsLayout);
}
以@注解Component
将目标依赖实例注入到目标类
具体引用
public class NewsLayout extends BaseLayout implements INewsView {
@Inject
NewsPresenter mNewsPresenter;
public NewsLayout(Context context) {
super(context);
}
@Override
public void inject() {
DaggerNewsComponent.builder()
.appComponent(ComponentManager.getsInstance(getContext()).getAppComponent())
.newsModule(new NewsModule(this))
.build()
.inject(this);
}
}
inject方法中将NewsLayout依赖的对象(NewsPresenter )注入了。mNewsPresenter对象只要添加@Inject注解就可以直接使用了
build里面创建了NewsPresenter对象,Inject将创建好的对象赋值给mNewsPresenter
3.2.概念总结
Inject用来标注目标类所依赖的属性和这个属性的构造函数
目标类是实际操作的类,如:Activity引用Presenter,Activity就是目标类,Presenter是需要用Inject来标注的类
每一个被Inject标注的对象都有一个对应的工厂类
Component是一个桥梁,一端是目标类,一端是目标类的实例。负责将目标类依赖的实例注入到目标类
- Module用来解决三方库和构造函数有特定参数的类
Provides用来注解在Module中定义的函数,这些函数返回的是三方类、有参数的类(无参数的也可以)和有参数的类的参数类型。
Singleton没有创建单例的能力(不是单例),我们只需要保证ApplicationComponent只有一个实例,是Scope自定义注解的一种特例
Scope可以理解为将Module和Component统一生命周期,在使用过程中我们一般会自定义Scope
- dependencies是Component注解的一个属性,可理解为依赖继承,与Java中的继承意义类似
- Named可结合Provides提供相同返回值得函数
3.4.编译过程
为对应类创建工厂类的过程步骤如下:
步骤1:查找Module中是否存在创建该类的方法。
步骤2:若存在创建类方法,查看该方法是否存在参数
步骤2.1:若存在参数,则按从步骤1开始依次初始化每个参数
步骤2.2:若不存在参数,则直接初始化该类实例,一次依赖注入到此结束
步骤3:若不存在创建类方法,则查找Inject注解的构造函数,
看构造函数是否存在参数
步骤3.1:若存在参数,则从步骤1开始依次初始化每个参数
步骤3.2:若不存在参数,则直接初始化该类实例,一次依赖注入到此结束
3.5.优缺点
优点
对比正常使用
mNewsAdapter = new NewsAdapter(getContext());
- 对比我们之前的正常使用,减少了依赖不用再new了,而且如果构造函数发生变化也不用依次去修改每一个使用的地方
缺点
- 中间代码太多,一般会有对应的mudule和Component
- 注入对象参数值不能动态修改,遇到的问题是retrofit在common中多url问题
4.零屏类图
如下为零屏的类关系图: