开发框架搭建——常用基类的封装

本文介绍了APP开发中框架搭建的过程,包括包结构的搭建和常用基类的封装,如BaseApplication、BaseActivity和BaseFragment。通过封装,便于管理和复用代码,提高开发效率。文中还提到了异常处理和用户登录状态的判断,以及如何使用这些基类在实际项目中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们想要开发一款APP,首要工作肯定是先把包结构建好,框架搭建起来,然后把基类封装,需要用到的第三方库导入项目等等一系列工作。今天我们就来说下如何完成这一套流程。
(注:每个人都有自己的代码风格,所以不存在哪种好,哪种不好,适合自己就可以了。)

通过本篇文章你可以Get到以下技能点:

1、新建项目的包结构如何搭建;
2、新建项目的常用基类的封装。

正文

包结构的搭建

提到分包大家肯定都有自己的方式,最常见的就是把activity放到一起、把fragment放到一起等等的。当然我也是这样分包的(嘿嘿)。下面就是我的分包图:
分包结构图

这里我是用了MVP模式,所以分包里面有一个mvp,如果看管老爷们不需要mvp就是简单点,那就把mvp换成去掉,把model、activity、fragment放到外面就可以了。

这里constants是放常量类,widget放的是自定义view的东西。别的包里面看包名就可以看出来里面要放什么东西,所以这里也不用过多解释了。各位看管老爷们看一下就行了。

常用基类的封装

下面才是本文的重点,常用基类的封装。我们按照顺序来,先从Application开始,废话不多说先上代码:

/**
 * @author: X_Meteor
 * @description: 自定义的BaseApplication
 * @version: V_1.0.0
 * @date: 2017/4/21 16:34
 * @email: lx802315@163.com
 */
public class BaseApplication extends Application {

    /**
     * 维护一个全局的context对象
     */
    public Context context;

    /**
     * 用于存放当前用户(如果有的话) 
     */
//    private static UserInfo currentUser;

    //单例模式
    private static BaseApplication myApplication = null;

    public static BaseApplication getInstance() {
        return myApplication;
    }

    /**
     * 获取当前的用户对象
     *
     * @param currentUser    
     */
//    public UserInfo getCurrentUser() {
//        UserInfo user = currentUser;
//        if (user != null) {
//            return user;
//        }
//        return null;
//    }

    /**
     * 设置当前的用户对象
     *
     */
//    public void setCurrentUser(UserInfo currentUser) {
//        this.currentUser = currentUser;
//    }

    /**
     * 定义一个标记
     */
    private static String TAG;

    @Override
    public void onCreate() {
        super.onCreate();
        //把TAG定义为当前类的类名
        TAG = this.getClass().getSimpleName();
        //由于Application类本身已经单例,所以直接按以下处理即可。
        myApplication = this;
        context = getApplicationContext();

        //全局异常处理
        if(Constants.isCollectException){
            CrashHandlerUtils crashHandler = CrashHandlerUtils.getInstance();
            crashHandler.init(getApplicationContext());
        }
    }
}

可以看到,在BaseApplication中,我们主要做了三件事:

  1. 获取当前系统使用用户(有用户模块的话)
  2. 定义了一个用于打印log的TAG,以当前类的类名为值
  3. 定义了一个全局错误异常类,在程序出现异常的时候可以捕获异常。(异常处理类后面会贴出)

下面再来BaseActivity:

/**
 * @author: Meteor
 * @description: 所有Activity的基类
 * @version: V 1.0
 * @date: 2016/12/28 0028 15:33
 * @company:
 * @email: lx802315@163.com
 */
public abstract class BaseActivity extends AppCompatActivity {

    //声明一个构建着对象,用于创建警告对话框
    private AlertDialog.Builder builder;
    //用于创建一个进度条对话框
    private ProgressDialog dialog;
    //用于打印log
    private final String TAG = "BaseActivity";
    //声明一个活动管理栈
    private static Stack<Activity> activities = new Stack<>();

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //添加活动到活动栈中
        activities.add(this);

        //固定屏幕方向
        this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        //设置在activity启动的时候输入法默认不开启
        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

        initRootView();
        ButterKnife.bind(this);

        initView();
        initData();
        initListener();

