纯粹是个人学习总结,如有不对的地方请吐槽。
目录结构
app目录下放全局配置文件,包括Application
base目录一眼就看清是什么
di目录存放dagger有关的文件
ui这个目录也很清楚
config是配置有关的文件
delegate是监听Activity和Fragment生命周期的文件,这里就是不需要继承的关键代码
di同样是dagger相关的文件,我这用的是dagger2
mvp就是我们的mvp各个模块的基类以及接口
screen是存放dp和sp设配文件的工具类,后面会将怎么使用
sharedpre不是很形象,仔细看还是能看出是SharedPreferences相关类
后面的目录就不介绍了
先来看看library下的Activity基类
public abstract class LibBaseActivity extends AppCompatActivity implements IActivity, IView {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initInject();//执行注入
initData();//初始化
}
/{@link IActivity 接口实现}/
@Override
public View getLayoutView() {
return null;
}
@Override
public boolean eventBus() {
return false;
}
@Override
public boolean fragment() {
return false;
}
/{@link IView 接口实现}/
@Override
public void showLoading() {
}
@Override
public void hideLoading() {
}
@Override
public void showMessage(String message) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
/其他方法/
/**
- 获取AppComponent
@return AppComponent */ protected AppComponent getAppComponent() { return AppDelegate.sAppDelegate.getAppComponent(); } }
关于IActivity接口我们先来看看delegate目录下的文件
再来看看IActivity里面的方法
public interface IActivity {
/**
* 获取当前布局Id
*
* @return
*/
int getLayoutId();
/**
* 执行注入方法
*/
void initInject();
/**
* 获取当前显示的布局
*
* @return
*/
View getLayoutView();
/**
* 子类做初始化操作
*/
void initData();
/**
* 是否有事件绑定
*
* @return
*/
boolean eventBus();
/**
* 是否使用fragment
*
* @return
*/
boolean fragment();
}
eventBus这个方法用于判断是否需要事件监听,返回true就完成了事件注册和事件注销
fragment这个方法用于判断是否需要监听fragment生命周期。
是不是觉得,看到这里还是不清楚到底是怎么回事,不用担心,这很正常,下面就来介绍如何不需要继承也能监听activity和Fragment的生命周期。
神奇之处就在于Application.ActivityLifecycleCallbacks和FragmentManager.FragmentLifecycleCallbacks对就是它们让我们脱离继承也能监听activity和Fragment的生命的周期,也许有很多小伙伴都不知道这个(我以前我也是其中之一),只是写着写着,就发现继承也存在不便(当你你已经继承了一个类,如果使用到其他第三方库,它也需要继承他的类,这时就JJ了)。
下面来看看监听的具体实现AppDelegate类,监听的关键代码
/**
* 在application的onCreate方法中调用
*/
public void onCreate() {
mActivityLifecycle = new ActivityLifecycle();
mApplication.registerActivityLifecycleCallbacks(mActivityLifecycle);
sAppDelegate = this;
}
第一行创建activity监听器,第二行设置监听器,fragment监听器后面介绍
然后在Application中创建并调用onCreate方法这样就完成了监听
mAppDelegate = new AppDelegate(sApp);
//这个方法执行之后会监听每个activity和fragment的生命周期
//建议在Application的onCreate方法里面调用
mAppDelegate.onCreate();
ActivityLifecycleCallbacks具体有那些回调方法可以自行百度,这里就不介绍了。
上面的没有看懂也没关系,只需要看懂下面的如何调用就可以了
总结一下如何调用:
public class App extends Application { private AppDelegate mAppDelegate; //当前app实例对象 public static App sApp; //全局上下文对象 public static Context sContext;
@Override public void onCreate() { super.onCreate(); sApp = this; sContext = this; mAppDelegate = new AppDelegate(sApp); //这个方法执行之后会监听每个activity和fragment的生命周期 //建议在Application的onCreate方法里面调用 mAppDelegate.onCreate(); initInject();//初始化全局注入 } /** * 初始化全局注入 */ public void initInject() { /**初始化注入,这个方法调用了之后就会调用{@link com.junwu.mvplibrary.config.IConfigModule#applyOptions(ConfigModule.Builder)}方法配置参数, * 接着就会调用{@link com.junwu.mvplibrary.config.IRegisterApiModule#registerComponents(IRepositoryManager)}方法,设置api接口 * 可以在测试接口确定了之后在调用该方法,比如:测试阶段需要选择测试服务器地址,选择之后再调用这个方法 **/ mAppDelegate.injectRegApiService(new AppConfigModule(), new RegisterApiModule()); }
} 关键代码就三句话: mAppDelegate = new AppDelegate(sApp); mAppDelegate.onCreate(); mAppDelegate.injectRegApiService(new AppConfigModule(), new RegisterApiModule()); 前面两句很好理解,最后一句就是设置OkHttp、Retrofit、RxCache的配置类和关于Retrofit、RxCache的api接口service类的配置
到这里,Activity和Fragment的生命周期监听部分和控件的初始化和事件注册,已经介绍完了,下面继续看关于MVP部分。
我们在写Activity和Fragment的时候一般都有base类,这里有两种选择,一就是自己写base类但是必须要实现IActivity和IFragment接口就行,也可以直接继承LibBaseActivity和LibBaseFragment,这里面实现也比较简单,就是实现了IActivity和IFragment两个接口。
再来看看dagger的配置,如果对dagger不熟悉的就自行查阅相关文档
这篇关于MVP模式对dagger的要求不高,只需要知道基本概念即可,如果实在不想看dagger的直接照搬也是可以的。
dagger相关的文件Component、Module、Scope以及注解Inject
AppComponent这个就是让Inject和Module产生关系的类
Module类有:AppModule配置Model的,关于更多Module
举个例子来看看,可能会更清楚
@ViewScope
@Component(modules = {ViewModule.class, ModelModule.class, UtilsModule.class}, dependencies = AppComponent.class)
public interface IViewComponent {
/*****************************activity注入***************************/
// void inject(StartActivity activity);
/*****************************Fragment注入***************************/
void inject(StartFragment fragment);
void inject(HomeFragment fragment);
/*****************************其他注入***************************/
}
从这里不难看出这个Component依赖AppComponent、ViewModule、ModelModule、UtilsModule
AppComponent在mvpLibary模块下:
@Singleton @Component(modules = {AppModule.class, ClientHttpModule.class, ConfigModule.class}) public interface AppComponent {
/** * 注入 * * @param delegate AppDelegate */ void inject(AppDelegate delegate); /** * 获取当前application对象 * * @return Application */ Application getApplication(); /** * 获取OkHttpClient */ OkHttpClient getOkHttp(); /** * 获取Retrofit */ Retrofit getRetrofit(); /** * 获取RxCache */ RxCache getRxCache(); /** * 获取RxCacheBuild对应的实体 */ RxCacheBuilderEntity getRxCacheBuilderEntity(); /** * 获取IRepositoryManager */ IRepositoryManager getIRepositoryManager();
}
这个就像是基础模块的获取类
ViewModule,这个必须同你写的代码是一个Module下
@Module public class ViewModule {
private IView mIView; private Activity mActivity; public ViewModule(IView view) { this(null, view); } public ViewModule(Activity activity, IView view) { mActivity = activity; this.mIView = view; } @ViewScope @Provides public Activity provideActivity() { return mActivity; } @ViewScope @Provides public IView provideIView() { return mIView; }
}
这里的IView和Presenter里面的IView以及Activity实现的IView有密切关系
ModelModule类的代码
@Module public class ModelModule {
@ViewScope @Provides StartContract.Model provideStartContractModel(StartModel startModel) { return startModel; }
}
UtilsModule就不介绍了,它是用于配置一些工具类的注入,为了思路清晰就单独分出来了
然后在看看LibBasePresenter
public class LibBasePresenter<M extends IModel, V extends IView> implements IPresenter { protected M mModel; protected V mView; //是否注册了eventBus事件 private boolean isEventBus = false;
/** * 处理IView的所有业务逻辑 * * @param m model 数据来源,网络、文件、数据库等数据 */ public LibBasePresenter(IModel m) { this.mModel = (M) m; onStart(); } /** * 处理IView的所有业务逻辑 * * @param v IView的子类接口实现类 */ public LibBasePresenter(IView v) { this(null, v); } /** * 处理IView的所有业务逻辑 * * @param m model 提供网络、文件、数据库等数据来源 * @param v IView的子类接口实现类 */ public LibBasePresenter(IModel m, IView v) { if (m != null) this.mModel = (M) m; if (v != null) this.mView = (V) v; onStart(); } @Override public void onStart() { if (useEventBus()) { registerEventBus(); } } @Override public void onDestroy() { //解除订阅 if (mCompositeDisposable != null) { mCompositeDisposable.clear(); } if (isEventBus) { EventBus.getDefault().unregister(this); isEventBus = false; } if (mModel != null) { mModel.onDestroy(); } mModel = null; mView = null; } /** * 注册EventBus事件 */ protected void registerEventBus() { EventBus.getDefault().register(this); isEventBus = true; } /** * 是否注册事件 * * @return */ protected boolean useEventBus() { return false; }
}
请看构造函数Model和View都是可以为空的,这就可以根据业务来判断虚部需要Model模块,有的MVP是吧Model模块和Presenter是融合在一起的,对于一些业务不是很复杂的可以这么做,如果业务比较多还是建议将Model和Presenter区分开。
看在这里基本上应该已经看懂了,下面就来总结一下:
1:IViewComponent将所有需要注入的类都用它来注入
2:ModelModule所有的Model都有它来提供
3:ViewModule里面将所有的Activity和Fragment都视为IView,在LibBasePresenter里面会自动转换为对应的子类,减少了IView的注册
4:还是要将代码自己梳理一遍,具体可以参照MVPAttempt
这里打个小广告:关于MVPAttempt框架的应用这里有个app已经上线,有兴趣的可以下载下来看看
所有的注入都由IViewComponent来完成,可能会太死板,如果有特殊注入就可以按照dagger完整的方式写一套注入来完成,这样也是可以的。