從零開始搭建一個主流項目框架(二)—MVP+dagger2

個人博客:haichenyi.com。感謝關(guān)注

??接著上一篇簡單的框架,沒有看過的同鞋可以去喵一眼。上一篇我們搭好了簡單的框架,初始化一次的內(nèi)容丟在Application里面,所有的activity繼承一個類BaseActivity,還有Fragment繼承的一個類BaseFragment

??現(xiàn)在我們來加上MVP,不懂MVP的同鞋可以看一下,我前面寫過的三種主流框架的對比。我們先導(dǎo)入dagger2的兩個包,代碼如下:

implementation 'com.google.dagger:dagger:2.14.1'
annotationProcessor "com.google.dagger:dagger-compiler:2.14.1"

第一步

??新建BasePresenter接口,BaseMvpPresenter類去實現(xiàn)BasePresenter接口,代碼如下

package com.shfzwkeji.smartwardrobe.base;

/**
 * Author: 海晨憶.
 * Date: 2017/12/21
 * Desc: 不帶mvp的presenter的基類
 */
public interface BasePresenter<T extends BaseView> {
  void attachView(T baseView);

  void detachView();
}
package com.haichenyi.myproject.base;

/**
 * Author: 海晨憶
 * Date: 2018/2/23
 * Desc:帶mvp的presenter的基類
 */
public class BaseMvpPresenter<T extends BaseView> implements BasePresenter<T> {
  protected T baseView;

  @Override
  public void attachView(T baseView) {
    this.baseView = baseView;
  }

  @Override
  public void detachView() {
    this.baseView = null;
  }
}

??這里就只有兩個方法,一個是綁定view,還有一個是在ondestory方法里面解除綁定的方法,用來保證P層的生命周期和V層同步,避免了,當(dāng)V層銷毀的時候,P層仍然存在造成的內(nèi)存泄漏。

第二步

??新建BaseMvpActivity

package com.haichenyi.myproject.base;

import javax.inject.Inject;

/**
 * Author: 海晨憶
 * Date: 2018/2/23
 * Desc:帶MVP的Activity
 */
public abstract class BaseMvpActivity<T extends BasePresenter>  extends BaseActivity{
  @Inject
  protected T basePresenter;

  @Override
  @SuppressWarnings("unchecked")
  protected void initView() {
    super.initView();
    initInject();
    if (null != basePresenter) {
      basePresenter.attachView(this);
    }
  }

  protected abstract void initInject();

  @Override
  protected void onDestroy() {
    if (null != basePresenter) {
      basePresenter.detachView();
      basePresenter = null;
    }
    super.onDestroy();
  }
}

??運用dagger2注解的方式,生成P層,這里我們在用P層之前得先生成P層,所以initject方法一定要在basePresenter用之前調(diào)用,因為他就是生成P層的代碼。

??怎么生成呢?dagger我們一般都命名成di層,所以,我們先創(chuàng)建di層的package,項目結(jié)構(gòu)圖如下:

項目結(jié)構(gòu)圖.png

??這里給出的是mvp+dagger加入之后的項目結(jié)構(gòu)。我們重點看選中的di層,里面有4個package分別是component,module,qualifier,scope四個包,至于他們的作用分別是什么,請自行百度,google,dagger的用法。我這里先貼出這幾個類,接口的代碼:

ActivityComponent

package com.haichenyi.myproject.di.component;

import com.haichenyi.myproject.MainActivity;
import com.haichenyi.myproject.di.module.ActivityModule;
import com.haichenyi.myproject.di.scope.ActivityScope;

import dagger.Component;

/**
 * Author: 海晨憶
 * Date: 2018/2/23
 * Desc:
 */
@ActivityScope
@Component(dependencies = AppComponent.class, modules = ActivityModule.class)
public interface ActivityComponent {
  void inject(MainActivity mainActivity);
}

AppComponent

package com.haichenyi.myproject.di.component;

import com.haichenyi.myproject.di.module.AppModule;
import com.haichenyi.myproject.di.module.HttpModule;

import javax.inject.Singleton;

import dagger.Component;

/**
 * Author: 海晨憶
 * Date: 2018/2/23
 * Desc:
 */
@Singleton
@Component(modules = {AppModule.class, HttpModule.class})
public interface AppComponent {
}

ActivityModule

package com.haichenyi.myproject.di.module;

import dagger.Module;

/**
 * Author: 海晨憶
 * Date: 2018/2/23
 * Desc:
 */
@Module
public class ActivityModule {
}

AppModule

package com.haichenyi.myproject.di.module;

import com.haichenyi.myproject.base.MyApplication;

import dagger.Module;

/**
 * Author: 海晨憶
 * Date: 2018/2/23
 * Desc:
 */
@Module
public class AppModule {
  private MyApplication application;

  public AppModule(MyApplication application) {
    this.application = application;
  }
}

HttpModule

package com.haichenyi.myproject.di.module;

import dagger.Module;

/**
 * Author: 海晨憶
 * Date: 2018/2/23
 * Desc:
 */
@Module
public class HttpModule {
}

ActivityScope

