Android App框架设计之编写基类BaseActivity

Android App框架设计之编写基类BaseActivity

编写基类BaseActivity

- OOP里面子类里面能够共享父类的方法,提高代码的可复用性

- 基类的编写要根据实际项目的情况,有的可能很简单 比如只是显示 “关于” 信息, 业务功能非常少 你可以不用继承基类进行扩展

BaseActivity继承Activity 还是 FragmentActivity 还是其它? 也是根据你的技术要求,因为解决问题的方法有很多种,或者你根本不用写基类也能完成工作。

我们的目的是编写较好的代码,提高代码可复用性,可扩展性,尤其是团队协作非常重要,这就是OOP为什么出现的原因之一。

考虑基类都应写什么?通用的代码。

  • 网络环境监控
  • 统一的数据接口
  • 生命周期不同方法应该做的事情

刚工作的时候,看Spring源码 根本就不知道为什么搞那么多接口和对象,一层层的。 随着经验的积累才知道OOP的好处。

下面我们编写一个基础的基类,并不复杂。 假设我们的业务是公司的移动OA系统 我们需要管理员工。

抽象一个员工

//Domine为通用实体类,后面可作为泛型参数有用
public class Employee extends Domine {

    private static final long serialVersionUID = 1L;

    public Employee() {
    }

    public String fullName;
    public String mobileTel;
    public String email;
    public String empNo;
}

//可以添加公共属性
public class Domine implements Serializable {

    private static final long serialVersionUID = 1L;

    public Domine() {
    }

    public int id;
    public String desc;

}

数据交互的模型


public class MData<T> implements Serializable {

    private static final long serialVersionUID = 1L;

    public String id;
    public String type;
    public T dataList;//多种类型数据,一般是List集合,比如获取所有员工列表

}

下面是数据回调接口,我们从网络端获取数据 需要通知给UI


public interface IDataCallback<T> { //我们一样传入通用类型
    public void onNewData(T data);
    public void onError(String msg,int code);
}

下面是独立出来一个UIHandler,一般是写在Activity里面作为内部类,我这里没有

public class UIHandler extends Handler {

    private IHandler handler;//回调接口,消息传递给注册者

    public UIHandler(Looper looper) {
        super(looper);
    }

    public UIHandler(Looper looper,IHandler handler) {
        super(looper);
        this.handler = handler;
    }

    public void setHandler(IHandler handler) {
        this.handler = handler;
    }

    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        if (handler != null) {
            handler.handleMessage(msg);//有消息,就传递
        }
    }
}

public interface IHandler {
    public void handleMessage(Message msg);
}

我们有了基本的东西,现在组合到BaseActivity中

public abstract class BaseActivity extends Activity {

    // 可以把常量单独放到一个Class中
    public static final String ACTION_NETWORK_CHANGE = "android.net.conn.CONNECTIVITY_CHANGE";
    public static final String ACTION_PUSH_DATA = "fm.data.push.action";
    public static final String ACTION_NEW_VERSION = "apk.update.action";

    protected static UIHandler handler = new UIHandler(Looper.getMainLooper());

    // 数据回调接口,都传递Domine的子类实体
    protected IDataCallback<MData<? extends Domine>> dataCallback;

    public BaseActivity() {

    }

