BaseActivity 里到底应该怎样才会死写哪些内容

BaseActivity的封装思想及YzsBaseActivity详解_Android开发_动态网站制作指南
BaseActivity的封装思想及YzsBaseActivity详解
来源:人气:498
BaseActivity在我们的项目中非常常用,所以,有一个好的封装会让我们的开发事半功倍 ,但是他怎么样封装才能方便我们的开发呢,这就是我们这片博客要讲解的内容。
在开始之前先安利两个项目,其实也可以说是一个项目,只不过被我拆分出来了,
一个共享的开发框架
/yaozs/YzsLib
YzsBaseActivity
BaseActivity的框架
/yaozs/YzsBaseActivity
这两个项目都正在维护中,baseactivity就是yzslib中拆分出来的,过年期间没有维护,给自己放了个假,嘿嘿,现在有开始继续维护。感兴趣的可以star下。里面有详细介绍,今天讲的所有东西都是YzsBaseActivity中的内容。
有人说现在流行的是mvp架构的程序,但我想问你,mvp架构的目的是什么呢? 他就是为了让代码的阅读性和可拓展性更强,同样,我写这篇博客的目的也是,而且我认为,在一些界面,根本就没必要使用mvp架构,架构是人写出来的,是死的东西,而人是活的,不要舍本逐末。当然,我也知道mvp架构的好处,所以,在这里提一句,我的这个封装是为了让一些简单的界面,常用的界面更加简洁的书写出来。没有必要说我这个app的架构是mvp就全用他。
接下来我们开始封装我们这种简单的界面,首先我们要弄清,我们需要在最基本的baseactivity里封装什么呢?
接收传值方法
Android 4.4版本以上沉浸式的封装
Toolbar的封装
界面之间消息传递的封装(EventBus)
加载中动画的封装
有了这些封装,我们在基本的activity中就减少了很多代码,比如加载动画,我们封装完成之后,可能只需要一个方法的调用,loading界面就出现了。
下面把我写的封装拿出来,给大家做一下参考,抛砖引玉。
1.跳转方法
* 界面跳转
* @param clazz 目标Activity
otected void readyGo(Class&?& clazz) {
readyGo(clazz, null);
* 跳转界面,
* @param clazz
目标Activity
* @param bundle 数据
protected void readyGo(Class&?& clazz, Bundle bundle) {
Intent intent = new Intent(this, clazz);
if (null != bundle)
intent.putExtras(bundle);
startActivity(intent);
* 跳转界面并关闭当前界面
* @param clazz 目标Activity
protected void readyGoThenKill(Class&?& clazz) {
readyGoThenKill(clazz, null);
* @param clazz
目标Activity
* @param bundle 数据
protected void readyGoThenKill(Class&?& clazz, Bundle bundle) {
readyGo(clazz, bundle);
* startActivityForResult
* @param clazz
目标Activity
* @param requestCode 发送判断值
protected void readyGoForResult(Class&?& clazz, int requestCode) {
Intent intent = new Intent(this, clazz);
startActivityForResult(intent, requestCode);
* startActivityForResult with bundle
* @param clazz
目标Activity
* @param requestCode 发送判断值
* @param bundle
protected void readyGoForResult(Class&?& clazz, int requestCode, Bundle bundle) {
Intent intent = new Intent(this, clazz);
if (null != bundle) {
intent.putExtras(bundle);
startActivityForResult(intent, requestCode);
2.接收传值方法
* @param extras
protected abstract void getBundleExtras(Bundle extras);
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//当手机版本大于等于4.4时才会使用的方法,沉浸式
if (Build.VERSION.SDK_INT &= Build.VERSION_CODES.KITKAT) {
setTranslucentStatus(true);
//这个对象不是android api中自带的,是我们自己写的
SystemBarTintManager tintManager = new SystemBarTintManager(this);
tintManager.setStatusBarTintEnabled(true);
tintManager.setStatusBarTintResource(R.color.colorPrimaryDark);//通知栏所需颜色
Bundle extras = getIntent().getExtras();
if (null != extras) {
getBundleExtras(extras);
EventBus.getDefault().register(this);
initContentView(savedInstanceState);
mToolbar = (Toolbar) findViewById(R.id.toolbar);
if (null != mToolbar) {
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayShowTitleEnabled(false);
initTitle();
initView();
initLogic();
* 替代onCreate的使用
protected abstract void initContentView(android.os.Bundle bundle);
* 初始化view
protected abstract void initView();
* 初始化逻辑
protected abstract void initLogic();
这样封装base,当使用者继承baseactivity时,会强制实现几个方法,而每个方法都有他自己的功能,这样就会使Activity的使用者使用起来更加清晰,即使维护者与开发者不是同一个人,其逻辑的清晰程度也会让他快速上手。
3.Android 4.4版本以上沉浸式的封装
在2中已经出现了,就是这个方法
//当手机版本大于等于4.4时才会使用的方法,沉浸式
if (Build.VERSION.SDK_INT &= Build.VERSION_CODES.KITKAT) {
setTranslucentStatus(true);
//这个对象不是android api中自带的,是我们自己写的
SystemBarTintManager tintManager = new SystemBarTintManager(this);
tintManager.setStatusBarTintEnabled(true);
tintManager.setStatusBarTintResource(R.color.colorPrimaryDark);//通知栏所需颜色
SystemBarTintManager 他是怎么写的呢,这个不在我们今天要讨论的范围,所以请直接参考
YzsBaseActivity
/yaozs/YzsBaseActivity
我的这个开源项目,里面有他的。
4.Toolbar的封装
同样是在onCreate方法中
5.界面之间消息传递的封装(EventBus)
mToolbar = (Toolbar) findViewById(R.id.toolbar);
if (null != mToolbar) {
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayShowTitleEnabled(false);
initTitle();
* 初始化toolbar
protected void initTitle() {
title = (TextView) findViewById(R.id.toolbar_title);
back = (ImageView) findViewById(R.id.toolbar_back);
iv_menu = (ImageView) findViewById(R.id.toolbar_iv_menu);
tv_menu = (TextView) findViewById(R.id.toolbar_tv_menu);
if (null != back) {
back.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
在这里说明下,我在我的库中findid不是吧他写死在中,而是在valuse中的创建了ids文件,
在这里把他引用出来,而在我们使用过程中如果你用到了,在你的xml把这个id使用出来就可以(id一致),如果不用,过着有更复杂的写法,将initTitle这个方法重写,就可以。
6.加载中动画的封装
在我的baseActivity框架中,我封装成的是一个loadingdialog,一个仿win10的loading,一个是自己写的动画
* 显示默认加载动画 默认加载文字
protected void showLoadingDialog() {
LoadingDialog.showLoadingDialog(this);
* 显示加载动画 默认加载文字
* @param type
protected void showLoadingDialog(int type) {
LoadingDialog.showLoadingDialog(this, type);
* 显示加载动画 默认加载文字,自定义图片
* @param type
protected void showLoadingDialog(int type, int drawableId) {
LoadingDialog.showLoadingDialog(this, type, drawableId);
* 显示默认加载动画 自定义加载文字
* @param str
protected void showLoadingDialog(String str) {
LoadingDialog.showLoadingDialog(this, str);
* 显示加载动画 自定义加载文字
* @param type
* @param str
protected void showLoadingDialog(int type, String str) {
LoadingDialog.showLoadingDialog(this, type, str);
* 显示加载动画 自定义加载文字 自定义图片(只对YzsDialog有效果)
* @param type
* @param str
protected void showLoadingDialog(int type, String str, int drawable) {
LoadingDialog.showLoadingDialog(this, type, str, drawable);
* 取消加载动画
protected void cancelLoadingDialog() {
LoadingDialog.cancelLoadingDialog();
同样在,其他地方调用loading时,也是一句话调用
LoadingDialog.showLoadingDialog(this, type, str, drawable);使用这个方法。具体使用请参考yzsbaseactivity源码。
这样一个最基础的baseactivity就封装完成了,但是本着为重复页面和重复需求服务的原则,就衍生出了YzsBaseListActivity和YzsBaseHomeActivity。就像命名一样,一个是为了列表list界面服务,一个是为普通首页服务如下图
这样的界面经常会在我们的app中出现,而我们做了什么封装呢,在这里首先声明一下我使用的几个库
1.FlycoTabLayout——viewpager指示器 与 导航栏控件
2.fragmentation——为”单Activity + 多Fragment”,”多模块Activity + 多Fragment”架构而生,替代官方fragment
3.eventbus——事件总线
4.BaseRecyclerViewAdapterHelper——RecyclerView的强大的BaseAdapter
通过对这几个库的封装让我们可以更加简单的写出一个界面
首先,最最长常用的list界面,让我们来一起封装,我的上一篇博客中介绍过,但是有些地方没有说出为什么这样封装,在这里详细说明下,就当上一篇的深度解释。
当我们封装这样的Activity时,涉及到一个东西就是泛型,为什么是泛型呢,因为在这样的界面,他就是一个重复的列表展示,所以他们的对象都是同一个对象,所以我们在类创建时,就要把他声明出来,声明之后,我们在其他的地方就可以直接调用了。
public abstract class YzsBaseListActivity&T& extends YzsBaseActivity
同样,为了我们这样的界面可以适配更多的类型,我们使用recyclerview,为什么使用他呢,因为recyclerview的功能更加强大,他的强大之处在于这几个方面
可以实现listview,gridview,瀑布流多种布局
回收机制比listview和gridview更加优秀
可定制性更加强大
下面,开始将BaseRecyclerViewAdapterHelper封装到我们的Activity中,这里最关键的地方就是一个问题,一般情况下我们是自己写adapter,单独的写出一个类出来,我们要做的就是把adapter封装在Activity中,让使用者不用关心adapter的创建,直接去使用它,但是adapter又需要list的数据类型,这样问题就回来了,我们最开始就声明了一个泛型数据类,我们在写listActivity时,写出了数据类型就可以直接使用了,就像这样
* Author: 姚智胜
* Version: V1.0版本
* Descrtion: list的activity的封装使用
public class ListActivity extends YzsBaseListActivity&DemoListBean& {
private static final String TAG = "ListActivity";
* 初始化子布局
* 在这个方法里处理的是recyclerview的所有的初始化,
* 包括对他的展示形式,是list或grid或瀑布流
protected void initItemLayout() {
//调用该方法设置adapter的子布局
setLayoutResId(R.layout.item_list_demo);
* adapter内部布局的处理
* @param baseViewHolder BaseViewHolder
* @param demoListBean
protected void MyHolder(BaseViewHolder baseViewHolder, DemoListBean demoListBean) {
protected void initContentView(Bundle bundle) {
protected void initLogic() {
protected void getBundleExtras(Bundle extras) {
protected void onEventComing(EventCenter center) {
那么YzsBaseListActivity怎么写的呢,我们想一下,recyclerview需要的设置都有哪些呢?设置他的布局方式,同时,是否打开他的baseadapter中为我们提供的loadmore方法(这个方法在新版本的adapter有些变化,但是不影响我们的使用,我们只需在base中改变一下就可以了)
public abstract class YzsBaseListActivity&T& extends YzsBaseActivity {
private static final String TAG = "YzsBaseListActivity";
* 普通list布局
protected static final int LINEAR_LAYOUT_MANAGER = 0;
* grid布局
protected static final int GRID_LAYOUT_MANAGER = 1;
* 瀑布流布局
protected static final int STAGGERED_GRID_LAYOUT_MANAGER = 2;
* 默认为0单行布局
private int mListType = 0;
* 排列方式默认垂直
private boolean mIsVertical =
* grid布局与瀑布流布局默认行数
private int mSpanCount = 1;
protected RecyclerView mRecyclerV
protected YzsListAdapter mA
* 子布局id
private int layoutResId = -1;
protected void initView() {
initItemLayout();
mRecyclerView = (RecyclerView) findViewById(R.id.yzs_base_list);
chooseListType(mListType, mIsVertical);
if (-1 == layoutResId) {
throw new RuntimeException("layoutResId is null!");
mAdapter = new YzsListAdapter(layoutResId, new ArrayList&T&());
mRecyclerView.setAdapter(mAdapter);
* 设置子布局layout
* @param layoutResId 子布局layout
public void setLayoutResId(@LayoutRes int layoutResId) {
this.layoutResId = layoutResId;
* 初始化子布局
protected abstract void initItemLayout();
* 是否打开加载更多
protected void openLoadMoreSize(boolean loadMore) {
mAdapter.loadMoreEnd(loadMore);
* @param type
布局管理type
* @param isVertical 是否是垂直的布局 ,true垂直布局,false横向布局
protected void setListType(int type, boolean isVertical) {
mListType =
mIsVertical = isV
protected void setSpanCount(int spanCount) {
if (spanCount & 0)
mSpanCount = spanC
* @param listType 选择布局种类
private void chooseListType(int listType, boolean isVertical) {
switch (listType) {
case LINEAR_LAYOUT_MANAGER:
//设置布局管理器
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.setOrientation(isVertical ? LinearLayoutManager.VERTICAL : LinearLayoutManager.HORIZONTAL);
mRecyclerView.setLayoutManager(linearLayoutManager);
case GRID_LAYOUT_MANAGER:
GridLayoutManager gridLayoutManager = new GridLayoutManager(this, mSpanCount);
gridLayoutManager.setOrientation(isVertical ? GridLayoutManager.VERTICAL : GridLayoutManager.HORIZONTAL);
mRecyclerView.setLayoutManager(gridLayoutManager);
case STAGGERED_GRID_LAYOUT_MANAGER:
//设置布局管理器
StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager
(mSpanCount, isVertical ? StaggeredGridLayoutManager.VERTICAL : StaggeredGridLayoutManager.HORIZONTAL);
mRecyclerView.setLayoutManager(staggeredGridLayoutManager);
//设置布局管理器
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setOrientation(isVertical ? LinearLayoutManager.VERTICAL : LinearLayoutManager.HORIZONTAL);
mRecyclerView.setLayoutManager(layoutManager);
* adapter内的处理
* @param baseViewHolder BaseViewHolder
* @param t
protected abstract void MyHolder(BaseViewHolder baseViewHolder, T t);
public class YzsListAdapter extends BaseQuickAdapter&T, BaseViewHolder& {
public YzsListAdapter(int layoutResId, List&T& data) {
super(layoutResId, data);
protected void convert(BaseViewHolder baseViewHolder, T t) {
MyHolder(baseViewHolder, t);
我们这样封装完成,在我们自己的Activity中,在这个方法initItemLayout()中,把reyclerview的所有初始化写完就可以了,剩下的在MyHolder(BaseViewHolder baseViewHolder, T t);这个方法中处理子布局就可以了,说的极限点,现在继承baselistactivity之后,最简单的list界面,你最少只需要写5到8行设置属性就搞定了,剩下的全是adapter里面的处理了,是不是简化了很多代码,同时让代码更加清晰了。
这也是我写这个库的目的,就是方便,就是要懒。
同样,basehomeActivity使用的是FlycoTabLayout这个开源库,不知道的可以去github搜索一下,下面来说下这也首页的封装思想,抛开那写定制度特别高的app,一般的app在首页都是在底部有几个导航按钮,上面是fragment进行切换,那么我们要封装到什么程度呢??
封装到我只需告诉程序我给你图标文字,和我这几个fragment都是什么就可以了,如果有选中要求,提供动态选择方法,这就完成了,不多说,先上代码看看我们可以几行写完
public class IndexActivity extends YzsBaseHomeActivity {
private static final String TAG = "IndexActivity";
private String[] mTitles = {"首页", "消息", "联系人", "更多"};
//未选中图片
private int[] mIconUnselectIds = {
R.drawable.tab_home_unselect, R.drawable.tab_speech_unselect,
R.drawable.tab_contact_unselect, R.drawable.tab_more_unselect};
//选中图片
private int[] mIconSelectIds = {
R.drawable.tab_home_select, R.drawable.tab_speech_select,
R.drawable.tab_contact_select, R.drawable.tab_more_select};
protected void initContentView(Bundle bundle) {
setContentView(R.layout.ac_index);
protected void initTab() {
//4个fragment
setmFragments(new YzsBaseFragment[]{new HomeFragment(), new MsgFragment(), new PersonFragment(), new MoreFragment()});
setmIconSelectIds(mIconSelectIds);
setmIconUnSelectIds(mIconUnselectIds);
protected void initLogic() {
//一句话调用loading
showLoadingDialog(LoadingDialog.YZS_LOADING, R.mipmap.icon);
new Handler().postDelayed(new Runnable() {
public void run() {
//取消loading
cancelLoadingDialog();
protected void getBundleExtras(Bundle extras) {
protected void onEventComing(EventCenter center) {
就这些代码,我们首页activity就写完了,同时没有你们所说的fragment覆盖问题,在这里要提一句,fragment重叠的问题是因为google原来fragment库的一个bug或者不能说是bug的问题,但他已经在api25的lib里修复了,我们这个库不管你用api几都会不出现这个问题,因为他是可以处理的,在这向大家推荐一个fragmentation
,上面我也提到,在这里使用,他提供了fragment的懒加载方法等非常使用的东西,有兴趣的可以去看看。
同时,我们的首页有两种形式,一种是可滑动的viewpager,一种是不支持滑动的framelayout格式,在我们的封装中,只需使用ids中指定的id就可以了,viewpager使用viewpager的id,framelayout使用它的id,程序会自动判断。是不是很方便!!
下面上basehome代码
public abstract class YzsBaseHomeActivity extends YzsBaseActivity {
private static final String TAG = "YzsBaseHomeActivity";
* title文字部分
private String[] mT
* 未选中图标数组
private int[] mIconUnSelectI
* 选中图标数组
private int[] mIconSelectI
* fragment集合
protected YzsBaseFragment[] mF
protected CommonTabLayout mTabL
* 图标信息对象
private ArrayList&CustomTabEntity& mTabEntities = new ArrayList&&();
protected ViewPager mViewP
protected FrameLayout mFrameL
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setBundle(savedInstanceState);
protected void initView() {
mTabLayout = (CommonTabLayout) findViewById(R.id.yzs_base_tabLayout);
mViewPager = (ViewPager) findViewById(R.id.yzs_base_tabLayout_viewPager);
mFrameLayout = (FrameLayout) findViewById(R.id.yzs_base_tabLayout_frameLayout);
initTab();
if (null == mFragments || mFragments.length == 0) {
throw new RuntimeException("mFragments is null!");
initTabEntities();
if (null == mTabLayout) {
throw new RuntimeException("CommonTabLayout is null!");
if (null == mTitles || mTitles.length == 0) {
mTabLayout.setTextsize(0);
if (null != mViewPager) {
Log.e(TAG,"Choose_ViewPager");
initViewpagerAdapter();
initFragments();
Log.e(TAG,"Choose_frameLayout");
setTabSelect();
* 初始化图标图片文字fragment数据
private void initTabEntities() {
if (null == mFragments || mFragments.length == 0 || mFragments.length != mIconSelectIds.length ||
mFragments.length != mIconUnSelectIds.length) {
throw new RuntimeException("mFragments is null!or Fragments and the number of ICONS do not meet");
for (int i = 0; i & mFragments. i++) {
mTabEntities.add(new TabEntity(mTitles == null ? "" : mTitles[i], mIconSelectIds[i], mIconUnSelectIds[i]));
mTabLayout.setTabData(mTabEntities);
* 初始化Fragments
private void initFragments() {
//加载mFragments
if (getBundle() == null) {
//加载mFragments
loadMultipleRootFragment(R.id.yzs_base_tabLayout_frameLayout, 1, mFragments);
// 这里库已经做了Fragment恢复,所有不需要额外的处理了, 不会出现重叠问题
for (int i = 0; i & mFragments. i++) {
Log.e(TAG,"initFragments" + i);
mFragments[i] = findFragment(mFragments[i].getClass());
* 初始化viewpager的adapter
private void initViewpagerAdapter() {
mViewPager.setAdapter(new MyPagerAdapter(getSupportFragmentManager()));
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
public void onPageSelected(int position) {
mTabLayout.setCurrentTab(position);
public void onPageScrollStateChanged(int state) {
* 为mTabLayout
private void setTabSelect() {
Log.e(TAG,"setTabSelect");
mTabLayout.setOnTabSelectListener(new OnTabSelectListener() {
public void onTabSelect(int position) {
if (null != mViewPager) {
mViewPager.setCurrentItem(position);
int toDoHidden = -1;
for (int i = 0; i & mFragments. i++) {
if (!mFragments[i].isHidden()) {
toDoHidden =
Log.e(TAG,"查找显示中的fragment-------" + toDoHidden);
Log.e(TAG,"选中的fragment-------" + position);
Log.e(TAG,"确定显示中的fragment-------" + toDoHidden);
showHideFragment(mFragments[position], mFragments[toDoHidden]);
public void onTabReselect(int position) {
if (position == 0) {
Log.e(TAG,"再次选中项" + position);
* 设置TabLayout属性,所有关于TabLayout属性在这里设置
protected abstract void initTab();
* 获取Fragment数组
* @return mFragments
public YzsBaseFragment[] getmFragments() {
* 放入Fragment数组(必须继承YzsBaseFragment)
* @param mFragments
public void setmFragments(YzsBaseFragment[] mFragments) {
this.mFragments = mF
* 获取选中图标数组
* @return mIconSelectIds
public int[] getmIconSelectIds() {
return mIconSelectI
* 放入选中图标数组
* @param mIconSelectIds
public void setmIconSelectIds(int[] mIconSelectIds) {
this.mIconSelectIds = mIconSelectI
* 获取未选中图标数组
* @return mIconUnSelectIds
public int[] getmIconUnSelectIds() {
return mIconUnSelectI
* 放入未选中图标数组
* @param mIconUnSelectIds
public void setmIconUnSelectIds(int[] mIconUnSelectIds) {
this.mIconUnSelectIds = mIconUnSelectI
* 获取mTitles数组
* @return mTitles
public String[] getmTitles() {
* 放入mTitles数组
* @param mTitles
public void setmTitles(String[] mTitles) {
this.mTitles = mT
public Bundle getBundle() {
public void setBundle(Bundle bundle) {
this.bundle =
private class MyPagerAdapter extends FragmentPagerAdapter {
public MyPagerAdapter(FragmentManager fm) {
super(fm);
public int getCount() {
return mFragments.
public CharSequence getPageTitle(int position) {
return mTitles == null ? "" : mTitles[position];
public Fragment getItem(int position) {
return mFragments[position];
封装结束,继承我们写的base就可以几行代码写完一个界面了, 是不是很爽。当然,我写的这些可能不是特别完美,如果大家有更好的意见,可以提出来,我会改进,并且baseactivity会继续更新,把大家在app中发现大量出现的界面都会写进来,让你几行就搞定。这片博客就到这里结束了,希望大家可以让我这个抛砖人的功夫没白花,让你们有自己的思路。
最后再次安利下我的两个库
一个共享的开发框架
/yaozs/YzsLib
YzsBaseActivity
BaseActivity的框架
/yaozs/YzsBaseActivity
下次再见嘿嘿 (^o^)/YES!
优质网站模板

我要回帖

更多关于 洗衣机到底应该怎么挑 的文章

 

随机推荐