You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中抽象类的具体用途是什么?基于代码复用场景的疑问

Android中抽象类的具体用途及示例

嘿,我懂你已经知道抽象类能当基类实现代码复用,但在Android开发里,它还有不少贴合实际场景的用法,能帮我们减少重复代码、统一组件规范,让开发效率提升不少。下面我结合具体场景给你拆解,再补上实用的示例代码:

1. 统一组件模板,强制子类实现核心逻辑

在自定义View、自定义控件这类场景中,抽象类可以定义一套通用的流程框架,同时强制子类实现核心业务逻辑,保证所有同类型组件遵循统一规范,避免重复编写通用代码。

比如自定义View的基类封装:

// 抽象基类:封装自定义View的通用初始化、触摸事件等逻辑
public abstract class BaseCustomView extends View {
    public BaseCustomView(Context context) {
        super(context);
        initCommon();
    }

    // 所有自定义View都需要的通用初始化逻辑
    private void initCommon() {
        setBackgroundColor(Color.LTGRAY);
        setupTouchHandling();
    }

    // 子类必须实现的核心绘制逻辑——强制子类完成自己的绘制需求
    protected abstract void onCustomDraw(Canvas canvas);

    // 通用触摸事件处理,子类可按需重写点击回调
    private void setupTouchHandling() {
        setOnTouchListener((v, event) -> {
            if (event.getAction() == MotionEvent.ACTION_UP) {
                onViewClicked();
                return true;
            }
            return false;
        });
    }

    // 可选重写的点击回调,默认空实现
    protected void onViewClicked() {}

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 调用子类的自定义绘制逻辑
        onCustomDraw(canvas);
    }
}

// 子类只需专注核心绘制,通用逻辑直接继承
public class CircleView extends BaseCustomView {
    private Paint circlePaint;

    public CircleView(Context context) {
        super(context);
        circlePaint = new Paint();
        circlePaint.setColor(Color.RED);
        circlePaint.setAntiAlias(true);
    }

    @Override
    protected void onCustomDraw(Canvas canvas) {
        int centerX = getWidth() / 2;
        int centerY = getHeight() / 2;
        canvas.drawCircle(centerX, centerY, Math.min(centerX, centerY) - 10, circlePaint);
    }

    @Override
    protected void onViewClicked() {
        Toast.makeText(getContext(), "圆形控件被点击啦!", Toast.LENGTH_SHORT).show();
    }
}

2. MVP/MVVM架构中的基类封装

在架构设计中,抽象类可以封装Presenter/ViewModel的通用逻辑,比如View绑定解绑、加载状态控制、错误处理等,让子类只需要专注业务逻辑实现。

以MVP的Presenter基类为例:

// 抽象Presenter基类:封装通用的View生命周期绑定和状态控制
public abstract class BasePresenter<V> {
    protected V mView;

    // 绑定View,建立关联
    public void attachView(V view) {
        this.mView = view;
    }

    // 解绑View,防止内存泄漏
    public void detachView() {
        this.mView = null;
    }

    // 子类必须实现的业务数据加载逻辑
    protected abstract void loadBusinessData();

    // 通用显示加载状态
    protected void showLoading() {
        if (mView != null && mView instanceof BaseView) {
            ((BaseView) mView).showLoadingDialog();
        }
    }

    // 通用隐藏加载状态
    protected void hideLoading() {
        if (mView != null && mView instanceof BaseView) {
            ((BaseView) mView).hideLoadingDialog();
        }
    }
}

// 业务Presenter子类:只需要处理具体业务
public class UserPresenter extends BasePresenter<UserView> {
    @Override
    protected void loadBusinessData() {
        showLoading();
        // 模拟网络请求获取用户数据
        new Handler().postDelayed(() -> {
            if (mView != null) {
                mView.showUserInfo("张三", "18岁");
                hideLoading();
            }
        }, 2000);
    }
}

// 抽象View接口:定义通用视图行为
public interface BaseView {
    void showLoadingDialog();
    void hideLoadingDialog();
}

// 业务View接口:扩展通用接口,定义业务专属行为
public interface UserView extends BaseView {
    void showUserInfo(String name, String age);
}

3. 封装Activity/Fragment的通用逻辑

Android中几乎每个Activity都需要处理Toolbar设置、返回键、权限请求等通用操作,抽象基类可以把这些逻辑统一封装,让业务Activity只专注自身业务。

比如抽象基类Activity:

// 抽象基类Activity:封装通用初始化流程
public abstract class BaseActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(getLayoutResId());
        initToolbar();
        initViews();
        initData();
    }

    // 子类必须提供布局ID
    protected abstract int getLayoutResId();

    // 通用Toolbar初始化
    private void initToolbar() {
        Toolbar toolbar = findViewById(R.id.toolbar);
        if (toolbar != null) {
            setSupportActionBar(toolbar);
            Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
            toolbar.setNavigationOnClickListener(v -> onBackPressed());
        }
    }

    // 子类初始化自身视图控件
    protected abstract void initViews();

    // 子类初始化业务数据
    protected abstract void initData();

    // 通用权限请求方法
    protected void requestAppPermissions(String[] permissions, int requestCode) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            requestPermissions(permissions, requestCode);
        }
    }
}

// 业务Activity子类:只需实现自身业务相关逻辑
public class UserDetailActivity extends BaseActivity {
    @Override
    protected int getLayoutResId() {
        return R.layout.activity_user_detail;
    }

    @Override
    protected void initViews() {
        // 初始化用户详情页的UI控件
        TextView tvUserName = findViewById(R.id.tv_user_name);
        // ...其他控件初始化
    }

    @Override
    protected void initData() {
        // 加载用户详情数据
        // ...
    }
}

基础代码复用(对应你给出的示例)

你提供的示例就是抽象类最基础的代码复用场景——把多个类都会用到的方法封装在基类中,子类直接继承调用,避免重复编写相同代码。

调整后的规范示例:

public class Base {
    public void test() {
        System.out.println("test");
    }
}

public class Main extends Base {
    public void doBusiness() {
        // 直接复用Base类的test方法
        test();
    }
}

在Android中,这种场景也很常见,比如多个工具类继承同一个基类,或者多个自定义View复用基类的通用工具方法。


内容的提问来源于stack exchange,提问作者Dineshkumar Arunachalam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:20:56