你该拥有自己的一套项目结构----Kotlin+Dagger2+MVP+Rx+Retrofit

前言:

架构是什么?框架是什么?
其实很简单,一句话:框架是软件,架构不是软件。框架落脚在“架”字上,可以理解成名词性的,是一个客观性的名词存在,如.Net Framework;而架构体现在“构”字上,理解成构造,是一个动词性的,是一系列动作发生的策略性体现。先大局后局部,就出现了架构;先通用后专用,就出现了框架。
让我这个菜鸟LOL玩家看来:架构就是LOL里面的一套打法、战术,框架则是精确到QWER+走位。

1.以前不懂得架构思想的我,拿到一个项目之后,囫囵吞枣的按照需求文档,也能“有模有样”的按时提交成果。这样直接导致的后果就是,很怕leader又要改改改,加加加。
2.当然网上有很多优秀的架构,别人的东西不是百分百适合自己的项目,所以要结合理解,搭建出属于自己熟悉的一套架构。随着经验的增长,从而不断的完善自己的那一套。
3.本文难点不大,高手勿喷,欢迎指点。希望起到抛砖迎玉的作用,让每个开发者都有自己熟悉的一套架构。


源码https://github.com/KomoriWu/Http.git

目录

一、MVP 设计模式
二、网络请求框架(Rx+Retrofit )
三、Kotlin
四、Dagger2

此文不在讲述一、二 请看 上一篇博文
http://blog.csdn.net/sinat_27033869/article/details/66972339

二、网络请求框架(Rx+Retrofit )

其中相比上一次,我把网络请求的框架完全提取出来,直接无脑使用就行。
Android studio 导入方法:
第一步:

allprojects {
        repositories {
            ...
            maven { url 'https://jitpack.io' }
        }
    }

第二步:

dependencies {
            compile 'com.github.KomoriWu:Http:v1.0.0'
    }

在项目中的调用
//这里框架我之前是用Java语言写的,demo中的调用我用的Kotlin。之后我会响应号召,把网络请求的框架也改为Kotlin
1.这里写图片描述
调用者只需编写两个简单的类即可。


public class ArticleApi extends BaseApi {
    private String mPage;
    private String mSize;

    public ArticleApi(RxAppCompatActivity rxAppCompatActivity, String page, String size,
                      HttpOnNextListener listener) {
        super(rxAppCompatActivity, listener,BASE_URL);
        this.mPage = page;
        this.mSize = size;
        //是否显示加载框
        setShowProgress(false);
    }

    //提供请求所需字段的数据
    @Override
    public Observable getObservable(Retrofit retrofit) {
        Map<String, String> map = new HashMap<>();
        map.put("page", mPage);
        map.put("size", mSize);
        HttpService service = retrofit.create(HttpService.class);
        return service.getAllArticles(map);//传数据到HttpService
    }
}
public interface HttpService {
    @GET(GET_ALL_ARTICLES)
    Observable<ArticleBody> getAllArticles(@QueryMap Map<String, String> map);
}

在程序中调用:

 val articleApi: ArticleApi = ArticleApi(context as RxAppCompatActivity, page, size, object :
                HttpOnNextListener<ArticleBody>() {
            override fun onNext(t: ArticleBody?) {
                onLoadListListener.onSuccess(t);
            }

            override fun onError(e: Throwable?) {
                onLoadListListener.onFail(e);
            }
        })
        HttpManager.getInstance().doHttpDeal(articleApi)

十分清爽,无脑使用。实现原理可以看我上一篇博客,这里只是交大家如何使用。结合demo看,效果更佳。

三、kotlin

Demo中的代码大家可以发现,既有Java 也有 Kotlin。的确100%融合,有些地方用Kotlin省心很多。
kotlin是什么?多的话我不说,早学晚学都要学。以后找Android,不会这个,估计就被挤下去了。
刚开始接触kotlin时,十分惧怕,看网上博客一脸懵逼。很难吗?其实不然,大家只要搞懂几个关键点,之后写代码,多使用官方API文档。上手还是很快的。

1.配置
第一种:as在3.0以下的需要安装插件:
Android Studio的Kotlin插件, 用于支持Kotlin的语言特性.
选择: Preferences -> Plugins -> Install JetBrains plugin -> kotlin.

第二种:也是我极力推荐的,将as升级到3.0,一切省心省事,3.0的版本优化很大,完全支持kotlin。

2.添加依赖

 compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
    compile 'org.jetbrains.anko:anko-sdk15:0.8.3'

//快捷键:选择Code -> Convert Java File to Kotlin File, 更好的学习kotlin

Kotlin API 入门
1. 变量

⼀次赋值(只读)的局部变量:

val a: Int = 1 // ⽴即赋值
val b = 2 // ⾃动推断出 `Int` 类型
val c: Int // 如果没有初始值类型不能省略
c = 3 // 明确赋值

可变变量:

var x = 5 // ⾃动推断出 `Int` 类型
x += 1

当某个变量的值可以为 null 的时候,必须在声明处的类型后添加 ? 来标识该引⽤可为空。
如果 str 的内容不是数字返回 null

2.条件
在 Kotlin 中,if是⼀个表达式,即它会返回⼀个值。 因此就不需要三元运算符(条件 ? 然后 : 否则),因为普通的 if 就能胜任这个⻆⾊

// 传统⽤法
var max = a
if (a < b) max = b
// With else
var max: Int
if (a > b) {
max = a
} else {
max = b
}
// 作为表达式
val max = if (a > b) a else b

if的分⽀可以是代码块,最后的表达式作为该块的值:

val max = if (a > b) {
print("Choose a")
a
} else {
print("Choose b")
b
}