    //这个地方有点“模板方法“的设计模式样子
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setBase();
        setHandler();
        initContentView(savedInstanceState);
    }

    private void setHandler() {
        handler.setHandler(new IHandler() {
            public void handleMessage(Message msg) {
                handler(msg);//有消息就提交给子类实现的方法
            }
        });
    }

    // 初始化UI,setContentView等
    protected abstract void initContentView(Bundle savedInstanceState);

    // 可能全屏或者没有ActionBar等
    private void setBase() {
        requestWindowFeature(Window.FEATURE_NO_TITLE);// 例
    }

    protected void addLeftMenu(boolean enable) {
        // 如果你的项目有侧滑栏可以处理此方法
        if (enable) { // 是否能有侧滑栏

        } else {

        }
    }
    //让子类处理消息
    protected abstract void handler(Message msg);

    // 横竖屏切换,键盘等
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        try {
            super.onRestoreInstanceState(savedInstanceState);
        } catch (Exception e) {
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        // 你可以添加多个Action捕获
        IntentFilter filter = new IntentFilter();
        filter.addAction(ACTION_NETWORK_CHANGE);
        filter.addAction(ACTION_PUSH_DATA);
        filter.addAction(ACTION_NEW_VERSION);
        registerReceiver(receiver, filter);
        //还可能发送统计数据,比如第三方的SDK 做统计需求
    }

    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(receiver);
        //还可能发送统计数据,比如第三方的SDK 做统计需求
    }

    BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            // 处理各种情况
            String action = intent.getAction();
            if (ACTION_NETWORK_CHANGE.equals(action)) { // 网络发生变化
                // 处理网络问题
            } else if (ACTION_PUSH_DATA.equals(action)) { // 可能有新数据
                Bundle b = intent.getExtras();
                MData<Employee> mdata = (MData<Employee>) b.get("data");
                if (dataCallback != null) { // 数据通知
                    dataCallback.onNewData(mdata);
                }
            } else if (ACTION_NEW_VERSION.equals(action)) { // 可能发现新版本
                // VersionDialog 可能是版本提示是否需要下载的对话框
            }
        }
    };

    public void setDataCallback(
            IDataCallback<MData<? extends Domine>> dataCallback) {
        this.dataCallback = dataCallback;
    }
}

有了基类现在编写一个子类Activity


public class EmployeeDisplayActivity extends BaseActivity implements IDataCallback<MData<? extends Domine>> { //实现数据回调接口

    public EmployeeDisplayActivity() {
    }

    @Override
    protected void initContentView(Bundle savedInstanceState) {
        setContentView(R.layout.activity_main);
        loadData();
    }

    private void loadData() {
        setDataCallback(this);//设置回调函数
        //我们还可以把这个Callback传给其它获取数据的类,比如HTTP获取数据
        //比如 HttClient.get(url,this);
    }

    @Override
    public void onNewData(MData<? extends Domine> data) {
        //update UI 更新UI数据
        final List<Employee> list = (List<Employee>) data.dataList;
        handler.post(new Runnable() {
            public void run() {
                //更新UI
            }
        });
        //或者
        handler.sendEmptyMessage(0);//通知Handler
    }

    @Override
    public void onError(final String msg, final int code) {
        handler.post(new Runnable() {
            public void run() {
                //通知错误消息
            }
        });
        //或者
        handler.sendEmptyMessage(0);//通知Handler
    }

    @Override
    protected void handler(Message msg) { //我们可以处理数据消息了
        switch (msg.what) {
        case 0:
            break;
        case -1:
            break;
        default:
            break;
        }
    }

}

UML关系图

本文编写了基本的BaseActivity代码,显然不可能是完美的,需要不断学习和改进,有问题欢迎探讨,Thanks.

时间: 2024-10-13 16:52:23

Android App框架设计之编写基类BaseActivity的相关文章

Android通用框架设计与完整电商APP开发

