谷歌在安卓上提供了一个序列化接口——Parcelable,它表示比java传统的序列化接口效率更高,然而现实是它不是自动化的,所以它的效果是很坑爹的——要重写很多代码。
于是在安卓studio上,大神就开发了一个基于注解式的插件。。。然而,我对@@@@@很感冒。。。于是自己编写的一个java swing窗体小程序,可以为实体类快速生成实现了Parcelable接口的代码。
通过各种正则表达式,各种折腾,各种解析最终实现。
最后java swing程序运行结果如下:
ok,将生成的代码复制到项目中。。。
以下是解析并生成Parcelable接口代码的部分:
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class FactoryCore {
//java命名规范
private static final String regexName = "[a-zA-z_$]{1,}[0-9]*[a-zA-z_$]*";
private static final String regexFiel = "([^ \n\r]*)[ ]{1,}("+ regexName+")[ ]*;";
private static final String regexClass = "class[ ]*("+regexName+")(.*\\{)";
private static final String regexInterface = "implements(.*)\\{";
private CharSequence interFaceInfoString;
private ArrayList<String> fielList;
private String classString;
private String[] interFaceStrings;
private ArrayList<String> typeList;
// private
public String formatString(String str) throws Exception{
StringBuilder sb = new StringBuilder();
formatClassName(str);
formatInterFaceName();
formatFielName(str);
sb.append(makeContent(str));
sb.append(makeRead());
sb.append(makeWrite());
sb.append("\n}");
// System.out.println(sb);
return sb.toString();
}
/**验证括号{}是否成双
*/
private boolean verificateBrackets(String str){
char[] chs = str.toCharArray();
int bracket_left = 0;
int bracket_right = 0;
int indextLeft = 0;
int indextRight = 0;
for (int i = 0; i < chs.length; i++) {
char c = chs[i];
if (c=='{') {
bracket_left++;
indextLeft = i;
}
if(c=='}'){
bracket_right++;
indextRight = i;
}
}
if (bracket_left == bracket_right && indextRight>indextLeft) {
return true;
}
return false;
}
private StringBuilder makeContent(String str){
StringBuilder sb = new StringBuilder();
int cl = str.indexOf("class");
sb.append(str.substring(0,cl));
sb.append("class "+classString);
if (interFaceStrings!=null&&interFaceStrings.length>0) {
sb.append(" implements Parcelable");
for (int i = 0; i < interFaceStrings.length; i++) {
String string = interFaceStrings[i];
if (!string.equals("Parcelable")) {
sb.append(string);
}
}
}
boolean fla = verificateBrackets(str);
int lastIndext =0;
if (fla) {
lastIndext = str.lastIndexOf("}");
}else {
lastIndext = str.length();
}
String s = str.substring(str.indexOf("{"),lastIndext);
sb.append(s);
sb.append("\n @Override \n public int describeContents() {\n return 0;\n}"
+"\n public static final Parcelable.Creator<"
+classString
+"> CREATOR = new Parcelable.Creator<"
+classString
+ ">() { "
+"\n public "
+classString
+ " createFromParcel(Parcel in) {"
+"\n return new "+classString+"(in);\n}"
+"\n public "
+classString
+ "[] newArray(int size) { "
+"\n return new "
+classString
+ "[size]; \n}\n};"
);
return sb;
}
private StringBuilder makeWrite(){
StringBuilder sb = new StringBuilder();
sb.append("\n @Override\n public void writeToParcel(Parcel dest, int flags) {\n");
for (int i = 0; i < typeList.size(); i++) {
String type = typeList.get(i);
String fiel = fielList.get(i);
sb.append("\n dest.write" );
switch (type) {
case "byte" :
sb.append("Byte");
break;
case "byte[]" :
sb.append("ByteArray");
break;
case "short" :
case "char" :
case "int" :
sb.append("Int");
break;
case "short[]":
case "char[]":
case "int[]":
sb.append("IntArray");
break;
case "long" :
sb.append("Long");
break;
case "long[]" :
sb.append("LongArray");
break;
case "String" :
sb.append("String");
break;
case "String[]" :
sb.append("StringArray");
break;
case "boolean" :
sb.append("Boolean");
break;
case "boolean[]" :
sb.append("BooleanArray");
break;
case "double" :
sb.append("Double");
break;
case "double[]" :
sb.append("DoubleArray");
break;
case "float" :
sb.append("Float");
break;
case "float[]" :
sb.append("FloatArray");
break;
case "Bundle" :
sb.append("Bundle");
break;
case "Exception" :
sb.append("Exception");
break;
case "ParcelFileDescriptor" :
sb.append("FileDescriptor");
break;
case "IBinder" :
sb.append("StrongBinder");
break;
default :
sb.append("Object");
break;
}
sb.append("("+fiel+");");
}
sb.append("\n }");
return sb;
}
private StringBuilder makeRead(){
StringBuilder sb = new StringBuilder();
sb.append("\n private "
+classString
+ "(Parcel in) { "
);
boolean flag = false;
for (int i = 0; i < typeList.size(); i++) {
String type = typeList.get(i);
String fiel = fielList.get(i);
sb.append("\n "+fiel +" = in.read" );
switch (type) {
case "byte" :
sb.append("Byte");
break;
case "byte[]" :
flag = true;
sb.append("ByteArray");
break;
case "short" :
case "char" :
case "int" :
sb.append("Int");
break;
case "short[]":
case "char[]":
case "int[]":
flag = true;
sb.append("IntArray");
break;
case "long" :
sb.append("Long");
break;
case "long[]" :
flag = true;
sb.append("LongArray");
break;
case "String" :
sb.append("String");
break;
case "String[]" :
flag = true;
sb.append("StringArray");
break;
case "boolean" :
sb.append("Boolean");
break;
case "boolean[]" :
flag = true;
sb.append("BooleanArray");
break;
case "double" :
sb.append("Double");
break;
case "double[]" :
flag = true;
sb.append("DoubleArray");
break;
case "float" :
sb.append("Float");
break;
case "float[]" :
flag = true;
sb.append("FloatArray");
break;
case "Bundle" :
sb.append("Bundle");
break;
case "Exception" :
sb.append("Exception");
break;
case "ParcelFileDescriptor" :
sb.append("FileDescriptor");
break;
case "IBinder" :
sb.append("StrongBinder");
break;
default :
sb.append("Object");
break;
}
if (flag) {
sb.append("("+fiel+");");
flag = false;
}else{
sb.append("();");
}
}
sb.append("\n}");
return sb;
}
public String getClassString() {
return classString;
}
public ArrayList<String> getFielList() {
return fielList;
}
public String[] getInterFaceNames() {
return interFaceStrings;
}
private void formatClassName(String str) throws Exception{
String className="";
Pattern pattern = Pattern.compile(regexClass);
Matcher matcher = pattern.matcher(str);
if(matcher.find(0)){
className = matcher.group(1);
// System.out.println(className);
interFaceInfoString = matcher.group(2);
}else{
throw new Exception("Class String have problems");
}
classString = className;
}
private void formatInterFaceName() throws Exception{
Pattern pattern = Pattern.compile(regexInterface);
Matcher matcher = pattern.matcher(interFaceInfoString);
String[] ifs=null;
Pattern p = Pattern.compile(regexName);
if(matcher.find()){
String s = matcher.group(1).replace(" ", "");
if (s.endsWith(",")) {
throw new Exception("Interface String have problems");
}
ifs = s.split(",");
for (int i = 0; i < ifs.length; i++) {
String string = ifs[i];
Matcher m = p.matcher(string);
if(!m.find()){
throw new Exception("Interface String have problems");
}
System.out.println(string);
}
}
interFaceStrings = ifs;
}
private void formatFielName(String str){
if(fielList==null){
fielList = new ArrayList<String>();
}else {
fielList.clear();
}
if (typeList == null) {
typeList = new ArrayList<String>();
}else {
typeList.clear();
}
Pattern pattern = Pattern.compile(regexFiel);
Matcher matcher = pattern.matcher(str);
// matcher.reset(str);
while (matcher.find()) {
String a = matcher.group(1);
String b = matcher.group(2);
typeList.add(a);
fielList.add(b);
// System.out.println(a+" "+b);
}
}
}
以下是java窗体部分:
package com.yue.ui;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.TextArea;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class MainWindow extends JFrame implements ActionListener{
private static final long serialVersionUID = -5462191167405612649L;
private Dimension screenSize;
private int panelCount;
private ArrayList<JPanel> panels;
private JLabel label;
private CardLayout cardLayout;
private JPanel panel_text;
private FactoryCore factoryCore;
public MainWindow() {
}
public MainWindow(String title) {
setTitle(title);
}
protected void onCreate(){
setResizable(false);
factoryCore = new FactoryCore();
String title = getTitle();
if (null==title||title.equals("")) {
setTitle(this.getClass().getName());
}
int w = (int) (getScreenWidth()*(0.85));
int h = (int) (getScreenHeight()*(0.85));
System.out.println(w+""+h);
setSize(w, h);
setLayout(null);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
if (panels==null) {
panels = new ArrayList<JPanel>();
}
if (panelCount>0) {
currentCard = 1;
}
for (int i = 0; i < panelCount; i++) {
JPanel panel = new JPanel();
panels.add(panel);
}
}
protected void onCreateView(Container contentView){
setContentPane(contentView);
contentView.setLayout(new BorderLayout(0, 0));
FlowLayout flowLayout = new FlowLayout();
JPanel selectP = new JPanel(flowLayout);
flowLayout.setHgap(10);
label = new JLabel(currentCard+"");
Button btn_previous = new Button("上一个");
Button btn_next = new Button("下一个");
Button btn_ok = new Button("确定");
selectP.add(btn_previous);
selectP.add(label);
selectP.add(btn_next);
selectP.add(btn_ok);
int w = getWidth();
int h = getHeight();
cardLayout = new CardLayout(30, 5);
panel_text = new JPanel(cardLayout);
for (int i = 0; i < panels.size(); i++) {
JPanel panel = panels.get(i);
panel.setBounds(0, 0, w, h);
panel.setLayout(null);
TextArea textAreaLeft = new TextArea();
textAreaLeft.setName("text_left");
textAreaLeft.setBounds(0, 0, (int)(0.9*w/2), (int) (0.9*panel.getHeight()));
textAreaLeft.setFont(font);
TextArea textAreaRight = new TextArea();
textAreaRight.setBounds((int)(0.975*w/2), 0, (int)(0.9*w/2), (int) (0.9*panel.getHeight()));
textAreaRight.setName("text_right");
textAreaRight.setFont(font);
textAreaRight.setForeground(rightFColor);
textAreaRight.setBackground(new Color(80,75,75));
panel.add(textAreaLeft);
panel.add(textAreaRight);
panel_text.add(panel);
}
btn_previous.setActionCommand("previous");
btn_next.setActionCommand("next");
btn_ok.setActionCommand("ok");
btn_previous.addActionListener(this);
btn_next.addActionListener(this);
btn_ok.addActionListener(this);
contentView.add(panel_text, BorderLayout.CENTER);
contentView.add(selectP,BorderLayout.NORTH);
}
public void setPanelCount(int panelCount){
this.panelCount = panelCount;
}
public int getPanelCount() {
return panels.size();
}
public void showWindow(){
onCreate();
onCreateView(new Container());
setVisible(true);
}
public Dimension getScreenSize(){
if (null==screenSize) {
screenSize = Toolkit.getDefaultToolkit().getScreenSize();
}
return screenSize;
}
public int getScreenWidth(){
return getScreenSize().width;
}
public int getScreenHeight(){
return getScreenSize().height;
}
@Override
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
if(null==command){
return;
}
if(command.equals("previous")){
previousCard();
}
else if (command.equals("next")) {
nextCard();
}
else if(command.equals("ok")){
doOk();
}
}
int currentCard = 0;
private void previousCard() {
currentCard = (currentCard>1)?(currentCard-1):panelCount;
label.setText(currentCard+"");
cardLayout.previous(panel_text);
}
private void nextCard(){
currentCard = (currentCard<panelCount)?(currentCard+1):1;
label.setText(currentCard+"");
cardLayout.next(panel_text);
}
private void doOk(){
JPanel p = panels.get(currentCard-1);
TextArea textAreaRight = null;
TextArea textAreaLeft = null;
int count = p.getComponentCount();
for (int i = 0; i < count; i++) {
Component comp = p.getComponent(i);
if ("text_left"==comp.getName()) {
textAreaLeft = (TextArea) comp;
}
if("text_right"==comp.getName()){
textAreaRight = (TextArea) comp;
}
}
String sb;
boolean eflag = false;
try {
sb = factoryCore.formatString(textAreaLeft.getText());
} catch (Exception e) {
sb = e.getMessage();
e.printStackTrace();
eflag = true;
}
if (eflag) {
textAreaRight.setForeground(new Color(230,0,0));
}else {
textAreaRight.setForeground(rightFColor);
}
textAreaRight.setText(sb);
}
private Color rightFColor = new Color(200,190,210);
private Font font = new Font("宋体", Font.TRUETYPE_FONT, 18);
}
程序入口部分:
package com.yue.ui;
public class Test {
public static void main(String[] args) {
// FactoryCore factoryCore = new FactoryCore();
// factoryCore.formatString("public class Notepad implements ss{"
// +" private int id ;"
// +"private long[] create$Time;"
// +"private long modifie_dTime;"
// +"private long uploadTime;"
// +"private String noteName;"
// +"private String noteType;"
// +"private int star;"
// +"private String title ;"
// +"private String summary;"
// +"private String content;"
// );
MainWindow mainWindow = new MainWindow("Parcelable代码生成");
mainWindow.setPanelCount(5);
mainWindow.showWindow();
}
}
最后,可运行的程序和程序项目代码如下:
资源下载