Android BaseActivity的设计(一)

Android开发中BaseActivity在程序设计对于项目的架构重要性不言而喻,一个好的BaseActivity设计可以让项目的Activity代码看起来更加简洁且易编写,同时BaseActivity也是MVC,MVP和MVVM架构体现。

BaseActivity使用场景
1 多个子类有公有的方法,并且逻辑基本相同时。
2 重要、复杂的算法,可以把核心算法设计为模板方法,周边的相关细节功能则由各个子类实现。
3 重构时,模板方法模式是一个经常使用的模式,把相同的代码抽取到父类中,然后通过钩子函数约束其行为。
①MVC的BaseActivity 没有加ButterKnife需要可以加上,EventBus也没加,需要的可以加上

public abstract class BaseActivity extends AppCompatActivity implements View.OnClickListener{
	//获取TAG的activity名称
    protected final String TAG = this.getClass().getSimpleName();
    //设置子activity布局
    FrameLayout frameLayout;
    //title 如果 return null 则隐藏
    RelativeLayout rlTitle;
    //返回按钮
    LinearLayout llBack;
    //title文字
    TextView tvTitleBase;
    //右侧按钮
    public Button btnRightBase;
    LinearLayout llRightBase;
    //获取上下文
    public Context mContext;
    //progressDialog 可以用自己自定义的Loading
    private ProgressDialog progressdialog;
    //是否有返回键
    public boolean isHaveBack = true;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mContext = this;
        //Activity管理
        ActivityUtil.getInstance().addActivity(this);
        //设置布局前处理一些逻辑
        init(savedInstanceState);
        //设置布局
        if (setLayoutResourceID() != 0) {
            setContentView(R.layout.activity_base);
            //ButterKnife.bind(this); 如果有需要可以在这里设置
            initBaseView();
        }
        //初始化控件 设置了ButterKnife 初始化控件就不需要了
        initView();
        //设置数据
        initData();
        //设置监听
        initListener();
    }

    /**
     * 设置布局前处理一些逻辑和设置
     *
     * @param savedInstanceState bundle
     */
    protected void init(Bundle savedInstanceState) {
    
    }

    /**
     * 基础View设置
     */
    private void initBaseView() {
        llBack = findViewById(R.id.ll_back_base);
        tvTitleBase = findViewById(R.id.tv_title_base);
        frameLayout = findViewById(R.id.fl_base_content);
        rlTitle = findViewById(R.id.rl_title_base);
        btnRightBase = findViewById(R.id.btn_right_base);
        llRightBase = findViewById(R.id.ll_right_base);
        if (StringUtil.isNotEmpty(initTitle())) {
            tvTitleBase.setText(initTitle());
        } else {
            rlTitle.setVisibility(View.GONE);
        }
        if (isHaveBack) {
            llBack.setVisibility(View.VISIBLE);
            llBack.setOnClickListener(view -> finish());
        } else {
            llBack.setVisibility(View.GONE);
        }
        btnRightBase.setOnClickListener(view -> rightBtnClickListener());
        View baseView = LayoutInflater.from(mContext).inflate(setLayoutResourceID(), frameLayout, false);
        frameLayout.addView(baseView);
    }

    /**
     * 设置布局
     * return 布局
     */
    @LayoutRes
    protected abstract int setLayoutResourceID();


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

    /**
     * 设置title
     *
     * @return title
     */
    protected abstract String initTitle();

    /**
     * 设置数据
     */
    protected void initData() {
    }

    /**
     * 设置监听
     */
    protected void initListener() {
    }

    @Override
    public void onClick(View view) {

    }

    /**
     * 设置右边Button样式
     *
     * @param resource
     */
    public void setRightBtnResource(int resource) {
        if (resource != 0) {
            llRightBase.setVisibility(View.VISIBLE);
            btnRightBase.setBackground(ContextCompat.getDrawable(mContext, resource));
        }
    }

    /**
     * 右边Button的点击事件
     */
    protected void rightBtnClickListener() {
    }

    /**
     * show shotToast
     *
     * @param msg 提示内容
     */
    public void showToast(String msg) {
        if (StringUtil.isEmpty(msg)) {
            return;
        }
        Toast.makeText(mContext, msg, Toast.LENGTH_SHORT).show();
    }

    /**
     * showProgress
     *
     * @param msg 提示内容
     */
    public void showProgress(String msg) {
        if (progressdialog == null) {
            progressdialog = new ProgressDialog(mContext);
        }
        progressdialog.setTitle("请等待...");
        progressdialog.setMessage(msg);
        progressdialog.show();
    }

    /**
     * dismissProgress
     */
    protected void dismissProgress() {
        if (progressdialog != null) {
            progressdialog.dismiss();
        }
    }

    /**
     * 普通跳转
     *
     * @param activity activity
     */
    protected void jumpToActivity(Class<?> activity) {
        startActivity(new Intent(mContext, activity));
    }

    /**
     * 保证同一按钮在1秒内只会响应一次点击事件
     */
    public abstract class OnSingleClickListener implements View.OnClickListener {
        //两次点击按钮之间的间隔,目前为1000ms
        private static final int MIN_CLICK_DELAY_TIME = 1000;
        private long lastClickTime;

        public abstract void onSingleClick(View view);

        @Override
        public void onClick(View view) {
            long curClickTime = System.currentTimeMillis();
            if ((curClickTime - lastClickTime) >= MIN_CLICK_DELAY_TIME) {
                lastClickTime = curClickTime;
                onSingleClick(view);
            }
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        ActivityUtil.getInstance().removeActivity(this);
    }
}

