本文是该系列的第二篇文章,主要针对上一篇文章中数据读取和存储的代码进行重构,使代码更清晰,为后续的优化做好准备。
接着上文的demo,请看方法insertRecordWithJSONArray
public void insertRecordWithJSONArray(JSONArray array) {
if (array == null || array.length() == 0) {
return;
}
SQLiteDatabase db = null;
try {
db = getWritableDatabase();
db.beginTransaction();
for (int i = 0; i < array.length(); i++) {
JSONObject obj = array.getJSONObject(i);
String serial = obj.getString("serial");
String sort = obj.getString("sort");
int amount = obj.getInt("amount");
int distribute = obj.getInt("distribute");
ContentValues values = new ContentValues();
values.put(RecordTable.COLUMN_SERIAL, serial);
values.put(RecordTable.COLUMN_AMOUNT, amount);
values.put(RecordTable.COLUMN_SORT, sort);
values.put(RecordTable.COLUMN_DISTRIB, distribute);
db.insert(RecordTable.TABLE_NAME, null, values);
}
db.setTransactionSuccessful();
db.endTransaction();
} catch (Exception e) {
e.printStackTrace();
} finally {
closeDatabase(db);
}
}
从JSON读取数据时使用直接操作JSON数据进行处理,如果因为需求变更,数据格式需要改变,如增加一个字段time,修改sort为type,这时使用直接读取JSON的方式就必须进行修改,如果涉及很多地方的调用,维护起来就比较困难。此时我们就需要对数据读取方式进行重构,目的是使代码结构更清晰,维护也会很方便。
我们采用《重构与模式》中的创建模式。新建Model类,用于封装Recod数据,添加数据的get/set方法
public class RecodeModel {
private String serial;
private String sort;
private int amount;
private int distribute;
public RecodeModel() {
}
public String getSerial() {
return serial;
}
public void setSerial(String serial) {
this.serial = serial;
}
public String getSort() {
return sort;
}
public void setSort(String sort) {
this.sort = sort;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
public int getDistribute() {
return distribute;
}
public void setDistribute(int distribute) {
this.distribute = distribute;
}
}
创建RecodeRevert .java类,用于将JSONObject转换成RecodeModel模型数据。
public class RecodeRevert {
public static RecodeModel parseJson(JSONObject obj) {
try {
String serial = obj.getString("serial");
String sort = obj.getString("sort");
int amount = obj.getInt("amount");
int distribute = obj.getInt("distribute");
RecodeModel model = new RecodeModel();
model.setAmount(amount);
model.setSerial(serial);
model.setDistribute(distribute);
model.setSort(sort);
return model;
} catch (JSONException e) {
e.printStackTrace();
return null;
}
}
}
然后就可以将ToyDatabaseHelper中读取JONS数据的代码进行重构
public void insertRecordWithJSONArray(JSONArray array) {
if (array == null || array.length() == 0) {
return;
}
SQLiteDatabase db = null;
try {
db = getWritableDatabase();
db.beginTransaction();
for (int i = 0; i < array.length(); i++) {
JSONObject obj = array.getJSONObject(i);
RecodeModel mode = RecodeRevert.parseJson(obj);
String serial = mode.getSerial();
String sort = mode.getSort();
int amount = mode.getAmount();
int distribute = mode.getDistribute();
ContentValues values = new ContentValues();
values.put(RecordTable.COLUMN_SERIAL, serial);
values.put(RecordTable.COLUMN_AMOUNT, amount);
values.put(RecordTable.COLUMN_SORT, sort);
values.put(RecordTable.COLUMN_DISTRIB, distribute);
db.insert(RecordTable.TABLE_NAME, null, values);
}
db.setTransactionSuccessful();
db.endTransaction();
} catch (Exception e) {
e.printStackTrace();
} finally {
closeDatabase(db);
}
}
继续优化,将多余的变量去掉,直接调用get方法取值:
public void insertRecordWithJSONArray(JSONArray array) {
if (array == null || array.length() == 0) {
return;
}
SQLiteDatabase db = null;
try {
db = getWritableDatabase();
db.beginTransaction();
for (int i = 0; i < array.length(); i++) {
JSONObject obj = array.getJSONObject(i);
RecodeModel mode = RecodeRevert.parseJson(obj);
ContentValues values = new ContentValues();
values.put(RecordTable.COLUMN_SERIAL, mode.getSerial());
values.put(RecordTable.COLUMN_AMOUNT, mode.getAmount());
values.put(RecordTable.COLUMN_SORT, mode.getSort());
values.put(RecordTable.COLUMN_DISTRIB, mode.getDistribute());
db.insert(RecordTable.TABLE_NAME, null, values);
}
db.setTransactionSuccessful();
db.endTransaction();
} catch (Exception e) {
e.printStackTrace();
} finally {
closeDatabase(db);
}
}
重构结束。
回顾本次重构,我们已经完成了使代码更清晰的目的,但似乎代码结构更臃肿了,我们下一步需要使代码更简洁。我们先从RecodeModel下手,多个get/set方法并不是好的编程习惯,毕竟我们更关注get,而尽量要忽略掉set方法。针对目前的需求,RecodeModel中的每个字段都会填充值,不会出现哪个字段为NULL的情况,所以我们就可以将所有的set方法都删除掉,在构造方法中对数据进行初始化。
public class RecodeModel {
private String serial;
private String sort;
private int amount;
private int distribute;
public RecodeModel(String serial, String sort, int amount, int distribute) {
this.serial = serial;
this.sort = sort;
this.amount = amount;
this.distribute = distribute;
}
public String getSerial() {
return serial;
}
public String getSort() {
return sort;
}
public int getAmount() {
return amount;
}
public int getDistribute() {
return distribute;
}
}
对应的RecodeRevert#parseJson(JSONObject obj)也需要修改
public class RecodeRevert {
public static RecodeModel parseJson(JSONObject obj) {
try {
String serial = obj.getString("serial");
String sort = obj.getString("sort");
int amount = obj.getInt("amount");
int distribute = obj.getInt("distribute");
RecodeModel model = new RecodeModel(serial, sort, amount, distribute);
return model;
} catch (JSONException e) {
e.printStackTrace();
return null;
}
}
}
如果一个类的内聚性很强,就不需要通过其他工具类来进行访问,所以我们要做的就是要删掉ModeRevert.java,增加Model类的内聚性,减少调用层级和代码耦合性。看到这里大家可能已经明白了,就是将ModelRevert中各个model的parse方法放到Model里,让Model进行解析处理。
我们将RecodeRevert#parseJson方法搬到RecodeModel中。
public class RecodeModel {
private String serial;
private String sort;
private int amount;
private int distribute;
public RecodeModel(String serial, String sort, int amount, int distribute) {
this.serial = serial;
this.sort = sort;
this.amount = amount;
this.distribute = distribute;
}
public static RecodeModel parseJson(JSONObject obj) {
try {
String serial = obj.getString("serial");
String sort = obj.getString("sort");
int amount = obj.getInt("amount");
int distribute = obj.getInt("distribute");
RecodeModel model = new RecodeModel(serial, sort, amount, distribute);
return model;
} catch (JSONException e) {
e.printStackTrace();
return null;
}
}
public String getSerial() {
return serial;
}
public String getSort() {
return sort;
}
public int getAmount() {
return amount;
}
public int getDistribute() {
return distribute;
}
}
此时我们有两种方式来创建RecodeModel,一种是通过构造方法创建,第二种通过parseJson方法创建。对于Model类,我们应该限制创建方式从而增加代码的可维护性。所以我们需要对RecodeModel的创建方式进行精简。构造方法初始化是为了方便之前RecodeRevert#parseJson中数据的赋值,既然现在parseJson方法已经在RecodeModel中了,就应该删掉该构造方法。同时,我们将RecodeModel的默认构造方法修改为private,只有在RecodeModel内部才可以通过默认构造方法创建自己。修改后代码如下:
public class RecodeModel {
private String serial;
private String sort;
private int amount;
private int distribute;
public static RecodeModel parseJson(JSONObject obj) {
try {
RecodeModel model = new RecodeModel();
String serial = obj.getString("serial");
String sort = obj.getString("sort");
int amount = obj.getInt("amount");
int distribute = obj.getInt("distribute");
model.serial = serial;
model.sort = sort;
model.amount = amount;
model.distribute = distribute;
return model;
} catch (JSONException e) {
e.printStackTrace();
return null;
}
}
public String getSerial() {
return serial;
}
public String getSort() {
return sort;
}
public int getAmount() {
return amount;
}
public int getDistribute() {
return distribute;
}
}
此时完成了重构,但对调用者来说parseJson方法名存在歧义,因为该方法是创建Model,所以需要修改方法名,使代码的含义更明确。然后可以删除代码中的变量,直接为model赋值,代码修改后如下:
public class RecodeModel {
private String serial;
private String sort;
private int amount;
private int distribute;
public static RecodeModel createFromJson(JSONObject obj) {
try {
RecodeModel model = new RecodeModel();
model.serial = obj.getString("serial");
model.sort = obj.getString("sort");
model.amount = obj.getInt("amount");
model.distribute = obj.getInt("distribute");
return model;
} catch (JSONException e) {
e.printStackTrace();
return null;
}
}
public String getSerial() {
return serial;
}
public String getSort() {
return sort;
}
public int getAmount() {
return amount;
}
public int getDistribute() {
return distribute;
}
}
然后修改创建RecodeModel的代码
public void insertRecordWithJSONArray(JSONArray array) {
if (array == null || array.length() == 0) {
return;
}
SQLiteDatabase db = null;
try {
db = getWritableDatabase();
db.beginTransaction();
for (int i = 0; i < array.length(); i++) {
JSONObject obj = array.getJSONObject(i);
RecodeModel mode = RecodeModel.createFromJson(obj);
ContentValues values = new ContentValues();
values.put(RecordTable.COLUMN_SERIAL, mode.getSerial());
values.put(RecordTable.COLUMN_AMOUNT, mode.getAmount());
values.put(RecordTable.COLUMN_SORT, mode.getSort());
values.put(RecordTable.COLUMN_DISTRIB, mode.getDistribute());
db.insert(RecordTable.TABLE_NAME, null, values);
}
db.setTransactionSuccessful();
db.endTransaction();
} catch (Exception e) {
e.printStackTrace();
} finally {
closeDatabase(db);
}
}