Android动态创建表格 .

来源:互联网 发布:杜月笙 知乎 编辑:程序博客网 时间:2024/06/14 19:04

 

一、摘要

     最近接触到Android开发,由于涉及到Android和服务器端要发送http请求,服务器端通过查表,可以得到结果集(ResultSet),在服务器端,将结果集封装成json对象,以字符串的形式响应给Android端。Android端则需要将对应的字符串再进行一次解析,形成json字符串。然后利用json字符串再在页面动态生成一张表格。这就是大致需要完成的项目中一个环节,下面将上述自己做的过程详细写出来。

    

二、Android发送http请求封装

    这里,我借用网友的代码,他的post请求参数封装非常完善,以servlet为服务器语言为例,发送http请求源代码如下:

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. String uri = "http://192.168.191.1:8080/LYunMIS/servlet/ProcessStorageList";  
  2.         Map<String, String> params = new HashMap<String, String>();  
  3.         params.put("operator""select");  
  4.         params.put("tablename", Constant.Tbl_ProductStorage);//表名  
  5.         params.put("NowAdmStatus""0");//查询条件  
  6.         String responseStr = URLUtil.submitPostData(params, Constant.UTF8, uri);  
  7. URLUtil.java  
  8. public class URLUtil {  
  9.   
  10.     public static HttpURLConnection createConn(String uri,String type,String charset) {  
  11.         URL url = null;  
  12.         HttpURLConnection urlConn = null;  
  13.         try {  
  14.             url = new URL(uri);  
  15.             urlConn = (HttpURLConnection) url.openConnection();  
  16.             urlConn.setDoInput(true);//设置输入流采用字节流  
  17.             urlConn.setDoOutput(true);  
  18.             urlConn.setRequestMethod(type);//请求方式为POST  
  19.             urlConn.setUseCaches(false);//不起用缓存  
  20.             urlConn.setRequestProperty("Content-Type""application/x-www-form-urlencoded");//设置meta参数  
  21.             urlConn.setRequestProperty("Charset", charset);  
  22.               
  23.         } catch (MalformedURLException e) {  
  24.             e.printStackTrace();  
  25.         } catch (ProtocolException e) {  
  26.             e.printStackTrace();  
  27.         } catch (IOException e) {  
  28.             e.printStackTrace();  
  29.         }  
  30.         return urlConn;  
  31.           
  32.     }  
  33.       
  34.     public static String submitPostData(Map<String, String> params, String encode, String uri) {  
  35.         byte[] data = getRequestData(params, encode).toString().getBytes();//获得请求体  
  36.         try {              
  37.             URL url = new URL(uri);  
  38.             HttpURLConnection httpURLConnection = (HttpURLConnection)url.openConnection();  
  39.             httpURLConnection.setConnectTimeout(3000);          //设置连接超时时间  
  40.             httpURLConnection.setDoInput(true);                  //打开输入流,以便从服务器获取数据  
  41.             httpURLConnection.setDoOutput(true);                 //打开输出流,以便向服务器提交数据  
  42.             httpURLConnection.setRequestMethod("POST");     //设置以Post方式提交数据  
  43.             httpURLConnection.setUseCaches(false);               //使用Post方式不能使用缓存  
  44.             //设置请求体的类型是文本类型   
  45.             httpURLConnection.setRequestProperty("Content-Type""application/x-www-form-urlencoded");  
  46.             //设置请求体的长度   
  47.             httpURLConnection.setRequestProperty("Content-Length", String.valueOf(data.length));  
  48.             //获得输出流,向服务器写入数据   
  49.             OutputStream outputStream = httpURLConnection.getOutputStream();  
  50.             outputStream.write(data);  
  51.               
  52.             int response = httpURLConnection.getResponseCode();            //获得服务器的响应码  
  53.             if(response == HttpURLConnection.HTTP_OK) {  
  54.                 InputStream inptStream = httpURLConnection.getInputStream();  
  55.                 return dealResponseResult(inptStream);                     //处理服务器的响应结果  
  56.             }  
  57.         } catch (IOException e) {  
  58.             e.printStackTrace();  
  59.         }  
  60.         return "";  
  61.     }  
  62.       
  63.     /* 
  64.      * Function  :   封装请求体信息 
  65.      * Param     :   params请求体内容,encode编码格式 
  66.      */  
  67.     public static StringBuffer getRequestData(Map<String, String> params, String encode) {  
  68.         StringBuffer stringBuffer = new StringBuffer();        //存储封装好的请求体信息  
  69.         try {  
  70.             for(Map.Entry<String, String> entry : params.entrySet()) {  
  71.                 stringBuffer.append(entry.getKey())  
  72.                             .append("=")  
  73.                             .append(URLEncoder.encode(entry.getValue(), encode))  
  74.                             .append("&");  
  75.             }  
  76.             stringBuffer.deleteCharAt(stringBuffer.length() - 1);    //删除最后的一个"&"  
  77.         } catch (Exception e) {  
  78.             e.printStackTrace();  
  79.         }  
  80.         return stringBuffer;  
  81.     }  
  82.       
  83.     /* 
  84.      * Function  :   处理服务器的响应结果(将输入流转化成字符串) 
  85.      * Param     :   inputStream服务器的响应输入流 
  86.      */  
  87.     public static String dealResponseResult(InputStream inputStream) throws UnsupportedEncodingException {  
  88.         String resultData = null;      //存储处理结果  
  89.         ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();  
  90.         byte[] data = new byte[1024];  
  91.         int len = 0;  
  92.         try {  
  93.             while((len = inputStream.read(data)) != -1) {  
  94.                 byteArrayOutputStream.write(data, 0, len);  
  95.             }  
  96.         } catch (IOException e) {  
  97.             e.printStackTrace();  
  98.         }  
  99.         resultData = new String(byteArrayOutputStream.toByteArray(),"UTF-8");   //设置UTF-8编码,保持编码格式一致否则会出现乱码   
  100.         return resultData;  
  101.     }  
  102. }  

    servlet这段的业务的处理与写servlet处理B/S浏览器端的处理类似,主要用到PrintWriter对象的print方法向Android传递字符串,字符串以何种方式传递效率较高呢?当然,对于一般的长度较短的字符串,可以直接进行解析。但如果是一个表的数千万行数据,自己解析效率就会相当低,而且对编写两层间通信接口造成相当大的维护难度。

  目前,对于java有两种比较成熟的方式,xml和json解析。这里介绍一下,json的封装和解析。

