Android 解析json数据

    花了两天的时间完成了一个简单的小程序:服务器端从数据库封装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;
    }
还有一些小的细节换一篇文章写一下。




     

     

  

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值