如果你使⽤ if 作为表达式⽽不是语句(例如:返回它的值或者 把它赋给变量),该表达式需要有 else 分⽀。

3.循环
when 取代了类 C 语⾔的 switch 操作符。其最简单的形式如下:

when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
else -> { // 注意这个块
print("x is neither 1 nor 2")
}
}

如果很多分⽀需要⽤相同的⽅式处理,则可以把多个分⽀条件放在⼀起,⽤逗号分隔:

when (x) {
0, 1 -> print("x == 0 or x == 1")
else -> print("otherwise")
}

我们可以⽤任意表达式(⽽不只是常量)作为分⽀条件

when (x) {
parseInt(s) -> print("s encodes x")
else -> print("s does not encode x")
}

我们也可以检测⼀个值在(in)或者不在(!in)⼀个区间或者集合中:

when (x) {
in 1..10 -> print("x is in the range")
in validNumbers -> print("x is valid")
!in 10..20 -> print("x is outside the range")
else -> print("none of the above")
}

For 循环
for 循环可以对任何提供迭代器(iterator)的对象进⾏遍历,语法如下:

for (item in collection) print(item)

如果你想要通过索引遍历⼀个数组或者⼀个 list,你可以这么做

for (i in array.indices) {
print(array[i])
}

4.函数
定义函数:带有两个 Int 参数、返回 Int 的函数:
fun+方法名+参数(参数名:类型)+返回类型(可以不写,自动判断。返回为空可省略)

fun sum(a: Int, b: Int): Int {
return a + b
}

将表达式作为函数体、返回值类型⾃动推断的函数:

fun sum(a: Int, b: Int) = a + b

函数返回⽆意义的值:

fun printSum(a: Int, b: Int): Unit {
println("sum of $a and $b is ${a + b}")
}

Unit 返回类型可以省略
//以上为Kotlin一些基础语法,简单易上手,有了这些看懂demo无压力

四、Dagger2在MVP中的使用

Dagger2:Dagger2现在由Google接手维护。是一个依赖注入的框架。
依赖注入:是面向对象编程的一种设计模式,其目的是为了降低程序耦合,这个耦合就是类之间的依赖引起的。
网上关于Dagger2的文章太多,比较后推荐这篇:
http://www.open-open.com/lib/view/open1482201981550.html


具体项目中我们如何使用呢?
先来看Demo的MVP+Dagger2的项目结构:
这里写图片描述
可能你觉得分包太多,但是实际层次更分明,结构更简单。日后维护、迭代再也不怕了。
MVP中的model :网络数据请求

class ArticleModelImpl : ArticleModel {

    override fun loaderArticle(context: Context, page: String, size: String,
                               onLoadListListener: OnLoadListListener) {

        val articleApi: ArticleApi = ArticleApi(context as RxAppCompatActivity, page, size, object :
                HttpOnNextListener<ArticleBody>() {
            override fun onNext(t: ArticleBody?) {
                onLoadListListener.onSuccess(t);
            }

            override fun onError(e: Throwable?) {
                onLoadListListener.onFail(e);
            }
        })
        //采用已经封装完毕的RX+Retrofit框架
        HttpManager.getInstance().doHttpDeal(articleApi)
    }

    interface OnLoadListListener {
        fun onSuccess(t: ArticleBody?)
        fun onFail(e: Throwable?)
    }
}

MVP中的View :将Model中得到的数据传给activity显示出来

interface ArticleView {
    fun addArticleList(articleBody: ArticleBody?)
}

MVP中的Presenter :中间体。将model与view连接起来

class ArticlePresenterImpl(private var mContext: Context,
                           private var mArticleView: ArticleView) :
        ArticlePresenter, ArticleModelImpl.OnLoadListListener {

    private var mArticleModel: ArticleModel? = null

    init {
        mArticleModel = ArticleModelImpl()
    }

    override fun loaderArticle(page: String, size: String) {
        mArticleModel?.loaderArticle(mContext, page, size, this)
    }

    override fun onSuccess(t: ArticleBody?) {
        mArticleView.addArticleList(t)
    }

    override fun onFail(e: Throwable?) {
    }

}

activity中的调用:
常规调用为:

 lateinit var mArticlePresenter: ArticlePresenter
mArticlePresenter = ArticlePresenterImpl(this, this)     mArticlePresenter?.loaderArticle("1", "8")

结合Dagger2

1.Module :生成依赖对象。@Module就是用来标准这个类的,而@Provide则是用来标注具体提供依赖对象的方法。由@Module 与@Provides 完成。提供数据。
我们这里提供数据的类是ArticlePresenterImpl

@Module
class ArticleModule(private var mContext: Context,
                    private var mArticleView: ArticleView) {
    @Provides
    fun providePresenter(): ArticlePresenter {
        return ArticlePresenterImpl(mContext, mArticleView)
    }
}

2.Component:是依赖需求方和依赖提供方之间的桥梁。
Dagger2提供依赖的是ArticleModule这个类。
Dagger2得到依赖的是MainActivity

@Component(modules = arrayOf(ArticleModule::class))
interface ArticleComponent {
    fun inject(mainActivity: MainActivity)
}

3.依赖需求方:在activity中的调用。
完成这些之后我们需要Build下项目,让Dagger2帮我们生成相关的Java类。接着我们就可以在activity中调用Dagger2生成的DaggerArticleComponent来实现注入

 @Inject
    lateinit var mArticlePresenter: ArticlePresenter
  DaggerArticleComponent.builder().articleModule(ArticleModule(this, this)).build().inject(this)
 mArticlePresenter.loaderArticle("1", "8")

下载demo学习更佳,欢迎start:
https://github.com/KomoriWu/Http.git

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值