②BaseActivity布局(可以自定义,如果右上角有多个控件也可以自己添加)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <RelativeLayout
        android:id="@+id/rl_title_base"
        style="@style/Panel.Title">

        <LinearLayout
            android:id="@+id/ll_back_base"
            android:layout_width="48dp"
            android:layout_height="48dp"
            android:gravity="center_vertical"
            android:orientation="vertical">

            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:background="@drawable/account_ic_back"
                android:clickable="false"
                android:minWidth="0dp"
                android:minHeight="0dp" />

        </LinearLayout>

        <TextView
            android:id="@+id/tv_title_base"
            style="@style/TextView.Title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:singleLine="true" />

        <LinearLayout
            android:id="@+id/ll_right_base"
            android:layout_width="48dp"
            android:layout_height="48dp"
            android:layout_alignParentTop="true"
            android:layout_alignParentRight="true"
            android:background="@drawable/selector_topbar_button"
            android:gravity="center_vertical"
            android:orientation="vertical"
            android:visibility="gone">

            <Button
                android:id="@+id/btn_right_base"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:background="@drawable/scan_icon"
                android:clickable="false"
                android:minWidth="0dp"
                android:minHeight="0dp" />

        </LinearLayout>

    </RelativeLayout>

    <FrameLayout
        android:id="@+id/fl_base_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

③附上ActivityUtil(Activity管理类)

public class ActivityUtil{
    private static final String TAG = "ActivityUtil";
    /**
     * 单一实例
     */
    private static ActivityUtil sActivityUtil;
    /**
     * Activity堆栈 Stack:线程安全
     */
    public Stack<Activity> mActivityStack = new Stack<>();

    /**
     * 私有构造器 无法外部创建
     */
    private ActivityUtil() {
    }

    /**
     * 获取单一实例 双重锁定
     * @return this
     */
    public static ActivityUtil getInstance() {
        if (sActivityUtil == null) {
            synchronized (ActivityUtil.class) {
                if (sActivityUtil == null) {
                    sActivityUtil = new ActivityUtil();
                }
            }
        }
        return sActivityUtil;
    }

    /**
     * 添加Activity到堆栈
     */
    public void addActivity(Activity activity) {
        mActivityStack.add(activity);
    }

    /**
     * 移除堆栈中的Activity
     * @param activity Activity
     */
    public void removeActivity(Activity activity) {
        if (activity != null && mActivityStack.contains(activity)) {
            mActivityStack.remove(activity);
        }
    }

    /**
     * 获取当前Activity (堆栈中最后一个添加的)
     * @return Activity
     */
    public Activity getCurrentActivity() {
        return mActivityStack.lastElement();
    }

