如何将Android数据库操作通用化(二)

来源:互联网 发布:麦田的守望者 知乎 编辑:程序博客网 时间:2024/05/19 13:06

      • 概述
      • 去年一滴相思泪今年刚流到腮边
      • 问君能有几多愁恰似一江春水向东流
      • 衣带渐宽终不悔为伊消得人憔悴

概述

接着上回的说,虽然我们已经找出了阻挡我们通用化Android数据库操作的五个问题,但是现在我们还不能立即开始去解决这些问题。

试想一下,我们有一个News,那么,相应的就会有NewsDaoNewsDaoImpl,同理,如果出现一个Book,是不是也要写出BookDaoBookDaoImpl? 这个问题想想就觉得太疯狂!

这里的BookDao等等都是假想的,和NewsDao是一样的东西,就不在复制黏贴一遍了。(偷笑中….)

那么,在解决五个问题之前我们需要做的工作就是,把NewsDaoBookDao中公共的部分在提取一次;把NewsDaoImplBookDaoImpl中的公共部分也再提取一次。

去年一滴相思泪,今年刚流到腮边

工作需要一步一步做,那么我们首先抽取NewsDaoBookDao接口中公共的部分,并放在BaseDao中。既然是抽取公共的,那么原先位于NewsDao中,传入特定的参数(如:Integer、News)可能就不在适用了,我们需要寻找更为一般、通用的东西来替代,而泛型就是我们的好帮手(O(∩_∩)O~)。

public interface BaseDao<M> {    /**     * 增加     */    long insert(M m);    /**     * 删除<     * 传入的参数可能或是Integer或者Long或者String,     * 那么此处就不能够使用具有特殊性的类型,要使用具有一般性的、公共的。<     * 而Serizlizable,则是Integer、Long、String共性的不二选择。     */    int delete(Serializable id);    /**     * 修改     */    int update(M m);    /**     * 查询所有     */    List<M> findAll();}

是不是很简单?

我们把公用的方法抽取到BaseDao中,并把参数替换成为泛型和Serializable,这样NewsDao只需要继承我们的BaseDao并传入泛型,就大功告成了。代码如下:

public interface NewsDao extends BaseDao<News> {    // 既然提取完公共的了,那么这些具有特殊性的就不需要了    // 另外,实现BaseDao接口    // long insert(News news);    // int delete(int id);    // int update(News news);    // List<News> findAll();    // 当然,除了通用的增删改查,还具有一些特有的方法    // 比如,查询按时间排序的最新的新闻}

是不是这个样子?NewsDao里面空空如也,当然,如果我们需要一些更为特殊的方法,还是需要写在这里面的,例如:查询按时间排序的最新的新闻。

问君能有几多愁?恰似一江春水向东流

既然接口中的公共的方法能够抽取,那么它们的实现类也是不能够例外的。我们抽取实现类(NewsDaoImplBookDaoImpl)中公共的部分,放在BaseDaoSupport中。

这里要记住BaseDaoBaseDaoSupport之间,只不过是NewsDaoNewsDaoImpl的映射,它们之间也是实现类的关系。

public abstract class BaseDaoSupport<M> implements BaseDao<M> {    // * 抽取公共部分应该解决的问题:<br>    // * 问题1:表名的获取<br>    // * 问题2:如何将实体中的数据,按照对应关系导入到数据库中<br>    // * 问题3:明确实体中主键是谁?获取到主键中封装的值<br>    // * 问题4:实体的对象创建<br>    // * 问题5:如何将数据库中表的列的数据,按照对应关系,封装到实体中<br>    private Context context;    private DBHelper helper;    private SQLiteDatabase db;    public BaseDaoSupport(Context context) {        super();        this.context = context;        this.helper = new DBHelper(context);        this.db = helper.getWritableDatabase();    }    @Override    public long insert(M m) {        // 请在此处填写代码        return 0;    }    @Override    public int delete(Serializable id) {        // 请在此处填写代码        return 0;    }    @Override    public int update(M m) {        // 请在此处填写代码        return 0;    }    @Override    public List<M> findAll() {        // 请在此处填写代码        return null;    }}

我们来看一下BaseDaoSupport中的东西,我们抽取出了ContextDBHelperSQLiteOpenHelper还有构造函数,看起来和我们的NewsDaoImpl中的东西一样。

再看看下面的insertdeleteupdatefindAll等方法,模子是一样的,只不过里面具体的参数替换成了泛型。

回过头我们看看被抽取完的NewsDaoImpl变成什么样子了,首先继承了BaseDaoSupport<News>并传入了自己所要操作的实体bean,然后又实现了NewsDao接口。代码如下:

public class NewsDaoImpl extends BaseDaoSupport<News> implements NewsDao {    public NewsDaoImpl(Context context) {        super(context);    }}

好像除了构造函数就空空如野了,但实际情况并非如此,我们在BaseDaoSupport中,已经实现了BaseBase接口,并且重写了insertupdatedeletefindAll等方法,这样我们NewsDaoImple中就继承了这些公共的方法了。

到了这一步是不是很开心! O(∩_∩)O~ ,代码看着越来越清爽了!

衣带渐宽终不悔,为伊消得人憔悴

到了这一步,我们的抽取和重构就基本完成了,那么我们接下来的工作重点就位于BaseDaoSupport,只要我们能够在此类中解决上一篇文章中碰到的五个问题,那么我们就可以做到Android中数据库的通用操作了。

是不是有点小激动了!! 别着急,我们慢慢来,请看下回分解!

最后把重构完成后的包结构展示给大家:

这里写图片描述

这里写图片描述

如果你浪费了自己的年龄,那是挺可悲的。因为你的青春只能持续一点儿时间——很短的一点儿时间。 —— 王尔德

2 0
原创粉丝点击