三、json的封装和解析

 

     从数据库查询一条或多条记录,jdbc将会得到一个结果集ResultSet,如果查询的记录为0条,封装的json为"[]".

 

     Result封装称jsonArray的方法

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. public static JSONArray ResultSetToJsonArray(ResultSet rs) throws SQLException, JSONException {  
  2.         //获取列数   
  3.         ResultSetMetaData md = rs.getMetaData();  
  4.         int columnCount = md.getColumnCount();  
  5.         //json数组   
  6.         JSONArray array = new JSONArray();  
  7.           
  8.         while (rs.next()) {  
  9.             JSONObject jsonObj = new JSONObject();  
  10.             for (int i = 1; i <= columnCount; i++) {  
  11.                 String columnName = md.getColumnLabel(i);  
  12.                 Object obj = rs.getObject(columnName);  
  13. //              String value = rs.getString(columnCount);  
  14.                 jsonObj.put(columnName, obj);  
  15.             }  
  16.             array.put(jsonObj);  
  17.         }  
  18.         return array;  
  19.     }  

得到了jsonArray对象,就可以将它以字符串的形式向Android端发送数据,Android端接收到的是json字符串,如何进行解析呢?

Android已经有专门的类为我们解析做好了准备了。

      如果明确得到的是jsonArray字符串:JSONArrayjsonArray = new JSONArray(str);

      而如果是jsonObject字符串:JSONObjectjsonObj = new JSONObject(str);

      有了jsonArray或者jsonObjet我们就可以动态创建表格了

四、Android动态创建表格

      动态创建表格需要自己来写相应的表格的实现类,这里借助网友的实现TableRow和TableCell代码如下:

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. /**  
  2.  * TableRow 实现表格的行  
  3.  */   
  4. public class TableRow {  
  5.     private TableCell[] cell;     
  6.     public TableRow(TableCell[] cell) {     
  7.         this.cell = cell;     
  8.     }     
  9.     public int getSize() {     
  10.         return cell.length;     
  11.     }     
  12.     public TableCell getCellValue(int index) {     
  13.         if (index >= cell.length)     
  14.             return null;     
  15.         return cell[index];     
  16.     }     
  17. }  
  18. /**  
  19.  * TableCell 实现表格的格单元  
  20.  * @author hellogv  
  21.  */     
  22. public class TableCell {     
  23.     static public final int STRING = 0;     
  24.     static public final int IMAGE = 1;     
  25.     public Object value;     
  26.     public int width;     
  27.     public int height;     
  28.     public int type;     
  29.     public TableCell(Object value, int width, int height, int type) {     
  30.         this.value = value;     
  31.         this.width = width;     
  32.         this.height = height;     
  33.         this.type = type;     
  34.     }     
  35. }    
 有了表格的行和单元格,我们就大致可以些添加数据的代码了,添加jsonArray的方法:
[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. public static List<TableRow> addData(int width,String jsonArray,String[] columnsKey,String[] columnsHead) {  
  2.         List<TableRow> table = new ArrayList<TableRow>();     
  3.         TableCell[] titles = new TableCell[columnsHead.length];// 每行4个单元   
  4.         try{  
  5.   
  6.             // 定义标题       
  7.             for (int i = 0; i < titles.length; i++) {     
  8.                 titles[i] = new TableCell(columnsHead[i],      
  9.                                         width,     
  10.                                         LayoutParams.MATCH_PARENT,      
  11.                                         TableCell.STRING);     
  12.             }  
  13.             table.add(new TableRow(titles));   
  14.             List<String[]> tables = JsonUtil.parseJsonArray(jsonArray, columnsKey);  
  15.             for (int i = 0; i < tables.size(); i++) {  
  16.                 TableCell[] cols = new TableCell[columnsKey.length];// 每行4个单元   
  17.                 String[] contents = tables.get(i);  
  18.                 for(int j = 0;j < contents.length;j++) {  
  19.                     cols[j] = new TableCell(contents[j], width, LayoutParams.MATCH_PARENT, TableCell.STRING);  
  20.                 }  
  21.                 table.add(new TableRow(cols));  
  22.             }  
  23.         }catch(Exception e) {  
  24.             Log.d("添加表格异常""Error:", e);  
  25.         }  
  26.         return table;  
  27.     }  

参数说明:jsonArray是对应的jsonArray字符串,columnsKey则是查询结果中的字段名也即key,columnsHead是表头,可以自己自定义为中文。

       有时候,也会将一条数据显示在一个表格中,同样借助上面的方式,可以自己改写,实现代码如下:

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. public static List<TableRow> addSingleRecord(int width,String jsonObjStr,String[] columnKey,String[] columnHead) {  
  2.         List<TableRow> table = new ArrayList<TableRow>();     
  3.         try{  
  4.             TableCell[] titles = new TableCell[2];// 每行2个单元   
  5.             titles[0] = new TableCell("字段名",      
  6.                                         width,     
  7.                                         LayoutParams.MATCH_PARENT,      
  8.                                         TableCell.STRING);    
  9.             titles[1] = new TableCell("字段值",      
  10.                         width,     
  11.                         LayoutParams.MATCH_PARENT,      
  12.                         TableCell.STRING);    
  13.             table.add(new TableRow(titles));   
  14.             int size = columnHead.length;  
  15.             JSONObject jsonObj = new JSONObject(jsonObjStr);  
  16.             for (int i = 0; i < size; i++) {  
  17.                 TableCell[] body = new TableCell[2];// 每行2个单元   
  18.                 Object col = jsonObj.get(columnKey[i]);  
  19.                 body[0] = new TableCell(columnHead[i], width, LayoutParams.MATCH_PARENT, TableCell.STRING);  
  20.                 body[1] = new TableCell(col, width, LayoutParams.MATCH_PARENT, TableCell.STRING);  
  21.                 table.add(new TableRow(body));  
  22.             }  
  23.         }catch(Exception e) {  
  24.             Log.d("添加表格异常""Error:", e);  
  25.         }  
  26.         return table;  
  27.     }  

这里就不贴图了,内容比较多,对需要的朋友应该会有很大的帮助。

仅仅有上面这些还不够,真正要将数据添加到页面,还需要一个table的适配器,它是继承自BaseAdatper

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. public class TableAdapter extends BaseAdapter {  
  2.   
  3.     private Context context;     
  4.     private List<TableRow> table;     
  5.     public TableAdapter(Context context, List<TableRow> table) {     
  6.         this.context = context;     
  7.         this.table = table;     
  8.     }     
  9.   
  10.     @Override  
  11.     public int getCount() {  
  12.         return table.size();  
  13.     }  
  14.   
  15.     @Override  
  16.     public long getItemId(int arg0) {  
  17.         return arg0;  
  18.     }  
  19.   
  20.     @Override  
  21.     public View getView(int arg0, View arg1, ViewGroup arg2) {  
  22.         TableRow tableRow = table.get(arg0);     
  23.         return new TableRowView(this.context, tableRow,arg0);   
  24.     }  
  25.   
  26.     @Override  
  27.     public Object getItem(int arg0) {  
  28.         return arg0;  
  29.     }  
  30.   
  31. }  

这些实现代码都帮助我们实现了,将数据真正添加到table已不是问题

五、Activity中添加数据

      list_process_storage为页面的ListView对象

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. List<TableRow> table;//声明为全局变量,供之后单条记录使用  
  2. table = TableUtil.addData(width, responseStr, TableUtil.Tbl_ProductStorage,TableUtil.Tbl_ProductStorage_zh);  
  3.         TableAdapter tableAdapter = new TableAdapter(this, table);     
  4.         list_process_storage.setAdapter(tableAdapter);  
  5.         list_process_storage.setOnItemClickListener(new ItemClickEvent());  
 通常还有这样的需求,得到了整个表,我们还需要得到其中某一条记录的具体内容,就在相应的ListView中添加单击事件

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. class ItemClickEvent implements OnItemClickListener {  
  2.           
  3.         @Override  
  4.         public void onItemClick(AdapterView<?> listView, View v, int position, long arg3) {  
  5.             if(position == 0return;//点击表头不跳转  
  6. //          TableRowView tableRowView = (TableRowView) v;  
  7. //          TextView teView = (TextView) tableRowView.getChildAt(0);  
  8.             //再将teView中的值在json中找到,跳转到确认状态页面  
  9. //          TableRow row = table.get(position);  
  10. //          Toast.makeText(DesignCommittingMtTblActivity.this,row.getCellValue(0).value.toString(),Toast.LENGTH_LONG).show();  
  11.             try {  
  12.                 JSONArray jsonArray = new JSONArray(arrayStr);  
  13.                 JSONObject jsonObj = jsonArray.getJSONObject(position - 1);  
  14.                 Intent intent = new Intent();  
  15.                 intent.setClass(ProcessStorageActivity.this, ProcessStorageSingleActivity.class);  
  16.                 intent.putExtra("single", jsonObj.toString());  
  17.                 intent.putExtra("enable"true);  
  18.                 startActivityForResult(intent, 0);  
  19.             } catch (JSONException e) {  
  20.                 e.printStackTrace();  
  21.             }  
  22.         }  
  23.     }  

注意:别小看注释部分,可能就是这里的细节对你有用!

漏了一点内容,多亏网友提醒,现加到后面

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. public class TableRowView extends LinearLayout {    
  2.       
  3.     public TableRowView(Context context, TableRow tableRow,int odd) {     
  4.         super(context);     
  5.              
  6.         this.setOrientation(LinearLayout.HORIZONTAL);     
  7.         for (int i = 0; i < tableRow.getSize(); i++) {//逐个格单元添加到行      
  8.             TableCell tableCell = tableRow.getCellValue(i);     
  9.             LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(     
  10.                     tableCell.width, tableCell.height);//按照格单元指定的大小设置空间      
  11.             layoutParams.setMargins(1111);//预留空隙制造边框      
  12.             if (tableCell.type == TableCell.STRING) {//如果格单元是文本内容      
  13.                 TextView textCell = new TextView(context);     
  14.                 textCell.setLines(1);     
  15.                 textCell.setGravity(Gravity.CENTER);     
  16.                 if(odd % 2 == 0)  
  17.                     textCell.setBackgroundColor(Color.GREEN);//背景   灰色  
  18.                 else   
  19.                     textCell.setBackgroundColor(Color.WHITE);//背景   白色  
  20.                 textCell.setText(String.valueOf(tableCell.value));     
  21.                 addView(textCell, layoutParams);     
  22.             } else if (tableCell.type == TableCell.IMAGE) {//如果格单元是图像内容      
  23.                 ImageView imgCell = new ImageView(context);     
  24.                 imgCell.setBackgroundColor(Color.WHITE);//背景灰色      
  25.                 imgCell.setImageResource((Integer) tableCell.value);     
  26.                 addView(imgCell, layoutParams);     
  27.             }     
  28.         }     
  29.         this.setBackgroundColor(Color.BLUE);//背景白色,利用空隙来实现边框      
  30.     }     
  31. }     


 




0 0