Android中Xml工具类的封装

  Android中经常使用到操作XML,其中有一对XmlSerializer和XmlPullParser封装的很好,可是操作起来很复杂,虽然不难,但是感觉做了一点小事却写了一大堆的代码。有点烦,因此封装一下。

  其思路为:根据传入的数据,获取字节码后进行反射解析,然后在存储。思路很简单,此demo只写了一个基本的List<T>类型的,其它类型道理与此大同小异,就当这个是抛砖引玉了。

  对于一些Model可能有些字段是不需要序列化的,这里可以使用注解来操作

/**
 * XML操作工具类
 * @author chenhao24
 *
 */
public class XMLUtils{
    
    public interface XMLProgressCallback{
        void onBefore(List<?> data);
        void onProgress(int index);
        void onFinished();
    }
    
    /**
     * 解析XML数据
     * @param path
     * @param clazz
     * @return
     */
    public static List<Object> pullParserData(String path, Class<?> clazz,XMLProgressCallback callback){

        if (clazz == null || path == null || TextUtils.isEmpty(path)) {
            return null;
        }

        File destFile = new File(path);
        
        if(! destFile.exists()){
            return null;
        }
        
        List<Object> resData = null;

        Map<String, Method> mdatas = new HashMap<String, Method>();

        String[] classNames = parseFields(clazz, mdatas, StaticDatas.METHOD_SET);
        
        List<Object> data = queryData(destFile, resData, mdatas, classNames);
        
        callback.onBefore(data);
        
        return data;
    }
    
    /**
     * 从XML中读取数据
     * @param destFile
     * @param resData
     * @param mdatas
     * @param classNames
     * @return
     */
    private static List<Object> queryData(File destFile, List<Object> resData,Map<String, Method> mdatas, String[] classNames) {
        
        XmlPullParser pullParser = Xml.newPullParser();

        InputStream inputStream;

        try {
            inputStream = new FileInputStream(destFile);

            pullParser.setInput(inputStream, StaticDatas.UTF8);

            int eventType = pullParser.getEventType();
            
            Object obj = null;

            while (eventType != XmlPullParser.END_DOCUMENT) {
                String tagName = pullParser.getName();

                if (eventType == XmlPullParser.START_TAG) {
                    if (tagName.equals(StaticDatas.XML_ROOT)) {
                        resData = new ArrayList<Object>();
                        eventType = pullParser.next();
                        continue;
                    }

                    if (tagName.equals(classNames[0])) {
                        obj = Class.forName(classNames[1]).newInstance();
                        eventType = pullParser.next();
                        continue;
                    }

                    for (Iterator<Entry<String, Method>> iter = mdatas.entrySet().iterator(); iter.hasNext();) {
                        Entry<String, Method> entry = iter.next();

                        String key = entry.getKey();

                        if(key.equals(tagName)){
                            Method method = entry.getValue();
                            method.invoke(obj, pullParser.nextText());
                        }
                    }
                }

                if (eventType == XmlPullParser.END_TAG) {
                    if (tagName.equals(classNames[0])) {
                        resData.add(obj);
                    }
                }

                eventType = pullParser.next();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        
        return resData;
    }
    
    /**
     * 持久化数据到本地xml
     * @param path
     * @param data
     * @throws Exception
     */
    public static void serializerData(String path,List<?> data,XMLProgressCallback callback){
        if(data == null || path == null || TextUtils.isEmpty(path) || data.isEmpty()){
            return;
        }
        
        callback.onBefore(data);
        
        File destFile = new File(path);
        
        try {
            if(destFile.exists()){
                destFile.delete();
                destFile.createNewFile();
            }
            
            Map<String, Method> mdatas = new HashMap<String, Method>();
            
            String className = parseFields(data,mdatas,StaticDatas.METHOD_GET)[0];
            
            insertData(mdatas,data,destFile,className,callback);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        callback.onFinished();
    }
    
    
    
    /**
     * 解析字段和Get方法
     * @param clazz
     * @param mdatas
     * @return
     */
    private static String[] parseFields(Class<?> clazz,Map<String, Method> mdatas,String methodType) {
        
        Field[] fields = clazz.getDeclaredFields();

        Method[] methods = clazz.getMethods();
        
        for (Field field : fields) {
            String fieldName = field.getName().toLowerCase(Locale.ENGLISH);
            for (Method method : methods) {
                //转小写
                String methodName = method.getName().toLowerCase(Locale.ENGLISH);
                
                // 根据 field和get匹配
                if (methodName.startsWith(methodType)
                        && methodName.endsWith(fieldName)) {
                    mdatas.put(fieldName, method);
                } else {
                    continue;
                }
            }
        }
        
        String clazzName = clazz.getName();
        
        return new String[]{clazzName.substring(clazzName.lastIndexOf(".") + 1).toLowerCase(Locale.ENGLISH),clazzName};
    }

    /**
     * 获取字节码并解析出字段和该字段对应的get方法
     * @param data
     * @param mdatas
     * @return
     */
    private static String[] parseFields(List<?> data,Map<String, Method> mdatas,String methodType) {
        Class<?> clazz = data.get(0).getClass();
        return parseFields(clazz,mdatas,methodType);
    }
    
    /**
     * 对数据进行解析并存储到xml中
     * 这个方法写的不好,解析类和操作XML的代码混合在一起
     * 而且还有个 双重循环。暂时先不处理
     * @param mdatas
     * @param data
     * @param destFile
     * @param clazzName
     * @throws Exception
     */
    private static void insertData(Map<String, Method> mdatas,List<?> data,File destFile,String clazzName,XMLProgressCallback callback) throws Exception{
        
        // 此处进行存储
        XmlSerializer xmlCreater = Xml.newSerializer();
        
        FileOutputStream outputStream = new FileOutputStream(destFile);
        
        xmlCreater.setOutput(outputStream, StaticDatas.UTF8);
        
        xmlCreater.startDocument(StaticDatas.UTF8, true);
        
        // XML_ROOT 常量 写死 的 根节点 list
        xmlCreater.startTag(null, StaticDatas.XML_ROOT);
        
        for (Object mtmp : data) {
            // 此处开始循环创建
            xmlCreater.startTag(null, clazzName);
            
            int index = 0;
            
            for (Iterator<Entry<String, Method>> iter = mdatas.entrySet().iterator(); iter.hasNext();) {
                callback.onProgress(++ index);
                
                Entry<String, Method> entry = iter.next();
                String key = entry.getKey();
                Method method = entry.getValue();
                Object obj = method.invoke(mtmp, new Object[]{});
                
                xmlCreater.startTag(null, key);
                xmlCreater.text(obj.toString());
                xmlCreater.endTag(null, key);
            }
            
            // 循环创建结束
            xmlCreater.endTag(null, clazzName);
        }
        
        xmlCreater.endTag(null, StaticDatas.XML_ROOT);
        
        xmlCreater.endDocument();
        
        xmlCreater.flush();
        
        if(outputStream != null){
            outputStream.close();
        }
        
        xmlCreater = null;
    }
}
原文地址:https://www.cnblogs.com/cbooy/p/4965073.html