快速搭建新项目框架2-mvp 结构

2017/10/29 posted in  Android

之前有两篇文章已经详细介绍过 mvp Android 中的MVP 模式 地图区域绘制 MVP 实践 ,本篇结合上篇的依赖注入使用

定义 base 类

定义 view 和 Presenter 的 interface

public interface BaseView<T> {

}
public interface BasePresenter<T> {

    /**
     * Binds presenter with a view when resumed. The Presenter will perform initialization here.
     *
     * @param view the view associated with this presenter
     */
    void  takeView(T view);

    /**
     * Drops the reference to the view when destroyed
     */
    void dropView();

}


presenter 的takeView在 view 对应的resume 生命周期中获取 view ,在 desdroy 中 将 view 赋值为 null ,以免内存泄露。

Contract

Contract 为 view 和 Presenter 的继承接口
举个例子 实现一个 splash 页面


public interface SplashContract {
    interface View extends BaseView<Presenter> {
        void showWaitingPage();
    }

    interface Presenter extends BasePresenter<View> {
        void goLogin();

        void goMain();

        void tryLogin();

        void takeView(SplashContract.View view);
    }
}

SplashPresenter

class SplashPresenter implements SplashContract.Presenter{

    @Inject
    public SplashPresenter() {
    }

    @Nullable
    private SplashContract.View mView;

    @Override
    public void goLogin() {
        ToastUtils.showShort("go login");
        ActivityUtils.startActivity(LoginActivity.class);
    }

    @Override
    public void goMain() {
        ToastUtils.showShort("go Main");
        ActivityUtils.startActivity(MainActivity.class);
    }

    @Override
    public  void tryLogin() {
        Handler requestHandler = new Handler(Looper.getMainLooper());
        requestHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                boolean islogin = false;
                if (islogin) {
                    goMain();
                } else {
                    goLogin();
                }
            }
        }, 1000);


    }

    @Override
    public void takeView(SplashContract.View view) {
        mView = view;
        if (mView != null) {
            mView.showWaitingPage();
        }
    }

    @Override
    public void dropView() {
        mView = null;
    }
}

注意
在构造方法是 使用 @Inject 注解,一遍 dagger 框架能找到该类
每次调用view 中的方法时,都要进行判空,感觉上用 kotlin 代码会更方便点

public class SplashActivity extends BaseActivity implements SplashContract.View {
    @Inject
    Context mContext;

    @Inject
    SplashContract.Presenter mPresenter;

    @BindView(R.id.ll_root)
    LinearLayout mLlRoot;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mPresenter.tryLogin();
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                ContactUtil.getContacts(mContext);
            }
        });
        thread.start();
    }

    @Override
    protected int getLayout() {
        return R.layout.activity_splash;
    }

    @Override
    protected void onResume() {
        super.onResume();
        mPresenter.takeView(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mPresenter.dropView();
    }

    @Override
    public void showWaitingPage() {
//        mLlRoot.setBackground(R.mipmap.ic_launcher);
    }
}
  1. Activity 实现view 接口,并在onResumeakeViewonDestroydropView
  2. 通过 dagger 注入找到对应的 presenter

为了能找到 Presenter ,我们还应该建立接口和对应实现的联系 ,可以使用 @bind注解

SplashPresenterModule

@Module
public abstract class SplashPresenterModule {

    @ActivityScoped
    @Binds
    abstract SplashContract.Presenter statitsticsPresenter(SplashPresenter presenter);
}

然后在上篇文章提到的ActivityBindingModule 中,加入该 Activity 和改 module

@Module
public abstract class ActivityBindingModule {
    @ActivityScoped
    @ContributesAndroidInjector(modules = TellTruePresenterModule.class)
    abstract MainActivity mainActivity();

    @ActivityScoped
    @ContributesAndroidInjector(modules = SplashPresenterModule.class)
    abstract SplashActivity splashActivity();

}