首页 > 代码库 > 解读郭神LitePal源代码-litepal.xml的解析

解读郭神LitePal源代码-litepal.xml的解析

在開始使用LitePal时,要求在项目的assets文件夹下新建一个litepal.xml文件:

<?xml version="1.0" encoding="utf-8"?

> <litepal> <dbname value="http://www.mamicode.com/Questionnaire"/> <version value="http://www.mamicode.com/1"></version> <list> <mapping class="com.aliao.parser.entity.UserInfo"></mapping> <mapping class="com.aliao.parser.entity.SurveyInfo"></mapping> </list> </litepal>


该配置文件用来设定数据库的名字、版本以及全部的对象关系映射模型。

什么是对象关系映射模型?

由于sqlite数据库是关系型数据库,而编程是面向对象的,为了使用面向对象的方式来操作数据库,所以在关系数据库和实体对象之间做了一个映射,这样在进行数据库操作的时候,我们仅仅须要操作实体对象就可以,不须要直接处理sql语句。

在litepal.xml文件的<list>标签里来设置须要进行映射的对象,数据库里的每一张的表都相应一个实体对象类。


一个litepal.xml文件让我们在进行数据库基本信息配置上变得异常方便。那程序是怎么来获取到我们配置后的信息呢?

首先须要通过解析xml文件来获取到数据库名,版本号信息,以及须要映射的对象。

在Litepal里使用SAXParser来解析xml。那解析后的信息放在哪里呢,是由LitePalAttr该实体类来接收从litepal.xml里读取到的全部属性值。


本来想直接贴源代码的,还是立足源代码自己手动实现一下好了,勤奋宝宝在咬我,biaji biaji biaji~~~


创建一个LitePalAttr实体类,相应litepal.xml的属性及其set/get方法:

package com.aliao.parser.entity;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by aliao on 2015/6/4.
 */
public class LitePalAttr {

    private static LitePalAttr litePalAttr;

    //数据库版本号号
    private int version;
    //数据库名
    private String dbName;
    //全部在数据库中想要有映射关系的实体类
    private List<String> classNames;

    public int getVersion() {
        return version;
    }

    public void setVersion(int version) {
        this.version = version;
    }

    public String getDbName() {
        return dbName;
    }

    public void setDbName(String dbName) {
        this.dbName = dbName;
    }

    /**
     * 在sqlite里table_schema表示自己主动生成的,这里一定要手动加入进去
     * table_schema用来查看数据库的元数据。这里的元数据包含表名及表类型
     * @return
     */
    public List<String> getClassNames() {
        if (classNames == null){
            classNames = new ArrayList<>();
            classNames.add("com.aliao.parser.entity.Table_Schema");
        }else if (classNames.isEmpty()){
            classNames.add("com.aliao.parser.entity.Table_Schema");
        }
        return classNames;
    }

    public void addClassName(String className){
        getClassNames().add(className);
    }

    /**
     * 这里用双重检測来实现单例模式
     * 整个程序创建一个唯一的litePalAttr对象,能够通过这个对象拿到数据库的基本信息
     * @return
     */
    public static LitePalAttr getIntance(){
        if (litePalAttr == null){
            synchronized (LitePalAttr.class){
                if (litePalAttr == null){
                    litePalAttr = new LitePalAttr();
                }
            }
        }
        return litePalAttr;
    }

    @Override
    public String toString() {
        return "数据库名称:"+dbName+" ,数据库版本号"+version;
    }
}


接下来就是怎样解析litepal.xml的问题了。源代码里郭神使用SAXParser来解析,怎样使用SAXParser来解析一个xml文件的知识会单独写篇blog总结一下,这里就不啰嗦直接上吧。

解析litepal.xml须要创建两个类:

       LitePalParser:这个类基本的操作就是创建解析器。然后解析文档

       LitePalContentHandler(继承DefaultHandler):解析文档的详细实现,開始对文档进行扫描分析。将xml里的属性值保存到LitePalAttr的相应属性里。

创建解析器:

package com.aliao.parser.entity;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by aliao on 2015/6/4.
 */
public class LitePalAttr {

    private static LitePalAttr litePalAttr;

    //数据库版本号号
    private int version;
    //数据库名
    private String dbName;
    //全部在数据库中想要有映射关系的实体类
    private List<String> classNames;

    public int getVersion() {
        return version;
    }