package com.haichenyi.myproject.di.scope;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

import javax.inject.Scope;

/**
 * Author: 海晨憶
 * Date: 2018/2/23
 * Desc:
 */
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface ActivityScope {
}

??這幾個類,接口里面基本上都沒有內(nèi)容,因為這幾個類都是后面才會用的到的,這里我直接貼出來,說起來方便一些。還需要加兩個方法,在MyApplication里面加如下方法:

/**
   * 獲取AppComponent.
   *
   * @return AppComponent
   */
  public static synchronized AppComponent getAppComponent() {
    if (null == appComponent) {
      appComponent = DaggerAppComponent.builder()
          .appModule(new AppModule(getInstance()))
          .httpModule(new HttpModule())
          .build();
    }
    return appComponent;
  }

在BaseActivity里面加如下方法:

protected ActivityComponent getActivityComponent() {
    return DaggerActivityComponent.builder()
        .appComponent(MyApplication.getAppComponent())
        .activityModule(new ActivityModule())
        .build();
  }

??加完這兩個方法之后,肯定會有錯誤提示,重新編譯一遍項目就可以了,如果重新編譯一遍,還是不行,請重新對比一下,哪里不一樣。

第三步

??就是關(guān)于mvp的了,從上面圖應(yīng)該看到了,有一個presenter包,和contract包,我們之前有一篇博客講過,MVP就是多了很多個接口,這些接口寫在哪呢?就在contract層

MainContract 代碼如下:

package com.haichenyi.myproject.contract;

import com.haichenyi.myproject.base.BasePresenter;
import com.haichenyi.myproject.base.BaseView;

/**
 * Author: 海晨憶
 * Date: 2018/2/23
 * Desc:
 */
public interface MainContract {
  interface IView extends BaseView{

  }
  interface Presenter extends BasePresenter<IView>{
    void loadData();
  }
}

??這里我需要說明的就是Presenter接口繼承的是IVew,不是BaseView,頁面變化的方法都是在IView接口里面定義,邏輯處理,網(wǎng)絡(luò)請求方法都是在Presenter接口里面定義

MainPresenter 代碼如下

package com.haichenyi.myproject.presenter;

import com.haichenyi.myproject.base.BaseMvpPresenter;
import com.haichenyi.myproject.contract.MainContract;

import javax.inject.Inject;

/**
 * Author: 海晨憶
 * Date: 2018/2/23
 * Desc:
 */
public class MainPresenter extends BaseMvpPresenter<MainContract.IView>
    implements MainContract.Presenter {
  @Inject
  MainPresenter() {
  }

  @Override
  public void loadData() {
    baseView.showTipMsg("加載數(shù)據(jù)");
  }
}

??這里我需要說明的是注意繼承BaseMvpPresenter傳的是MainContract.IView,不是BaseView,實現(xiàn)MainContract.Presenter接口,還有一點就是注意構(gòu)造方法,上面有注解,這里的loadData里面應(yīng)該是我們的網(wǎng)絡(luò)請求邏輯,這里我放到后面一篇在說,這里我先就直接Toast,表示走了這個方法

第四步

??就是MainActivity,這里我貼出代碼

package com.haichenyi.myproject;

import android.os.Bundle;

import com.haichenyi.myproject.base.BaseMvpActivity;
import com.haichenyi.myproject.contract.MainContract;
import com.haichenyi.myproject.presenter.MainPresenter;

public class MainActivity extends BaseMvpActivity<MainPresenter> implements MainContract.IView {

  @Override
  protected int getLayoutId(Bundle savedInstanceState) {
    return R.layout.activity_main;
  }

  @Override
  protected void initData() {
    super.initData();
    initToolbar(true, false, true).setMyTitle("主頁").setMoreTitle("更多");
    basePresenter.loadData();
  }

  @Override
  protected void initInject() {
    getActivityComponent().inject(this);
  }
}

??這里我需要說明的是繼承BaseMvpActivity,泛型直接傳MainPresenter,然后,實現(xiàn)MainContract.IView接口,直接用basePresenter調(diào)用方法,需要實現(xiàn)initInject方法,只要是是繼承BaseMvpActivity的activity,都需要在ActivityComponent()里面注冊一邊。比方說,LoginActivity也是繼承的BaseMvpActivity,辣么,在di層的component包下面的ActivityComponent接口里面定義一個方法

void inject(LoginActivity loginActivity);

在LoginActivity的initInject方法里面寫同樣的代碼

getActivityComponent().inject(this);

就像這樣寫就可以了。

總結(jié)

??寫到這里,mvp+dagger2基本上完成了,MVP的目的就是解藕,把業(yè)務(wù)邏輯,網(wǎng)絡(luò)請求丟在P層,頁面不發(fā)生變化,就只用改P層邏輯,從而達到了解藕的目的。dagger2簡化了代碼,并且,它有著全局單例模式,和局部單例模式,優(yōu)化了我們的內(nèi)存,減少了內(nèi)存浪費。不用每次都去new一個P層對象出來。下一篇,我們就把網(wǎng)絡(luò)請求加上

項目鏈接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容