最详细的结构目录搭建(MVC模式)
一. 刚建好的项目结构
![](https://i-blog.csdnimg.cn/blog_migrate/5607231672ac78136e1f71c348343152.png)
![](https://i-blog.csdnimg.cn/blog_migrate/93c925d78f715ab1b4a9888f5da64ad4.png)
- activity用来放置activity界面
- adapter用来放适配器,无论是recyclview还是viewpager,几乎都会用到
- base用来放置我们的基类
- config放置常量
- fragment里放fragment界面
- model用来放数据模型
- utils里放的是工具类
- view文件夹放的是我们的自定义view
分类明确后,再要找到指定类就简单方便多了,当然还可以根据项目需求新增其他的文件夹,可以根据项目的模块再在每个分类下再分类,没有谁规定死一定要怎么样构建你的项目,怎么做方便就怎么样来。
二.关于基类
基类,顾名思义就是基础类。就像盖房子需要打地基,地基打得稳了,房子才稳。
基类在面向对象设计中被定义为包含所有实体共性的class类。基类可以简化我们的代码,减少我们代码冗余,让我们的代码变得更简单易懂。
下面简单写出用于activity和fragment的基类,我会写上详细的注释。
/**
* 作者:Created by qujifan on 2018/10/17.
* 邮箱:joker_qjf@foxmail.com
* 描述: 公共接口
*
*/
public interface IBase {
/**
* 显示进度条
* @param flag 是否可取消
* @param message 要显示的信息
*/
void showProgress(boolean flag, String message);
/** 隐藏进度条 */
void hideProgress();
/**
* 根据资源文件id弹出toast
* @param resId 资源文件id
*/
void showToast(int resId);
/**
* 根据字符串弹出toast
* @param msg 提示内容
*/
void showToast(String msg);
/**
* 显示自定义的加载框
* @param msg 提示内容
* @param cancelable 是否可取消
*/
void showLoadingDialog(String msg, boolean cancelable);
/**
* 自定义样式的right弹框
* @param msg 提示内容
* @param delay 显示的时长
*/
void showRightDialog(String msg, int delay);
/**
* 自定义样式的error弹框
* @param msg 提示内容
* @param delay 显示的时长
*/
void showErrorDialog(String msg, int delay);
/** 隐藏自定义的弹框 */
void dissDialog();
}
/**
* 作者:Created by qujifan on 2018/10/17.
* 邮箱:joker_qjf@foxmail.com
* 描述: activity的基类,不限制继承FragmentActivity,写的时候可以根
* 据项目需求更改,最终的父类都是Activity
*/
public abstract class BaseActivity extends FragmentActivity implements IBase, DialogInterface.OnDismissListener {
//根据所在界面输出log日志
public String TAG = this.getClass().getSimpleName();
//提示弹出框
private Dialog mDialog;
private Handler disHandler;
private Runnable disRunnable;
private TextView tvToastText;
private Toast mToast;
private MMKV mkv;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
disHandler = new Handler();
disRunnable = () ->{
mDialog.dismiss();
};
initContentView();
initView();
initController();
initListener();
}
/**
* 初始化布局
*/
public abstract void initContentView();
/**
* 初始化控件
*/
public abstract void initView();
/**
* 初始化控制中心
*/
public abstract void initController();
/**
* 初始化监听事件
*/
public abstract void initListener();
@Override
public void showProgress(boolean flag, String message) {
}
@Override
public void hideProgress() {
}
/**
* 获取mmkv实例
* @return
*/
public MMKV getMmkv(){
if(mkv!=null){
return mkv;
}
return mkv = MMKV.defaultMMKV();
}
/**
* 初始化toast
* @param msg
*/
private void initToast(String msg){
View view = getLayoutInflater().inflate(R.layout.layout_toast, null);
tvToastText = view.findViewById(R.id.tv_toast_text);
mToast = new Toast(this);
mToast.setGravity(Gravity.CENTER,0,0);
mToast.setDuration(Toast.LENGTH_SHORT);
mToast.setView(view);
tvToastText.setText(msg);
mToast.show();
}
@Override
public void showToast(int resId) {
showToast(getString(resId));
}
@Override
public void showToast(String msg) {
if(mToast!=null){
tvToastText.setText(msg);
mToast.show();
}else{
initToast(msg);
}
}
@Override
public void showLoadingDialog(String msg, boolean cancelable) {
if (mDialog != null && mDialog.isShowing()) {
mDialog.dismiss();
}
LayoutInflater inflater = LayoutInflater.from(this);
View v = inflater.inflate(R.layout.layout_dialog_loding, null);
TextView tvText = v.findViewById(R.id.tv_text);
tvText.setText(msg);
mDialog = new Dialog(BaseActivity.this, R.style.dialog);
mDialog.setCancelable(cancelable);
mDialog.setContentView(v, new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
mDialog.setOnDismissListener(this);
mDialog.show();
}
@Override
public void showRightDialog(String msg, int delay) {
if (mDialog != null && mDialog.isShowing()) {
mDialog.dismiss();
}
LayoutInflater inflater = LayoutInflater.from(this);
View v = inflater.inflate(R.layout.layout_dialog_right, null);
ImageView image = v.findViewById(R.id.iv_img);
TextView tvText = v.findViewById(R.id.tv_text);
image.setImageResource(R.drawable.icon_complete);
tvText.setText(msg);
mDialog = new Dialog(BaseActivity.this, R.style.dialog);
mDialog.setCancelable(true);
mDialog.setContentView(v, new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
mDialog.setOnDismissListener(this);
mDialog.show();
//delay时间后关闭弹框
disHandler.postDelayed(disRunnable,delay);
}
@Override
public void showErrorDialog(String msg, int delay) {
if (mDialog != null && mDialog.isShowing()) {
mDialog.dismiss();
}
LayoutInflater inflater = LayoutInflater.from(this);
View v = inflater.inflate(R.layout.layout_dialog_right, null);
ImageView image = v.findViewById(R.id.iv_img);
TextView tvText = v.findViewById(R.id.tv_text);
image.setImageResource(R.drawable.icon_error);
tvText.setText(msg);
mDialog = new Dialog(BaseActivity.this, R.style.dialog);
mDialog.setCancelable(true);
mDialog.setContentView(v, new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
mDialog.setOnDismissListener(this);
mDialog.show();
disHandler.postDelayed(disRunnable,delay);
}
@Override
public void dissDialog() {
if (mDialog != null && mDialog.isShowing()) {
mDialog.dismiss();
}
}
/**
* mDialog 的Dismiss事件监听
* @param dialog
*/
@Override
public void onDismiss(DialogInterface dialog) {
}
/**
* 统一处理back操作,因为每个界面都会需要返回操作
* @param v
*/
public void back(View v) {
onBackPressed();
}
/**
* 打开一个新的activity
*
* @param pClass 目标activity
*/
protected void openActivity(Class<?> pClass) {
openActivity(pClass, null);
}
/**
* 打开一个新的activity并传递数据
*
* @param pClass 目标activity
* @param pBundle Bundle类型参数传递
*/
protected void openActivity(Class<?> pClass, Bundle pBundle) {
Intent intent = new Intent(this, pClass);
if (pBundle != null) {
intent.putExtras(pBundle);
}
startActivity(intent);
}
}
/**
* 作者:Created by qujifan on 2018/10/17.
* 邮箱:joker_qjf@foxmail.com
* 描述: fragment的基类
*/
public abstract class BaseFragment extends Fragment {
public FragmentActivity mActivity;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
/**
* 返回一个需要展示的View
*
* @param inflater
* @param container
* @param savedInstanceState
* @return
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mActivity = (FragmentActivity) getActivity();
View view = initView(inflater);
initFindViewById(view);
return view;
}
/*
* 当Activity初始化之后可以在这里进行一些数据的初始化操作
*/
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initData();
initEvent();
}
/**
* 子类实现此抽象方法返回View进行展示
*
* @return
*/
public abstract View initView(LayoutInflater inflater);
/**
* 初始化控件
*/
protected abstract void initFindViewById(View view);
/**
* 子类在此方法中实现数据的初始化
*/
public abstract void initData();
/**
* 子类可以复写此方法初始化事件
*/
protected void initEvent() {
}
}
然后我们的activity就可以写成这样:
![](https://i-blog.csdnimg.cn/blog_migrate/ea5190c728763d7f12bbf480bfe8556d.png)
fragment就成了这样:
![](https://i-blog.csdnimg.cn/blog_migrate/6feec1979fc8387f8b5aa47cfdda345a.png)
三.end
不难看出来,子类的“共性”被放在了基类里面,我们activity及fragment中所写的代码就少了很多,看上去也更加的简洁明了。我只是简单介绍了基类的使用,他还有很多种写法,可以更方便性能更好,我们也可以把它用在adapter、view等等的class类上。