第1章 课程介绍及APP效果展示(Java版)本章概述了本课程大家能学到什么,老师如何讲解,为什么这么讲解,并介绍了框架的整体架构设计与模块分解,最后展示了用自己设计的框架开发出来的完整电商APP的效果图(服务端API快速搭建教程:http://www.imooc.com/article/19001) ...1-1 课程导学1-2 项目架构设计与模块分解 第2章 项目初始化本章将从零搭建一个空项目,实践项目搭建的过程,并额外教大家搭建一个基于Go语言的Web版Git服务器,实现代码托管的自举.(

Android App的设计架构:MVC,MVP,MVVM与架构经验谈

来源: Android App的设计架构:MVC,MVP,MVVM与架构经验谈 和MVC框架模式一样,Model模型处理数据代码不变在Android的App开发中,很多人经常会头疼于App的架构如何设计: 我的App需要应用这些设计架构吗? MVC,MVP等架构讲的是什么?区别是什么? 本文就来带你分析一下这几个架构的特性,优缺点,以及App架构设计中应该注意的问题. 1.架构设计的目的 通过设计使程序模块化,做到模块内部的高聚合和模块之间的低耦合.这样做的好处是使得程序在开发的过程中,开发人员

[转]Android程序框架设计

这篇文章主要内容来自于之前我讲的一个PPT文档,现在将其整理如下.欢迎指正.以下的内容都是来自于我自身的经验,欢迎大家多提自己的建议. 1.一些概念 模式的定义: 每个模式都描述了一个在我们的环境中不断出现的问题,然后描述了该问题的解决方案的核心.通过这种方式,你可以无数次地使用那些已有的解决方案,无需在重复相同的工作. 什么是设计模式? 设计模式是在某种特别的情况下,针对某种问题的某种典型.通用的解决方法. 我们是需要适当了解并学习一些设计模式,在程序开发过程中,总是会涉及到一些框架设计,模块

android app 架构设计02

二:在开放的过程中,尽量把工具类,BaseActivity 放在指定的位置, DateFormat Bitmap Notification Shared Preference Environment Device 三: 2.2 Task管理 线程只是一种机制,保证我们要完成的任务不运行在UI线程(也就是说不阻塞UI),完成的任务才是我们关注的核心,因此,我们可以通过设计,把线程封装,让使用者根本感觉不到是线程,他只用关心他要做的事情就行了. 这里,我们可以设计一种"异步链式调用"的框架

Android 程序框架设计

1.一些概念 模式的定义: 每个模式都描述了一个在我们的环境中不断出现的问题,然后描述了该问题的解决方案的核心.通过这种方式,你可以无数次地使用那些已有的解决方案,无需在重复相同的工作. 什么是设计模式? 设计模式是在某种特别的情况下,针对某种问题的某种典型.通用的解决方法. 我们是需要适当了解并学习一些设计模式,在程序开发过程中,总是会涉及到一些框架设计,模块设计之类的东西,如果能很好理解并运行设计模式,你所设计的模块或框架将会要稳定得多,因为这些设计模式它们都是通用的解决方案,是经过实践经验

教你写Android网络框架之Request、Response类与请求队列

转载请注明出处,本文来自[ Mr.Simple的博客 ]. 我正在参加博客之星,点击这里投我一票吧,谢谢~ 前言 在教你写Android网络框架之基本架构一文中我们已经介绍了SimpleNet网络框架的基本结构,今天我们就开始从代码的角度来开始切入该网络框架的实现,在剖析的同时我们会分析设计思路,以及为什么要这样做,这样做的好处是什么.这样我们不仅学到了如何实现网络框架,也会学到设计一个通用的框架应该有哪些考虑,这就扩展到框架设计的范畴,通过这个简单的实例希望能给新人一些帮助.当然这只是一家之言

第二章App框架设计与重构

response标准格式: { "isError":false, "errorType": 0, "errorMessage": "网络异常", "result": "" } { "errorMessage" : "网络异常", "errorType" : 0, "isError" : false, &quo

构建自己的PHP框架--抽象Controller的基类

上一篇博客中,我们将简单的路由解析和执行,从入口文件public/index.php中移入到框架中.入口文件顿时变得清爽无比-- 但是,去我们的controller里看一下,会看到如下的code: public function actionView() { $body = 'Test body information'; require '../views/site/view.php'; } 难道我们每写一个要去渲染页面的action,都要去找相应路径的view,然后把它require进来.肯

C# Winform下一个热插拔的MIS/MRP/ERP框架15(窗体基类场景1)

最基础的窗体基类其实是通过应用场景反推的结构. 以下是场景一: 单表应用,普通的数据,比如单位/颜色/特殊字典等使用者少的,无需过多控制的可以使用一个数据表格来管理. 和Excel表格差不多,批量修改,统一保存. 这种设计时只需要变更Datagridview的数据列,并在代码中指定数据来源即可.看下代码: #region 数据目标定义 SaveTableName = "SYS_URightDef"; SaveTablePrimaryKey = "URDefRKEYIN&quo