项目中我们可以加载assets文件夹下的xml文件、txt文件、图片文件,也可加载sd卡下xml文件、txt文件、图片文件。如图
这里有两个变化的维度,文件地址和数据格式。我将抽象与实现分离构建本地数据加载。
代码:数据
public interface Data<D> {
/**
* 加载数据流
* @param inputStream
*/
void load(InputStream inputStream);
/**
* 数据对象
* @return
*/
D get();
/**
* 数据对象大小
* @return
*/
int size();
}
抽象数据
public abstract class AbsData<D> implements Data<D> {
protected Path path;
public AbsData(Path path) {
this.path = path;
load(path.loadInputStream());
}
//关闭流
protected void close(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException ex) {
}
}
}
}
数据地址
public interface Path {
/**
* 路径
*
* @return
*/
void setDataPath(String path);
/**
* 获取流
*
* @return
*/
InputStream loadInputStream();
}
抽象地址
public abstract class AbsPath implements Path {
protected String path;
@Override
public void setDataPath(String path) {
this.path = path;
}
}
Assets文件夹
public class AssetPath extends AbsPath {
private Context context;
public AssetPath(Context context) {
this.context = context;
}
@Override
public InputStream loadInputStream() {
try {
return context.getAssets().open(path);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
sd卡
public class FilePath extends AbsPath {
@Override
public InputStream loadInputStream() {
try {
File urlFile = new File(path);
return new FileInputStream(urlFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
位图数据
public class BitmapData extends AbsData<Bitmap> {
private Bitmap data;
public BitmapData(Path path) {
super(path);
}
@Override
public void load(InputStream inputStream) {
data = BitmapFactory.decodeStream(inputStream);
}
@Override
public Bitmap get() {
return data;
}
@Override
public int size() {
return data.getByteCount();
}
}
字符数据
public class StringData extends AbsData<String> {
protected String data;
public StringData(Path path) {
super(path);
}
@Override
public void load(InputStream inputStream) {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
close(inputStream);
}
data = sb.toString();
}
@Override
public String get() {
return data;
}
@Override
public int size() {
return data.length();
}
}
抽象xml数据
public abstract class XmlData<T> extends AbsData {
protected T data;
public XmlData(Path path) {
super(path);
}
@Override
public void load(InputStream inputStream) {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
data = parser(builder.parse(inputStream));
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
close(inputStream);
}
}
@Override
public T get() {
return data;
}
protected abstract T parser(Document parse);
}
xml数据
public class RiverXml extends XmlData<List<River>> {
public RiverXml(Path path) {
super(path);
}
@Override
public int size() {
return data.size();
}
@Override
protected List<River> parser(Document document) {
//找到根Element
data = new ArrayList<>();
Element root = document.getDocumentElement();
NodeList nodes = root.getElementsByTagName("river");
//遍历根节点所有子节点,rivers 下所有river
River river;
for (int i = 0; i < nodes.getLength(); i++) {
river = new River();
Element riverElement = (Element) (nodes.item(i));
river.setName(riverElement.getAttribute("name"));
river.setLength(Integer.parseInt(riverElement.getAttribute("length")));
Element introduction = (Element) riverElement.getElementsByTagName("introduction").item(0);
river.setIntroduction(introduction.getFirstChild().getNodeValue());
Element imageUrl = (Element) riverElement.getElementsByTagName("imageurl").item(0);
river.setImageurl(imageUrl.getFirstChild().getNodeValue());
data.add(river);
}
return data;
}
River类
public class River implements Serializable {
private int length;
private String imageurl;
private String name;
private String introduction;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
public String getIntroduction() {
return introduction;
}
public void setIntroduction(String introduction) {
this.introduction = introduction;
}
public String getImageurl() {
return imageurl;
}
public void setImageurl(String imageurl) {
this.imageurl = imageurl;
}
}
测试xml文件
<?xml version="1.0" encoding="utf-8"?>
<rivers>
<river name="灵渠" length="605">
<introduction>
灵渠在广西壮族自治区兴安县境内,是世界上最古老的运河之一,有着“世界古代水利建筑明珠”的美誉。
</introduction>
<imageurl>
http://imgsrc.baidu.com/baike/pic/item/389aa8fdb7b8322e08244d3c.jpg
</imageurl>
</river>
<river name="胶莱运河" length="200">
<introduction>
胶莱运河南起黄海灵山海口,北抵渤海三山岛,流经现胶南、胶州、平度、高密、昌邑和莱州等,全长200公里。
</introduction>
<imageurl>
http://imgsrc.baidu.com/baike/pic/item/389aa8fdb7b8322e08244d3c.jpg
</imageurl>
</river>
<river name="苏北灌溉总渠" length="168">
<introduction>
位于淮河下游江苏省北部,西起洪泽湖边的高良涧,流经洪泽,青浦、淮安,阜宁、射阳,滨海等六县(区),东至扁担港口入海的大型人工河道。
</introduction>
<imageurl>
http://imgsrc.baidu.com/baike/pic/item/389aa8fdb7b8322e08244d3c.jpg
</imageurl>
</river>
</rivers>
代码调用
FilePath filePath = new FilePath();
AssetPath assetPath = new AssetPath(this);
filePath.setDataPath("/sdcard/river.xml");
assetPath.setDataPath("river.xml");
RiverXml assetData = new RiverXml(assetPath);
RiverXml fileData = new RiverXml(filePath);
L.d(assetData.get().get(1).getName());
L.d(fileData.get().get(2).getName());
assetPath.setDataPath("temp_license.txt");
StringData stringData = new StringData(assetPath);
L.d(stringData.get());
结果
07-18 09:45:27.119 636-636/com.aiju.myapplication D/AiJu: 胶莱运河
07-18 09:45:27.119 636-636/com.aiju.myapplication D/AiJu: 苏北灌溉总渠
07-18 09:45:27.121 636-636/com.aiju.myapplication D/AiJu: assets文本测试