    /**
     * 获取指定类名的Activity
     */
    public Activity getActivity(Class<?> cls) {
        if (mActivityStack != null)
            for (Activity activity : mActivityStack) {
                if (activity.getClass().equals(cls)) {
                    return activity;
                }
            }
        return null;
    }

    /**
     * 结束当前Activity (堆栈中最后一个添加的)
     */
    public void finishCurrentActivity() {
        Activity activity = mActivityStack.lastElement();
        finishActivity(activity);
    }

    /**
     * 结束指定的Activity
     * @param activity Activity
     */
    public void finishActivity(Activity activity) {
        if (activity != null && mActivityStack.contains(activity)) {
            mActivityStack.remove(activity);
            activity.finish();
        }
    }

    /**
     * 结束指定类名的Activity
     * @param clazz Activity.class
     */
    public void finishActivity(Class<?> clazz) {
        for (Activity activity : mActivityStack) {
            if (activity.getClass().equals(clazz)) {
                finishActivity(activity);
                break;
            }
        }
    }

    /**
     * 结束所有Activity
     */
    public void finishAllActivity() {

        for (int i = mActivityStack.size() - 1; i >= 0; i--) {

            if (mActivityStack.get(i) != null) {
                finishActivity(mActivityStack.get(i));
            }
        }
        mActivityStack.clear();
    }

    /**
     * 结束某个Activity之外的所有Activity
     */
    public void finishAllActivityExcept(Class<?> clazz) {
        for (int i = mActivityStack.size() - 1; i >= 0; i--) {

            if (mActivityStack.get(i) != null && !mActivityStack.get(i).getClass().equals(clazz)) {
                finishActivity(mActivityStack.get(i));
            }
        }
    }

    /**
     * 退出应用程序
     */
    public void exitApp() {
        try {
            finishAllActivity();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.exit(0);
        }
    }

    /**
     * 判断某个Activity 界面是否在前台
     * @param context
     * @param className 某个界面名称
     * @return
     */
    public static boolean  isForeground(Context context, String className) {
        if (context == null || TextUtils.isEmpty(className)) {
            return false;
        }

        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningTaskInfo> list = am.getRunningTasks(1);
        if (list != null && list.size() > 0) {
            ComponentName cpn = list.get(0).topActivity;
            if (className.equals(cpn.getClassName())) {
                return true;
            }
        }
        return false;
    }
}

④基础用法 可以自己扩展方法

public class TestActivity extends BaseActivity {
    Button button;
    Button button2;

	//设置布局
    @Override
    protected int setLayoutResourceID() {
        return R.layout.activity_test;
    }

    //在设置布局之前做一些操作设置或者接收数据
    @Override
    protected void init(Bundle savedInstanceState) {
        super.init(savedInstanceState);
        //是否有返回按钮 默认有
        //isHaveBack=false;
    }

    //初始化控件 如果用了ButterKnife 初始化控件就不需要了
    @Override
    protected void initView() {
        button = findViewById(R.id.button_test);
        button2 = findViewById(R.id.button_test2);
    }

    //给控件设置数据
    @Override
    protected void initData() {
        super.initData();
        //做网络请求前
        showProgress("xxxx");
        //网络请求结束
        dismissProgress();
        //toast short
        showToast("xxx");
        //普通跳转
        //jumpToActivity(xxx.activity);
    }

    @Override
    protected void initListener() {
        super.initListener();
        //设置1s内单次点击事件
        button.setOnClickListener(new OnSingleClickListener() {
            @Override
            public void onSingleClick(View view) {

            }
        });
        //普通点击事件
        button2.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        super.onClick(view);
        switch (view.getId()) {
            case R.id.button_test2:

                break;
            default:
                break;
        }
    }

    //设置 title 如果没有title 可以 return null 就没有title了
    @Override
    protected String initTitle() {
        return "测试title";
    }
}

后续会推出基于MVP的BaseMVPActivity的封装,如果有自己需要的方法也可以自己抽出来放在BaseActivity中,本文主要是提供一个思路,具体实现根据个人需要。

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值