花了两天的时间完成了一个简单的小程序:服务器端从数据库封装json 数据,客户端解析json数据后用listview 显示,现在做一个简单的梳理。
一、服务器端从数据库中获取数据后封装成json数据:(服务器端编程)
连接数据库的过程就不上代码了,基本过程为:
加入数据库的驱动——>DriverManager.getConnection()——>封装sql语句在perparedStatement对象中(具体看具体实例的要求,可以查看api)——>执行perparedSatatement对象,返回ResultSet对象。
1.使用Java 反射机制将获得ResultSet数据放进List<T>,其中T是封装数据的类,放一个主要操作的代码:
这一条是根据我的需求写的,查询单条或增删操作也可以仿照这里,写齐了就是不错的数据库操作的工具类。
//泛型编程,通过反射机制查询多条数据
public <T> List<T> FindMoreData2(String sql,List<Object> params,Class<T> cls)throws Exception{
List<T> list=new ArrayList<T>();
ptmt=conn.prepareStatement(sql);
int index=1;
if(params!=null&&!params.isEmpty()){
for(int i=0;i<params.size();i++){
ptmt.setObject(index++,params.get(i));
}
}
resultSet=ptmt.executeQuery();
ResultSetMetaData rData=resultSet.getMetaData();
int col_num=rData.getColumnCount();
while(resultSet.next()){
T resultObject=cls.newInstance();
for(int i=1;i<col_num;i++){
String col_name=rData.getColumnName(i+1);
Object col_value=resultSet.getObject(col_name);
if(col_value==null) col_value="";
<span style="color:#ff0000;">Field field=cls.getDeclaredField(col_name);//根据类名找到domain 类 中的属性
field.setAccessible(true);
field.set(resultObject, col_value);</span>
}
list.add(resultObject);
}
return list;
}
2.反射机制注意要写一个可序列化的封装类,数据库表中的列名与成员变量相对应,这样方便进行封装操作。我使用的数据库中表如下,数据比较粗糙。
News.java如下,getter和setter 方法省略:
public class News implements Serializable {
private String iconUrl;
private String title;
private String content;
public News(String iconUrl, String title, String content) {
super();
this.iconUrl = iconUrl;
this.title = title;
this.content = content;
}
3.通过JsonObject方法封装成json数据,并以字符串的方式返回:
public static String createJsonString(String key,Object value){
//String jsonString=null;
JSONObject jsonobject=new JSONObject();
jsonobject.put(key, value);
return jsonobject.toString();
}
JsonObject方法可以去查看api。
4.建立一个servlert,在dopost()方法中调用createJsonString("News",list);
"News"类似于数组名一样的存在,在客户端需要根据它来获得数据;list 是我们通过查询数据库获得的数据封装成的List<News>.
二、客户端从网络获取数据并显示在listview中(Android编程)
1.从网络上获取数据的话,应该使用异步加载的方式,Android的单线程模式决定了耗时操作不能放在主线程中完成,避免阻塞主线程(一般是UI线程),出现ANR错误。
AsyncTask之前有做过整理,这里就不重复写了。
2.在AsyncTask中写在doInBackGround()中的主要的Json解析操作:
private List<NewsBean> getJsonData(String url) {//根据inputstream获取json格式的字符串
List<NewsBean> list=new ArrayList<>();
try {
String jsonstring=readStream(new URL(url).openStream());
JSONObject jsonObject;
NewsBean bean;
try {
jsonObject=new JSONObject(jsonstring);
JSONArray jsonArray=jsonObject.getJSONArray("persons");//这里要注意
for(int i=0;i<jsonArray.length();i++){
jsonObject=jsonArray.getJSONObject(i);
bean=new NewsBean();
bean.setNewsiconurl(jsonObject.getString("iconUrl"));//这里重写一遍
bean.setNewscontent(jsonObject.getString("content"));
bean.setNewstitle(jsonObject.getString("title"));
list.add(bean);
}
} catch (JSONException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
private String readStream(InputStream is){
InputStreamReader isr;
String result="";
try {
String line="";
isr=new InputStreamReader(is,"utf-8");
BufferedReader br=new BufferedReader(isr);
try {
while((line=br.readLine())!=null){
result+=line;
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return result;
}
上面的new URL(url).openStream()的操作就类似于:new URL(url).openConnection().getInputStream(),实现联网,并且返回inputstream.
readstream()函数是将输入的inputStream 按照utf-8的编码方式转换成字符串。
3.适配器NewsAdapter
public class NewsAdapter extends BaseAdapter implements AbsListView.OnScrollListener{
private List<NewsBean> mlist;
private LayoutInflater mlayoutInflater;
private ImageLoader imageLoader;//保证不出现多个cache
private int mStart,mEnd;//
public static String[] Urls;
private boolean mFirst;//用来判断是否是第一次启动
public NewsAdapter(Context context, List<NewsBean> data,ListView listView) {
mlist = data;
mlayoutInflater = LayoutInflater.from(context);
imageLoader=new ImageLoader(listView);
Urls=new String[data.size()];//创建数组,这里要加强练习
for (int i = 0; i < data.size(); i++) {
Urls[i]=data.get(i).getNewsiconurl();
}
mFirst=true;//第一次启动
listView.setOnScrollListener(this);//实现了监听器,一定要记得注册
}
@Override
public int getCount() {
return mlist.size();
}
@Override
public Object getItem(int position) {
return mlist.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder=null;
if(convertView==null){
viewHolder=new ViewHolder();
convertView=mlayoutInflater.inflate(R.layout.item,null);
viewHolder.im= (ImageView) convertView.findViewById(R.id.im_icon);
viewHolder.title= (TextView) convertView.findViewById(R.id.tv_title);
viewHolder.content= (TextView) convertView.findViewById(R.id.tv_content);
convertView.setTag(viewHolder);
}
else{
viewHolder= (ViewHolder) convertView.getTag();
}
viewHolder.im.setImageResource(R.mipmap.ic_launcher);
viewHolder.im.setTag(mlist.get(position).getNewsiconurl());//item图片出现错乱的原因是,list正确的item没有对应正确的url
imageLoader.ShowImageByAsyncask(viewHolder.im,mlist.get(position).getNewsiconurl());
viewHolder.content.setText(mlist.get(position).getNewscontent());
viewHolder.title.setText(mlist.get(position).getNewstitle());
return convertView;
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if(scrollState==SCROLL_STATE_IDLE){
//没有滚动项,开始加载
imageLoader.LoadImages(mStart,mEnd);//没有进行预加载
}else{
//停止加载
imageLoader.CancelAllTask();
}
}
/**
*
* @param view 可见视图
* @param firstVisibleItem 第一个可见元素
* @param visibleItemCount 可见元素数目
* @param totalItemCount list 中的总数
*/
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
mStart=firstVisibleItem;
mEnd=firstVisibleItem+visibleItemCount;
if(mFirst&&visibleItemCount>0){//当前列表第一次启动而且item已经绘出
imageLoader.LoadImages(mStart,mEnd);
mFirst=false;
}
}
class ViewHolder{//这是类,不要再加括号了!!!!
public TextView title,content;
public ImageView im;
}
}
4.因为需要根据URL获得服务器上的图片,另外再开一个线程去加载图片很重要,ImageLoader类中写了使用AsyncTask 的方法加载图片,并且更新了传递进来的imageview:
放一个根据url 获取图片的方法:
public Bitmap BitmapFromUrl(String url){
Bitmap bm=null;
InputStream is=null;
try {
HttpURLConnection hcn= (HttpURLConnection) new URL(url).openConnection();
is=new BufferedInputStream(hcn.getInputStream());
bm= BitmapFactory.decodeStream(is);
hcn.disconnect();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return bm;
}
还有一些小的细节换一篇文章写一下。