        //打印当前类名
        String msg = this.getClass().getName();
        LogUtils.print(msg);
    }

    /**
     * 初始化根布局文件
     */
    public abstract void initRootView();

    /**
     * 初始化控件
     */
    public abstract void initView();

    /**
     * 初始化数据
     */
    public abstract void initData();

    /**
     * 初始化接口
     */
    public abstract void initListener();

    /**
     * 实现沉浸式通知栏,使通知栏和APP的标题颜色一样
     */
    protected void immersiveNotification() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            //导航栏透明
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            //底部虚拟按钮透明
//            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
        }
    }

    /**
     * 显示一个警告对话框,无按钮,需要自己设置
     *
     * @param title 标题
     * @param msg   内容
     * @param flag  是否可以取消
     * @return
     */
    protected AlertDialog.Builder showAlertDialog(String title, String msg, boolean flag) {
        if (builder == null) {
            //创建一个构建者对象
            builder = new AlertDialog.Builder(this);
            builder.setTitle(title).setMessage(msg).setCancelable(flag);
        }
        return builder;
    }

    /**
     * 功能:取消警告对话框
     */
    protected void dismissAlertDialog(android.app.AlertDialog alertDialog) {
        if (alertDialog != null) {
            //取消警告对话框
            alertDialog.dismiss();
        }
    }

    /**
     * 功能 :显示一个进度条对话框
     */
    protected void showProcessDialog(String title, String msg, boolean falg) {
        if (dialog == null) {
            dialog = new ProgressDialog(this);
        }
        dialog.setTitle(title);
        dialog.setMessage(msg);
        dialog.setCancelable(falg);
        dialog.show();
    }

    /**
     * 功能 :取消一个进度条对话框
     */
    protected void dismissProcessDialog() {
        if (dialog != null) {
            dialog.dismiss();
        }
    }

    /**
     * 判断用户是否登陆过
     *
     * @return true 为登陆成功 false 为没有登陆过
     */
    protected boolean isLogin() {
    //这里面做你自己的逻辑处理
        return true;
    }

    /**
     * 退出所有活动并且退出当前应用
     */
    public static void exitApplication() {
        for (Activity activity : activities) {
            if (activity != null) {
                activity.finish();
            }
        }
        System.exit(0);
        android.os.Process.killProcess(android.os.Process.myPid());
    }
}

可以看到,在BaseActivity中我们做了很多处理:

  1. 定义了一个AlertDialog,警告对话框
  2. 定义了一个ProgressDialog,进度对话框
  3. 实现了一个判断用户是否登录的方法
  4. 维护了一个活动栈,并且开放了一个退出所有活动的方法
  5. 定义了抽象四个方法:initRootVeiw();initView;initData();initListener。
    (注:这里的initRootView是为了使用butterknife专门定义的,我们需要在集成的子类中把setContentView放入其中)

具体可以看代码:BaseActivity的onCreate()

@Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //添加活动到活动栈中
        activities.add(this);

        //固定屏幕方向
        this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        //设置在activity启动的时候输入法默认不开启
        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

        initRootView();
        //加入ButterKnife注解框架
        ButterKnife.bind(this);

        initView();
        initData();
        initListener();

        //打印当前类名
        String msg = this.getClass().getName();
        LogUtils.print(msg);
    }

继承的子类,MainActivity:

public class MainActivity extends BaseActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public void initRootView() {
        setContentView(R.layout.activity_main);
    }

    @Override
    public void initView() {

    }

    @Override
    public void initData() {

    }

    @Override
    public void initListener() {

    }
}

下面再来BaseFragment:

/**
 * @author: Meteor
 * @description: 所有Fragment的基类
 * @version:
 * @date: 2016/12/28 0028 16:16
 * @company:
 * @email: lx802315@163.com
 */
public abstract class BaseFragment extends Fragment {

    //定义一个用于重复View的回收池
    private View contentView = null;

