这个基类是自己封装的,不是很完善,之前一直打算写博客
却一直没动手
这里进行先断网,再测试,可以看到界面切换的三个状态
项目中最常见的界面不外乎 标题栏加上具体内容
标题栏:返回按钮 + 标题 + 菜单按钮
具体内容:需要考虑考虑加载状态
这就可以考虑进行封装了,还有一个方法,常用成员变量也可以考虑封装到基类中,方便使用
本基类主要封装内容
1.DataBinding避免findViewById
2.toolbar满足基本要求的封装
3.Activity管理类绑定生命周期
4.界面加载状态切换管理类封装
5.一些常用资源声明为成员变量到基类
BaseActivity传入泛型,主要用于DataBinding绑定xml
`public abstract class BaseActivity extends AppCompatActivity implements View.OnClickListener {`
成员变量
`/**
* DataBinding 对象
*/
protected T mBinding;
/**
* 界面状态切换 对象
*/
protected VaryViewHelper mHelper;
/**
* 本Actvitiy类名
*/
protected static String ACTIVITY_NAME;
/**
* onCreate方法中保存的数据
*/
protected Bundle savedInstanceState;
/**
* 上下文
*/
protected Activity context;
/**
* 全局上下文 ,这里进行了强转,需要注意自己的Application实际类名
*/
protected App application;
/**
* 屏幕宽,高, 状态栏高
*/
protected int screenWidth, screenHeight, statusBarHeightX;`
主要onCreate初始化
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.savedInstanceState = savedInstanceState;
LogUtils.i(ACTIVITY_NAME = getClass().getSimpleName());
context = this;
application = (App) getApplication();
screenWidth = ScreenUtils.getScreenWidthPixels(getActivity());
screenHeight = ScreenUtils.getScreenHeightPixels(getActivity());
statusBarHeightX = ScreenUtils.getStatusHeight(getActivity());
ActivityCollector.addActivity(this); //添加进activity管理
mBinding= DataBindingUtil.setContentView(this,setLayoutId()); //获取DataBinding对象
initToolBar();
initView();
initListener();
mHelper = new VaryViewHelper.Builder() //初始化界面状态管理器 ,需要自己写几类布局
.setDataView(findViewById(getRootId()))
.setLoadingView(LayoutInflater.from(this).inflate(R.layout.layout_loadingview,
null))//加载页,无实际逻辑处理
.setEmptyView(LayoutInflater.from(this).inflate(R.layout.layout_emptyview,
null))//空页面,无实际逻辑处理
.setErrorView(
LayoutInflater.from(this).inflate(R.layout.layout_errorview, null))//错误页面
.setRefreshListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mHelper.showLoadingView();
getData();
}
})
.build();
mHelper.showLoadingView();
getData();
}
主要进行类DataBinding绑定布局,初始化界面管理类,初始化toolbar等
下面是抽象出来的必须实现的方法
/**
* 设置布局 layout 的 资源id
*/
protected abstract int setLayoutId();
/**
*设置除了toolbar 以外的 内容布局content的id ,防止toolbar在页面状态切换时被覆盖
*/
protected abstract int getRootId();
/**
* 初始化ToolBar
*/
protected abstract void initToolBar();
/**
* 初始化一些非加载数据相关的view
*/
protected abstract void initView();
/**
* 初始化监听
*/
protected abstract void initListener();
/**
* 获取网络数据,获取数据后也在这里更新数据
*/
protected abstract void getData();
/**
* BaseActivity已经实现了OnClickListener 接口 ,这里进行了空实现,防止部分界面不需要点击事件,也就不需要实现
* 如果需要直接重写该方法
*/
@Override
public void onClick(View v) {
}
其他工具类 及onDestroy方法接触Activity管理类的管理
@Override
public void onBackPressed() {
finish();
}
@Override
protected void onDestroy() {
ActivityCollector.removeActivity(this);
super.onDestroy();
}
/**
* Toast工具类
*/
public Toast toast;
public void showToast(String text) {
if (toast == null) {
toast = Toast.makeText(context, text, Toast.LENGTH_SHORT);
} else {
toast.setText(text);
}
toast.show();
}
public void showToast(BaseActivity activity, String text) {
if (toast == null) {
toast = Toast.makeText(activity, text, Toast.LENGTH_SHORT);
} else {
toast.setText(text);
}
toast.show();
}
public void showToast(int textId) {
showToast(getString(textId));
}
public BaseActivity getActivity() {
return this;
}
public Intent getIntent(Class clazz) {
return new Intent(context, clazz);
}
public void startIntent(Class clazz) {
startActivity(getIntent(clazz));
}
public int dp2px(int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
context.getResources().getDisplayMetrics());
}
protected void hideStatusBar() {
int flag = WindowManager.LayoutParams.FLAG_FULLSCREEN;//隐藏状态栏, 定义全屏参数
Window window = getWindow(); //获得当前窗体对象
window.setFlags(flag, flag);//设置当前窗体为全屏显示
}
private long lastClickTime;
/**
* 实现连续点击两次才退出应用程序
*/
public void exit() {
if ((System.currentTimeMillis() - lastClickTime) > 2000) {
showToast("再按一次退出" + context.getResources().getString(R.string.app_name));
lastClickTime = System.currentTimeMillis();
} else {
ActivityCollector.removeAll();
System.exit(0);
}
}
不需要的工具方法可以删除
本基类包含初始化Toolbar内容,旨在统一风格
使用ToolBar需要给Activity配上style
主要加上这两条属性
- true
- false
布局文件中必须包含Toolbar
然后在initToolBar实现中进行设置ToolBar
activity_main.xml
layout_toolbar.xml
对于toolbar中的menu实现类中进行加载
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.menu_item_four, menu);
menu
.findItem(R.id.item1)
.setVisible(true);
menu.findItem(R.id.item2)
.setVisible(true);
menu.findItem(R.id.item3)
.setVisible(true);
return true;
}
res/menu/menu_item_four.xml
public class MainActivity extends BaseActivity {
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.menu_item_four, menu);
menu
.findItem(R.id.item1)
.setVisible(true);
menu.findItem(R.id.item2)
.setVisible(true);
menu.findItem(R.id.item3)
.setVisible(true);
return true;
}
@Override
protected void initToolBar() {
mBinding.includeToolbar.idToolbar.setTitle("");
mBinding.includeToolbar.toolbarTitle.setText("mainactivity");
setSupportActionBar(mBinding.includeToolbar.idToolbar);
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
}
@Override
protected void initView() {
}
@Override
protected void initListener() {
mBinding.btn.setOnClickListener(this);
}
@Override
protected int setLayoutId() { //传入layout布局
return R.layout.activity_main;
}
@Override
protected int getRootId() { //传入布局中除去toolbar部分的布局id
return R.id.content_main;
}
@Override
protected void getData() {
//网络请求
OkHttpUtils
.get()
.url("http://gank.io/api/data/Android/10/1")
.build()
.execute(new GankCallback() {
@Override
public void requestError(Call call, Exception e, int id) {
mHelper.showErrorView();//切换加载错误界面
}
@Override
public void onResponse(String response, int id) {
mBinding.tv.setText(response);
mHelper.showDataView();//切换正常界面
}
});
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn:
break;
}
}
}
需要注意的是 基类初始化 只是初试标题栏等不需要网络数据的部分
在onCreate最后调用getData获取网络数据前,已经切换页面为加载状态
需要在getData实现类中切换回来
因为加载状态时 希望标题栏不被加载界面覆盖,这里的getRootId实现类传入主体内容容器id,不包含toolbar
activity管理类
/**
Desc: activity管理类
*/
public class ActivityCollector {
public static List activitys = new ArrayList<>();
public static void addActivity(Activity activity) {
activitys.add(activity);//把传入的Activity添加到List中
}
public static void removeActivity(Activity activity) {
activitys.remove(activity);//根据传入的Activity来删除
}
public static void removeAll() {
for (Activity activity : activitys) {
if (!activity.isFinishing()) {
activity.finish();
}
}
}
/**
除了传来的Activity其他的全部删除
可以传多个Activity
*/
public static void removeAll(Class>... clazz) {
boolean isExist = false;
for (Activity act : activitys) {
for (Class c : clazz) {
if (act.getClass().isAssignableFrom(c)) {
isExist = true;
break;
}
}
if (!isExist) {
if (!act.isFinishing()) {
act.finish();
}
} else {
isExist = false;
}
}
}
/**
从Activity集合查询, 传入的Activity是否存在
如果存在就返回该Activity,不存在就返回null
*/
public static Activity getActivity(Class> activity) {
for (int i = 0; i < activitys.size(); i++) {
// 判断是否是自身或者子类
if (activitys.get(i).getClass().isAssignableFrom(activity)) {
return activitys.get(i);
}
}
return null;
}
public static Activity getTopActivity() {
return activitys.get(activitys.size()-1);
}
}
Demo下载地址
http://download.csdn.net/detail/jiushiwo12340/9852351
参考内容
基于 Android在开发中的实用技巧之BaseActivity
基于DataBinding
基于 Activity加载网络数据切换状态工具