前言
日常开发中,每个 Activity、Fragment 中都有很多共同的部分,比如 Toast、ButterKnike、startActivity、初始化 init() 等。其实可以根据 Activity 封装一个 BaseActivity,把 ButterKnike 抽取上去,把 注入对象 抽取上去:譬如 presenter 对象。还可以把 Component 抽取到父类(包括通用的 getApplication)。
这样做的目的就是一次封装,方便子类使用,不需要在每个 Activity、Fragment 中写总是写重复的代码了,把重复的工作都抽出来放在父类,自己就继承父类即可。
下面就项目中的封装简单介绍下如何封装 Activity、Fragment、Presenter.
Acitvity 的封装与使用
BaseActivity
继承 AppCompatActivity,重写 onCreate() 方法,并设置布局文件,但是这个布局应该由子类提供(每个 Activity 的布局都不一样),所以代码中定义一个抽象方法 setLayout() 给子类去实现,提供自己的布局。
其他由子类提供的东西,都可以在父类定义一个抽象方法,让子类实现即可。当然,该封装的 Activity 得声明为 abstract 类型的。
也可以提供一些常用的方法:startActivity()
另外,还可以把公共的东西抽取到父类 onCreate() 方法中,如:ButterKnife 控件绑定、Component 的注入。
public abstract class BaseActivity<T extends BasePresenter> extends AppCompatActivity {
private Unbinder mUnbinder; //用于解除 butterknife 的绑定
private AppApplication mApplication; //很常用,不解释
@Inject
T mPresenter ; //把 Presenter 抽出来,泛型表示,因为每个子类需要的 presenter 都不确定
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
//字体图标的一些渲染
LayoutInflaterCompat.setFactory(getLayoutInflater(), new IconicsLayoutInflater(getDelegate()));
super.onCreate(savedInstanceState);
setContentView(setLayout());
mUnbinder = ButterKnife.bind(this);
this.mApplication = (AppApplication) getApplication(); //常用的东西直接在父类里面获取好,子类直接享用
setupAcitivtyComponent(mApplication.getAppComponent());
init(); //在父类留下公共的方法,让子类去实现
}
@Override
protected void onDestroy() {
super.onDestroy();
if(mUnbinder !=Unbinder.EMPTY){
mUnbinder.unbind();
}
}
// protected void startActivity(Class c){
//
// this.startActivity(new Intent(this,c));
// }
//
// 提供很多公共的方法,这样不用每个 Activity 都把需要的再写一遍
//让子类实现该方法,设置自己的布
public abstract int setLayout();
public abstract void setupAcitivtyComponent(AppComponent appComponent);//把参数 丢给子类 去使用
//初始化一些数据
public abstract void init();
}
MainActivity
上面介绍了 Activity 的封装,下面继承封装的 BaseActivity,实现该抽象类的几个抽象方法。
public class MainActivity extends BaseActivity {
@BindView(R.id.navigation_view)
NavigationView mNavigationView;
@BindView(R.id.drawer_layout)
DrawerLayout mDrawerLayout;
@BindView(R.id.tool_bar)
Toolbar mToolBar;
@BindView(R.id.tab_layout)
TabLayout mTabLayout;
@BindView(R.id.view_pager)
ViewPager mViewPager;
private View headerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
//设置自己的 布局
@Override
public int setLayout() {
return R.layout.activity_main;
}
//从父类传过来的 appComponent,这里暂且不使用
@Override
public void setupAcitivtyComponent(AppComponent appComponent) {
}
@Override
public void init() {
initDrawerLayout();
initTablayout();
}
.
.
.
}
Fragment 的封装与使用
Fragment 的封装和 Activity 的封装基本一样的,根据上面封装好的 BaseActvity 很快就可以把 BaseFragment 封装妥当。
BaseFragment
继承 Fragment,重写 onCreateView() 方法。
//和 BaseActivity 基本一样
public abstract class BaseFragment<T extends BasePresenter> extends Fragment {
private Unbinder mUnbinder;
private AppApplication mApplication;
private View mRootView;
@Inject
T mPresenter ; //和 BaseActivity 一样,抽取出来
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
mRootView = inflater.inflate(setLayout(), container, false);//和 BaseActivity 一样,layout() 由子类实现,提供布局。
mUnbinder= ButterKnife.bind(this, mRootView);//同样把 ButterKnife 抽出来
return mRootView;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
this.mApplication = (AppApplication) getActivity().getApplication(); //和 BaseActivity 一样
setupAcitivtyComponent(mApplication.getAppComponent());
init();
}
@Override
public void onDestroy() {
super.onDestroy();
if(mUnbinder != Unbinder.EMPTY){
mUnbinder.unbind();
}
}
public abstract int setLayout(); //提供给子类实现的抽象类
public abstract void setupAcitivtyComponent(AppComponent appComponent);
public abstract void init();
}
封装的基本就和 BaseActivity 封装的一样。
RecommendFragment
继承上面封装好的 BaseFragment,实现几个抽象方法即可。
//继承 BaseFragment ,指定 Presenter 的类型:RecommendPresenter
public class RecommendFragment extends BaseFragment<RecommendPresenter> implements RecommendContract.View {
@BindView(R.id.recycle_view)
RecyclerView mRecyclerView;
private RecomendAppAdatper mAdatper;
@Inject
ProgressDialog mProgressDialog;
@Override
public int setLayout() {
return R.layout.fragment_recomend; //设置 layout(),父类 onCreateView() 方法中调用本方法获得子类的 布局
}
@Override
public void setupAcitivtyComponent(AppComponent appComponent) {
// 参数 appComponent 从父类传递过来,就是父类调用本方法
DaggerRecommendComponent.builder().appComponent(appComponent)
.remmendModule(new RemmendModule(this)).build().inject(this);
}
@Override
public void init() {
mPresenter.requestDatas(); //mPresenter 是从父类来的
}
.
.
.
}
Activity、Fragment 的封装就是如此简单,但是具体封装方式还得根据自己的业务需求或者个人喜好来封装。下面说说 Presenter 的封装。
Presenter 的封装与使用
presenter 经常用到两个东西 : Model、View 定义泛型,子类继承 BasePresenter 的时候指定 泛型 的类型即可。
BasePresenter
public class BasePresenter<M,V extends BaseView> {
protected M mModel;
protected V mView;
//M、v 通过子类构造方法传过来
public BasePresenter(M m,V v){
this.mModel=m;
this.mView = v;
}
}
子类中,通过自己的构造方法调用父类的构造方法,这样子类中就可以很方便的使用 model 、view 对象
RecommendPresenter
BasePresenter 中已经抽取出 model、view ,这样子类就不用总是去 new 来获取对象,仅仅通过构造方法 把对象传过去。
public class RecommendPresenter extends BasePresenter<RecommendModel,RecommendContract.View> {
//在需要依赖的地方使用这个注释:需要 RecommendModel、RecommendContract.View 对象
@Inject
public RecommendPresenter(RecommendModel model, RecommendContract.View view) {
super(model, view); //调用父类的构造方法,把 两个对象 传给父类构造方法
}
public void requestDatas() {
mView.showLodading();
mModel.getApps(new Callback<PageBean<AppInfo>>() {
@Override
public void onResponse(Call<PageBean<AppInfo>> call, Response<PageBean<AppInfo>> response) {
if(response !=null){
mView.showResult(response.body().getDatas());
}
else{
mView.showNodata();
}
mView.dimissLoading();
}
@Override
public void onFailure(Call<PageBean<AppInfo>> call, Throwable t) {
mView.dimissLoading();
mView.showError(t.getMessage());
}
});
}
}
总结
以上关于 Activity、Fragment、Presenter 的封装都是比较简单的,功能也没有很多,这里只做一个抛砖引玉的作用,更完善的封装还得根据自己业务需求去修改。
本文为菜鸟窝作者 吴威龙 的连载
菜鸟窝是专业的程序猿在线学习平台,提供最系统的 Android 项目实战课程
如需转载,请联系菜鸟窝公众号(cniao5),并注明出处。
菜鸟窝-程序猿的黄埔军校。 如需转载,请注明出处(菜鸟窝 , 原文链接: http://www.cniao5.com/forum/thread/811b02a2437e11e7932a00163e0230fa )关注公众号免费领取"140套优秀开源项目源码"