    /**
     * Fragment当前状态是否可见
     */
    protected boolean isVisible;
    private AlertDialog.Builder builder;
    private AlertDialog alertDialog;
    private ProgressDialog dialog;
    //用于Butterknife 的绑定
    Unbinder unbinder;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        if (contentView == null) {//判断回收池是否为空
            contentView = initLayout(inflater, container, false);
            unbinder = ButterKnife.bind(this, contentView);
        }
        if (contentView != null) {
            unbinder = ButterKnife.bind(this, contentView);
            return contentView;
        }
        return super.onCreateView(inflater, container, savedInstanceState);
    }

    /**
     * 初始化Fragment的布局,当要创建试图时候调用
     *
     * @param inflater 布局填充器
     * @param container ViewGroup
     * @param b     标记
     * @return view 返回视图
     */
    protected abstract View initLayout(LayoutInflater inflater, ViewGroup container, boolean b);

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        //初始化数据
        initData(savedInstanceState);
    }

    /**
     * 初始化数据,当ViewCreate被创建时调用此方法
     * @param savedInstanceState
     */
    protected abstract void initData(Bundle savedInstanceState);

    @Override
    public final void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);

        if (getUserVisibleHint()) {
            isVisible = true;
            onVisible();
        } else {
            isVisible = false;
            onInvisible();
        }
    }

    /**
     * 可见
     */
    protected void onVisible() {
        lazyLoad();
    }

    /**
     * 不可见
     */
    protected void onInvisible() {

    }

    /**
     * 延迟加载
     * 子类必须重写此方法
     */
    protected abstract void lazyLoad();

    @Override
    public final void onDestroyView() {
        //移除当前视图,防止重复加载相同视图使得程序闪退
        ((ViewGroup) contentView.getParent()).removeView(contentView);
        super.onDestroyView();
        unbinder.unbind();
    }

    /**
     * 判断用户是否登陆过
     *
     * @return true 为登陆成功 false 为没有登陆过
     */
    protected boolean isLogin() {
        return false;
    }

    /**
     *  功能 :显示一个警告对话框
     */
    protected void showAlertDialog(String title,String text){
        if (builder==null){
            //创建一个构建者对象
            builder = new AlertDialog.Builder(getContext());
            builder.setTitle(title).setMessage(text).setCancelable(false);
            builder.setPositiveButton("设置", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    //跳转到系统网络设置
                    Intent intent = new Intent(Settings.ACTION_WIRELESS_SETTINGS);
                    startActivity(intent);
                }
            }).setNegativeButton("取消", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    //退出虚拟机
                    System.exit(0);
                }
            });
        }
        alertDialog = builder.show();
    }

    /**
     * 功能:取消警告对话框
     */
    protected void dismissAlertDialog(){
        if (alertDialog!=null){
            //取消警告对话框
            alertDialog.dismiss();
        }
    }
    /**
     * 功能 :显示一个进度条对话框
     */
    protected void showProcessDialog(String title,String msg,boolean falg){
        if(dialog==null){
            dialog = new ProgressDialog(getContext());
        }
        dialog.setTitle(title);
        dialog.setMessage(msg);
        dialog.setCancelable(falg);
        dialog.show();
    }

    /**
     * 功能 :取消一个进度条对话框
     */
    protected void dismissProcessDialog(){
        if(dialog!=null){
            dialog.dismiss();
        }
    }

    public interface BackHandledInterface {
        public abstract void setSelectedFragment(BaseFragment selectedFragment);
    }
}

这里除了跟BaseActivity 的相似的显示对话框外,主要多个懒加载方法,关于懒加载的知识,看官老爷们可以自行百度这里不过多解释。

子类继承使用如下:

/**
 * @author: X_Meteor
 * @description: 类描述
 * @version: V_1.0.0
 * @date: 2017/4/22 16:37
 * @email: lx802315@163.com
 */
public class homeFragment extends BaseFragment {
    @Override
    protected View initLayout(LayoutInflater inflater, ViewGroup container, boolean b) {
        View rootView = inflater.inflate(R.layout.activity_main, null);
        return rootView;
    }

    @Override
    protected void initData(Bundle savedInstanceState) {

    }

    @Override
    protected void lazyLoad() {

    }
}

到这里最常用的基类就封装完毕了,当然还是那句话,没有最好的只有最合适的自己的。项目已经上传 地址如下:
Demo

今天的内容就到此结束了,后面我会写一下rxjava2 + retrofit2 的网络请求框架的简单封装。欢迎大家共同探讨学习。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值