    public void setVersion(int version) {
        this.version = version;
    }

    public String getDbName() {
        return dbName;
    }

    public void setDbName(String dbName) {
        this.dbName = dbName;
    }

    /**
     * 在sqlite里table_schema表示自己主动生成的,这里一定要手动加入进去
     * table_schema用来查看数据库的元数据,这里的元数据包含表名及表类型
     * @return
     */
    public List<String> getClassNames() {
        if (classNames == null){
            classNames = new ArrayList<>();
            classNames.add("com.aliao.parser.entity.Table_Schema");
        }else if (classNames.isEmpty()){
            classNames.add("com.aliao.parser.entity.Table_Schema");
        }
        return classNames;
    }

    public void addClassName(String className){
        getClassNames().add(className);
    }

    /**
     * 这里用双重检測来实现单例模式
     * 整个程序创建一个唯一的litePalAttr对象,能够通过这个对象拿到数据库的基本信息
     * @return
     */
    public static LitePalAttr getIntance(){
        if (litePalAttr == null){
            synchronized (LitePalAttr.class){
                if (litePalAttr == null){
                    litePalAttr = new LitePalAttr();
                }
            }
        }
        return litePalAttr;
    }

    @Override
    public String toString() {
        return "数据库名称:"+dbName+"\n数据库版本号:"+version+"\n\n数据库映射对象类名:";
    }
}


将xml的属性值保存到实体类相应属性里:

package com.aliao.parser.saxparser;

import com.aliao.parser.entity.LitePalAttr;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/**
 * Created by aliao on 2015/6/4.
 */
public class LitePalContentHandler extends DefaultHandler{

    private LitePalAttr litePalAttr;

    @Override
    public void startDocument() throws SAXException {
        litePalAttr = LitePalAttr.getIntance();
        litePalAttr.getClassNames().clear();//由于litePalAttr是静态的,所以假设再次进行解析要清空之前的数据
    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        if ("dbname".equalsIgnoreCase(localName)){
            for (int i = 0; i<attributes.getLength(); i++){
                if ("value".equalsIgnoreCase(attributes.getLocalName(i))){
                    litePalAttr.setDbName(attributes.getValue(i).trim());
                }
            }
        }else if ("version".equalsIgnoreCase(localName)){
            for (int i = 0; i<attributes.getLength();i++){
                if ("value".equalsIgnoreCase(attributes.getLocalName(i))){
                    litePalAttr.setVersion(Integer.parseInt(attributes.getValue(i).trim()));
                }
            }
        }else if ("mapping".equalsIgnoreCase(localName)){
            for (int i = 0; i<attributes.getLength();i++){
                if ("class".equalsIgnoreCase(attributes.getLocalName(i))){
                    litePalAttr.addClassName(attributes.getValue(i).trim());
                }
            }
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        super.endElement(uri, localName, qName);
    }

    @Override
    public void endDocument() throws SAXException {
        super.endDocument();
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        super.characters(ch, start, length);
    }
}

在主程序里启动解析:

package com.aliao.parser.saxparser;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;

import com.aliao.parser.R;
import com.aliao.parser.entity.LitePalAttr;

/**
 * Created by aliao on 2015/6/4.
 */
public class LitePalParserFragment extends Fragment implements View.OnClickListener {
    public static final String TAG = LitePalParserFragment.class.getSimpleName();
    private TextView mTvResult;

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

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_saxparser_litepal, container, false);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        Button btnParse = (Button) view.findViewById(R.id.btn_parse_litepal);
        btnParse.setOnClickListener(this);
        mTvResult = (TextView) view.findViewById(R.id.tvSaxParserResult);
    }


    @Override
    public void onClick(View v) {
        LitePalParser.parseLitePalConfiguration();
        showResult();
    }

    private void showResult() {
        mTvResult.setVisibility(View.VISIBLE);
        LitePalAttr mLitePalAttr = LitePalAttr.getIntance();
        StringBuffer sb = new StringBuffer(mLitePalAttr.toString());
        for (String className:mLitePalAttr.getClassNames()){
            sb.append("\n\n"+className);
        }
        mTvResult.setText("SAXParser解析litepal.xml结果:\n\n"+sb.toString());
    }
}
 

执行结果:

技术分享

先到这吧



解读郭神LitePal源代码-litepal.xml的解析