前言:
转眼已经2018年了, 17年有点忙,出差将近三个月,博客也停更了好久。 一直都是不停的修复bug,和做一些业务需要的提示和交互。主要是因为和硬件有关系所以比较麻烦,开发周期也很长,而且还不稳定,硬件先行,然后在是调试,交互。不过也有好处,学到的东西自然不是简简单单的 代码了。
然后在转换这个数据之前我啥真的是一脸懵逼啊,连jsbc都不知道是啥,也不知道怎么用,总感觉是陌生的东西,然后获取到数据后也是没一点头绪,不知道怎么划分数据,分成一层一层,虽然知道是用循环,但是怎么把一个数据集合循环出几层?
废话不多说,来今天的正题!
任务:
1.需求:民航局给了你一个sql(省市区)文件,需要你对应的转换成你需要的格式方便解析。
2.原因:网上有诸多类似的 province.json数据 ,但是不行,因为此SQL表中 是定制的 所有的城市的ID 号是定制的,①请求参数需要ID号,②显示UI 需要 文字
3.目的:为了 到达效果就是三级联动,同时根据对应的城市索引到对应的城市ID,并执行下一步操作
4.需要用到的工具 :①Navicat 12 for MySQL (为什么不用MySql Workbench,当然这个只是为了建个表格,你要是会用,
但是还是用最简单的可视化的还是比较方便的 ② Eclipse + 驱动包(mysql-connector-java-5.1.27.jar) ③百度 json 格式转换.
先上几个gif图和格式吧!
第一步就是先将SQL 数据转换成类似图二的格式,
第二步:然后在将图二解析 实现如下的效果,
第三步:gif图确定后 界面显示是文字,Toast提示是所对应的 城市ID
先导入表格,
然后
然后在Eclipse中创建程序,
下面导入的2个jar包 分别是 用来将String 转换为 json 数据,和jdbc的驱动包
第一步:先打通和数据库的链接。
import java.sql.*;
public class GetConnection {
public static void main(String[] args) {
try {
// 调用Class.forName()方法加载驱动程序
Class.forName("com.mysql.jdbc.Driver");
System.out.println("成功加载MySQL驱动!");
} catch (ClassNotFoundException e1) {
System.out.println("找不到MySQL驱动!");
e1.printStackTrace();
}
//String url = "jdbc:mysql://localhost:3306/beibei"; // JDBC的URL
String url = "jdbc:mysql://localhost:3306/splname"; // 这里splname 是你的表的名字,例如我上边的是beibei
// 调用DriverManager对象的getConnection()方法,获得一个Connection对象
Connection conn;
try {
//conn = DriverManager.getConnection(url, "root", "123456");
conn = DriverManager.getConnection(url, "root", "password");//这里password 是密码 创建服务时候的密码
// 创建一个Statement对象
Statement stmt = conn.createStatement(); // 创建Statement对象
System.out.print("成功连接到数据库!");
stmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
第二步:如果运行结果是成功连接数据库,我们就可以进行下一步,读取数据了。
public static void main(String[] args) {
try {
// 调用Class.forName()方法加载驱动程序
Class.forName("com.mysql.jdbc.Driver");
System.out.println("成功加载MySQL驱动!");
String url = "jdbc:mysql://localhost:3306/beibei"; // JDBC的URL
Connection conn;
conn = DriverManager.getConnection(url, "root", "211314");
Statement stmt = conn.createStatement(); // 创建Statement对象
System.out.println("成功连接到数据库!");
String sql = "select * from theaty_area"; // 要执行的SQL
ResultSet rs = stmt.executeQuery(sql);// 创建数据对象
System.out.println("索引ID" + "\t\t" + "地区名称" + "\t\t" + "地区父ID"
+ "\t\t" + "排序" + "\t\t" + "地区深度");
while (rs.next()) {
System.out.print(rs.getInt(1) + "\t\t");
System.out.print(rs.getString(2) + "\t\t");
System.out.print(rs.getInt(3) + "\t\t");
System.out.print(rs.getInt(4) + "\t\t");
System.out.print(rs.getInt(5) + "\t\t");
System.out.print(rs.getString(6) + "\t\t");
System.out.println();
}
saveListData(rs);//分类存数据
rs.close();
stmt.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
运行打印成功便是成功了一半,成功读取出数据了。下面就是要分类了
第三步:之前我在读取数据后,我把所有的数据存到同一个集合中,然后根本没有思路在进行下去了,我发现我无论怎么循环都很麻烦,后来问了一个朋友,他经验比我丰富,一句话就让我明白了。也是同样的:第一步读取数据 第二步:分类,需要几层分成几层,然后每一层循环遍历 。第三步:在统一存到同一个集合中并遍历生成json格式在输出。
我是豁然开朗,对啊,没说非要存到一个集合中 ,可以先分在合。怎么方便,怎么逻辑清楚怎么来啊。
于是乎:
/**
* 存储数据
*
* @param rs
*/
public static void saveListData(ResultSet rs) {
try {
ArrayList<TheatyBean> beanlist01 = new ArrayList();
ArrayList<TheatyBean> beanlist02 = new ArrayList();
ArrayList<TheatyBean> beanlist03 = new ArrayList();
while (rs.next()) {
int area_deep = rs.getInt(5);//此处是spl数据中的地区深度(1,2,3-->省市区)
if (area_deep == 1) {
TheatyBean theatyBean = new TheatyBean();
theatyBean.name_id = rs.getInt(1);
theatyBean.name = rs.getString(2);
theatyBean.parent_area_id = rs.getInt(3);
beanlist01.add(theatyBean);
} else if (area_deep == 2) {
TheatyBean theatyBean = new TheatyBean();
theatyBean.name_id = rs.getInt(1);
theatyBean.name = rs.getString(2);
theatyBean.parent_area_id = rs.getInt(3);
beanlist02.add(theatyBean);
} else if (area_deep == 3) {
TheatyBean theatyBean = new TheatyBean();
theatyBean.name_id = rs.getInt(1);
theatyBean.name = rs.getString(2);
theatyBean.parent_area_id = rs.getInt(3);
beanlist03.add(theatyBean);
}
}
RankBeanList(beanlist01, beanlist02, beanlist03);
// Arrayprintln(beanlist01);
// Arrayprintln(beanlist02);
// Arrayprintln(beanlist03);
} catch (SQLException e) {
e.printStackTrace();
}
}
TheatyBean.java
public class TheatyBean {
public int name_id;// 城市id
public String name;//城市名字
public int parent_area_id;// 父ID
}
第四步:就是逻辑的分类了。相信都能看懂。
/**
* 通过三个级别数据,循环遍历
*
* @param beanlist01
* @param beanlist02
* @param beanlist03
*/
private static void RankBeanList(ArrayList<TheatyBean> beanlist01,
ArrayList<TheatyBean> beanlist02, ArrayList<TheatyBean> beanlist03) {
LinkedList<LinkedHashMap<String, Object>> jsonList = new LinkedList<LinkedHashMap<String, Object>>();// 省集合
for (int i = 0; i < beanlist01.size(); i++) {
LinkedHashMap<String, Object> prMap = new LinkedHashMap<String, Object>();
prMap.put("name", beanlist01.get(i).name);
prMap.put("name_id", String.valueOf(beanlist01.get(i).name_id));
List<LinkedHashMap<String, Object>> citylist = new ArrayList<LinkedHashMap<String, Object>>();// 市集合
for (int j = 0; j < beanlist02.size(); j++) {
if (beanlist01.get(i).name_id == beanlist02.get(j).parent_area_id) {
LinkedHashMap<String, Object> cityMap = new LinkedHashMap<String, Object>();
cityMap.put("name", String.valueOf(beanlist02.get(j).name));
cityMap.put("name_id", String.valueOf(beanlist02.get(j).name_id));
ArrayList<String> list_area = new ArrayList<String>();// 区名字集合
ArrayList<String> list_area_id = new ArrayList<String>();// 区编号集合
for (int k = 0; k < beanlist03.size(); k++) {
if (beanlist02.get(j).name_id == beanlist03.get(k).parent_area_id) {
String area = beanlist03.get(k).name;
String area_id = String.valueOf(beanlist03.get(k).name_id);
list_area.add(area);
list_area_id.add(area_id);
}
}
cityMap.put("area", list_area);
cityMap.put("area_id", list_area_id);
citylist.add(cityMap);
}
}
prMap.put("city", citylist);// 省下面的市集合
jsonList.add(prMap);
}
mapPrintln(jsonList);// 输出
}
这里使用LinkedHashMap 用来排序,毕竟本身给的sql数据库是乱的。根据父ID循环找到归属的城市。并装入map中。
第五步:就是生成json 并输出
/**
* <P>
* 打印map集合和数据
* </p>
*
* @param list
*/
private static void mapPrintln(List<LinkedHashMap<String, Object>> list) {
// TODO Auto-generated method stub
if (list == null && list.size() == 0) {
return;
}
System.out.println(list.size()
+ "-----------------------------------------------------");
// System.out.println(list.toString());
Gson gson = new Gson();
String jsonString = gson.toJson(list);
inputFile(jsonString);// json文件
System.out.println(jsonString);// 打印
}
开启线程并指定输出路径:
/**
* 开启线程
*
* @param jsonString
*/
private static void inputFile(final String jsonString) {
// TODO Auto-generated method stub
new Thread(new Runnable() {
public void run() {
// TODO Auto-generated method stub
WriteConfigJson(jsonString);
}
}).start();
}
/**
* 输出json文件
*
* @param args
*/
public static void WriteConfigJson(String args) {
String src = "D:\\province.json";// 自定义文件路径
File file = new File(src);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
try {
file.delete();
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
try {
FileWriter fw = new FileWriter(file, true);
fw.write(args);
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
最后拿到json数据后,他可能是这样的
百度json格式 就OK 了。 并导入自己的assets 资源文件夹中 使用。
最后一步就是解析过程了:
首先获取资源文件:也是要开启线程的,线程内执行解析过程。
获取:
/***
* <P>解析JSon数据</P>
*/
private void initJsonData() {
/**
* 注意:assets 目录下的Json文件仅供参考,实际使用可自行替换文件
* 关键逻辑在于循环体
*
* */
String JsonData = new GetJsonDataUtil().getJson(this, "city/province.json");//获取assets目录下的json文件数据
ArrayList<JsonBean> jsonBean = parseData(JsonData);//用Gson 转成实体
}
解析:
/**
* <P>使用gson 解析</P>
*
* @param result
* @return
*/
public ArrayList<JsonBean> parseData(String result) {//Gson 解析
ArrayList<JsonBean> detail = new ArrayList<>();
try {
//含ID 的解析
Gson gson = new Gson();
ArrayList<JsonBean> jsonBeen = gson.fromJson(result, new TypeToken<ArrayList<JsonBean>>() {
}.getType());
detail = jsonBeen;
} catch (Exception e) {
e.printStackTrace();
handler.sendEmptyMessage(MSG_LOAD_FAILED);
}
return detail;
}
通过Gson 的反射原理解析json中的参数。
最后就是分类成不同的集合:并各取所需。再次我创建了 6个集合 分别是省,市,区 和对应的ID 集合。因为清楚明了。
private ArrayList<JsonBean> options1Items = new ArrayList<>();
private ArrayList<ArrayList<String>> options2Items = new ArrayList<>();
private ArrayList<ArrayList<ArrayList<String>>> options3Items = new ArrayList<>();
private ArrayList<JsonBean> index1Items = new ArrayList<>();
private ArrayList<ArrayList<String>> index2Items = new ArrayList<>();
private ArrayList<ArrayList<ArrayList<String>>> index3Items = new ArrayList<>();
/***
* <P>解析JSon数据</P>
*/
private void initJsonData() {
/**
* 注意:assets 目录下的Json文件仅供参考,实际使用可自行替换文件
* 关键逻辑在于循环体
*
* */
String JsonData = new GetJsonDataUtil().getJson(this, "city/province.json");//获取assets目录下的json文件数据
ArrayList<JsonBean> jsonBean = parseData(JsonData);//用Gson 转成实体
/**
* 添加省份数据
*
* 注意:如果是添加的JavaBean实体,则实体类需要实现 IPickerViewData 接口,
* PickerView会通过getPickerViewText方法获取字符串显示出来。
*/
options1Items = jsonBean;
index1Items = jsonBean;
for (int i = 0; i < jsonBean.size(); i++) {//遍历省份
// 这里是显示 在UI 上的参数
ArrayList<String> CityList = new ArrayList<>();//该省的城市列表(第二级)
ArrayList<ArrayList<String>> Province_AreaList = new ArrayList<>();//该省的所有地区列表(第三极)
//下面是 需要调用的ID 参数
ArrayList<String> CityID = new ArrayList<>();//该省的城市列表(第二级)
ArrayList<ArrayList<String>> Province_AreaID = new ArrayList<>();//该省的所有地区列表(第
for (int c = 0; c < jsonBean.get(i).getCityList().size(); c++) {//遍历该省份的所有城市
// 城市 name add
String CityName = jsonBean.get(i).getCityList().get(c).getName();
CityList.add(CityName);//添加城市
// 城市 ID add
String cityid = jsonBean.get(i).getCityList().get(c).getName_id();
CityID.add(cityid);
// 地区 name
ArrayList<String> City_AreaList = new ArrayList<>();//该城市的所有地区列表
// 地区 ID
ArrayList<String> City_AreaID = new ArrayList<>();//该城市的所有地区列表
//如果无地区数据,建议添加空字符串,防止数据为null 导致三个选项长度不匹配造成崩溃
if (jsonBean.get(i).getCityList().get(c).getArea() == null
|| jsonBean.get(i).getCityList().get(c).getArea().size() == 0) {
City_AreaList.add("");
City_AreaID.add("");
} else {
for (int d = 0; d < jsonBean.get(i).getCityList().get(c).getArea().size(); d++) {//该城市对应地区所有数据
// 地区 name add
String AreaName = jsonBean.get(i).getCityList().get(c).getArea().get(d);
City_AreaList.add(AreaName);//添加该城市所有地区数据
// 地区 id add
String AreaID = jsonBean.get(i).getCityList().get(c).getArea_id().get(d);
City_AreaID.add(AreaID);//添加该城市所有地区数据
}
}
Province_AreaList.add(City_AreaList);//添加该省所有地区数据
Province_AreaID.add(City_AreaID);//添加该省所有地区数据
}
/**
* 添加城市数据
*/
options2Items.add(CityList);
index2Items.add(CityID);
/**
* 添加地区数据
*/
options3Items.add(Province_AreaList);
index3Items.add(Province_AreaID);
}
handler.sendEmptyMessage(MSG_LOAD_SUCCESS);//通知解析成功。为防止调用的时候空指针
}
最后,可能有人想要三级联动的代码,其实GitHub 上你一搜索 WheelView 都一堆 这样的代码。