Android——使用Volley+fastJson在新线程中读取网络接口获取天气信息

一,关于Volley

其实最初对于网络数据的访问,我是没想到要用框架的,使用HttpURLConnection或者HttpGet or HttpPost都可以实现。但是why? why I have to use Volley?

  Before Volley:

class HttpURLConnection_post extends Thread{
		@Override
		public void run() {
			//设置请求的路径
			String strUrl="http://api.qingyunke.com/api.php";
			//
			//将请求的参数进行UTF-8编码,并转换成byte数组=
			try {
				String params="key="+URLEncoder.encode("free","UTF-8")+"appid="+URLEncoder.encode("0","UTF-8")+"msg="+URLEncoder.encode("天气梅州","UTF-8");
				byte[] postData=params.getBytes();
				//创建一个URL对象
				URL url=new URL(strUrl);
				//打开一个HttpURLConnection连接
				HttpURLConnection urlConn=(HttpURLConnection)url.openConnection();
				//设置连接超时的时间
				urlConn.setDoOutput(true);
				//在使用post请求的时候,设置不能使用缓存
				urlConn.setUseCaches(false);
				//设置该请求为post请求
				urlConn.setRequestMethod("POST");
				urlConn.setInstanceFollowRedirects(true);
				//配置请求content-type
				urlConn.setRequestProperty("Content-Type", "application/x-www-form-urlencode");
				//执行连接操作
				urlConn.connect();
				//发送请求的参数
				DataOutputStream dos=new DataOutputStream(urlConn.getOutputStream());
				dos.write(postData);
				dos.flush();
				dos.close();
				//若请求成功通过读取连接的数据流,则获取返回的数据
				if(urlConn.getResponseCode()==200){
					//显示
    	        	InputStreamReader isr = new InputStreamReader(urlConn.getInputStream(), "utf-8");
                    int i;
                    String strResult = "";
                    // read
                    while ((i = isr.read()) != -1) {
                    	strResult = strResult + (char) i;
                    }
                    isr.close();
    	        	textview=(TextView)findViewById(R.id.textview1);
    	        	textview.setText(strResult); //显示在textView中
				}else
				{
					textview.setText(urlConn.getResponseCode()); //显示在textView中
				}

			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}
    }

对于上面代码,我只能说只能将就着用。

  volley来源:

Volley 是 Google 推出的 Android 异步网络请求框架和图片加载框架。在 Google I/O 2013 大会上发布。

从名字由来和配图中无数急促的火箭可以看出 Volley 的特点:特别适合数据量小,通信频繁的网络操作。(个人认为 Android 应用中绝大多数的网络操作都属于这种类型)。

        主要特点:

(1). 扩展性强。Volley 中大多是基于接口的设计,可配置性强。
                 (2). 一定程度符合 Http 规范,包括返回 ResponseCode(2xx、3xx、4xx、5xx)的处理,请求头的处理,缓存机制的支持等。并支持重试及优先级定义。
                 (3). 默认 Android2.3 及以上基于 HttpURLConnection,2.3 以下基于 HttpClient 实现,这两者的区别及优劣在4.2.1 Volley中具体介绍。
                 (4). 提供简便的图片加载工具。

基于它有这么多的优点,而且比较官方正统,是在原始网络访问类的基础上的一个扩展及优化,所以,我们使用它来从网络中读写数据。

二,使用fastJson

安卓中的数据是以轻量高效的数据传输格式json作为载体的。所以,在安卓开发中,有很大一部分代码,我们是要对JSON字符串及对象或者集合进行转换的代码。

我们可以使用传统的JSONObject或者JSONArray:

 //创建一个对象
		 JSONObject person=new JSONObject();
		 //创建数组对象
		 JSONArray phone=new JSONArray();
		 phone.put("123445");
		 try {
			person.put("name", "lhc");
			person.put("age", 100);
			//创建一个对象
			JSONObject address=new JSONObject();
			address.put("country","china");
			address.put("province","hebei");
			person.put("address", address);

		//JSON文本的解析
			JSONObject object=new JSONObject(person.toString());
			JSONArray array=object.getJSONArray("phone");
			String phonenum=(String) array.get(0);
			String name=object.getString("name");
			int age=object.getInt("age");
			JSONObject object1=object.getJSONObject("address");
			String country=object1.getString("country");
			String province=object1.getString("province");

		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		

但是这种做法并不高效,因此,我们可以使用fastjson或者jackjson来实现这个过程的简单操作。

三,关于安卓的开启新线程及为什么要使用异步处理消息类

安卓系统的线程模型属于单线程模型,假如在非UI线程中去访问或者更新只能在UI线程中去更新的视图类就会报异常。但是很多耗时的操作又不能放在UI线程中,我们只能在主线程上start一个新线程,然后再新线程中放入我们的网络访问,IO访问等操作。

但是当我们取到数据之后,因为在非UI线程中是不允许更新UI的组件视图的,所以我们要使用异步处理的消息类去通知主线程,完成更新视图的操作。

三,简单Demo

首先是跟我的Json对应的实体类:

package com.example.demoproject;

public class WeatherInfo {

	private String result;//请求的结果
	private String content;//返回的内容
	public String getResult() {
		return result;
	}
	public void setResult(String result) {
		this.result = result;
	}
	public String getContent() {
		return content;
	}
	public void setContent(String content) {
		this.content = content;
	}

}

原json:

{

    "result": 0,
    "content": "★ 北京天气{br}霾,18℃,东北风2级{br}★ 三天预测{br}[10月06日] 白天:霾,25℃,无持续风向;夜晚:雾,15℃,无持续风向{br}[10月07日] 白天:阴,25℃,无持续风向;夜晚:晴,13℃,北风{br}[10月08日] 白天:晴,19℃,北风;夜晚:多云,9℃,无持续风向"
}

接着引用volley跟fastjson的jar包:

在AndroidManifest.xml中配置网络的访问权限:

<uses-permission android:name="android.permission.INTERNET"></uses-permission> 

Activity中代码:

package com.example.demoproject;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

import com.alibaba.fastjson.JSON;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.Request.Method;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.ActionBarActivity;
import android.widget.TextView;
public class MainActivity extends ActionBarActivity {

	 private static final int MSG_SUCCESS = 0;//获取天气信息成功的标识
	 private static final int MSG_FAILURE = 1;//获取天气信息失败的标识

	 private TextView textView;
	 /*
		 * 这里拿到的RequestQueue是一个请求队列对象,
		 * 它可以缓存所有的HTTP请求,然后按照一定的算法并发地发出这些请求。
		 * RequestQueue内部的设计就是非常合适高并发的,
		 * 因此我们不必为每一次HTTP请求都创建一个RequestQueue对象,
		 * 这是非常浪费资源的,基本上在每一个需要和网络交互的Activity中创建一个RequestQueue对象就足够了。
		 * */
	 private RequestQueue mQueue;
	 //用于更新UI线程的handler
	 private Handler mHandler=new Handler(){
		 //此方法在UI线程中执行
		@Override
		public void handleMessage(Message msg) {
			switch(msg.what){
				case MSG_SUCCESS:
					WeatherInfo weather=(WeatherInfo)msg.obj; //获取消息信息
					textView.setText(weather.getContent());
					break;
				case MSG_FAILURE:
					textView.setText("获取信息失败,请稍后重试");
					break;
			}
		}
	 };

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		textView=(TextView)findViewById(R.id.textview1);
		mQueue=Volley.newRequestQueue(MainActivity.this);
		new Thread(new WeatherTest()).start();//在新线程中读取数据并绑定
	}

	/*
	 * 读取天气数据使用的新线程
	 * 天气接口示例:
	 * 		http://api.qingyunke.com/api.php?key=free&appid=0&msg=天气北京
	 * */
	class WeatherTest implements Runnable{

			@Override
			public void run() {
				String strURL="http://api.qingyunke.com/api.php?key=free&appid=0&msg=";//请求数据的地址
				String strCity="";
				try {
					/*
					 * 注:volley中的参数必须进行编码,不然会出现乱码问题
					 * */
					strCity=URLEncoder.encode("天气北京","UTF-8");
				} catch (UnsupportedEncodingException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				strURL+=strCity;
				/*
				 * 使用Volley中封装的StringRequest对象来发送HTTP请求
				 * StringRequest需要三个参数:
				 * 		0,获取数据的方法
				 * 		1,目标服务器的URL地址
				 * 		2,服务器响应成功的回调
				 * 		3,服务器响应失败的回调
				 * */
			    StringRequest stringRequest = new StringRequest(Method.GET,strURL,
			                            new Response.Listener<String>() {
			                                @Override
			                                public void onResponse(String response) {
			                                	/*成功获取到数据之后的处理*/
			                                	WeatherInfo weatherInfo=null;
			                                	//将json串转为对象
			                                	weatherInfo=JSON.parseObject(response.toString(),WeatherInfo.class);
			                                	//绑定数据过程
			                                	mHandler.obtainMessage(MSG_SUCCESS,weatherInfo).sendToTarget();
			                                }
			                            }, new Response.ErrorListener() {
			                                @Override
			                                public void onErrorResponse(VolleyError error) {
			                                	//读取失败的处理
			                                	mHandler.obtainMessage(MSG_FAILURE).sendToTarget();
			                                }
			                            });
			    mQueue.add(stringRequest); //将请求添加到请求队列中
			}}
}

           



             JRKJ整体框架正在完善中,欢迎补充!

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-05 07:09:01

Android——使用Volley+fastJson在新线程中读取网络接口获取天气信息的相关文章

Android之Handler在新线程中读取网络的两种方法

方法一: 创建一个Thread,然后调用start方法. 实例: package com.example.android_handle; import java.io.BufferedInputStream; import java.io.InputStream; import java.net.URL; import java.net.URLConnection; import org.apache.http.util.ByteArrayBuffer; import android.app.A

Android新线程中更新主线程中的UI控件

Android中的View都不是线程安全的,所以如果在某一个新线程中直接更新主线程中的UI控件时就会报如下错误: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 为了解决在另一个线程中更新UI控件的问题,我们可以使用如下几种解决方案: 1. 自己写Handler解决,参见<And

Android开之在非UI线程中更新UI

当在非UI线程中更新UI(程序界面)时会出现如下图所示的异常: 那如何才能在非UI线程中更细UI呢? 方法有很多种,在这里主要介绍两种: 第一种:在需要更新UI的代码行后加Looper.prepare();与Looper.loop();两句话即可.如: new Thread(){ @Override public void run() { // TODO Auto-generated method stub txtRotation.setText("在非UI线程中更新UI!"); Lo

Swing中耗时任务需要另起新线程,这个新线程中更新GUI的操作仍需由EDT来做(转)

最近调试程序时发现,点击某个界面时会出现卡死的情况,出现的频率还是比较频繁的. 再次出现卡死的情况后,利用jvisualvm查看线程的运行情况,dump操作之后发现线程间出现了死锁:Found one Java-level deadlock:============================="Thread-122":  waiting to lock monitor 0x484052e4 (object 0x1af2bb08, a com.raisecom.ems.temple

Android&quot;挂逼&quot;修炼之行---微信中定位照片的位置信息插件开发详解

一.前言 最近关于微信中,朋友之间发送原图就可能暴露你的位置信息,其实这个问题不在于微信,微信是为了更好的体验效果,才有发送原图功能,而对于拍照,发送普通图片微信后台都会过滤图片的exif信息,这样就不会携带位置信息了.我们本身用手机自带的相机拍摄照片默认都是会在图片中添加位置信息的.当然我们也可以手动的关闭这个功能.这一点个人觉得不能怪微信.因为更好的逆向学习,和用户体验,本文将开发一套更加好用的插件,就是选择图片直接利用微信自带的地图功能,定位图片位置.这个过程会很麻烦.但是本文会逐一详细介

Web网站中利用JavaScript中ActiveXObject对象获取硬件信息(显示器数量、分辨率)从而进行单双屏跳转

前言:最近这两天工作上,要实现一个功能,在好友阿聪的帮助下,算是比较好的解决了这个需求. B/S的Web网站,需要实现点击按钮时,根据客户端连接的显示屏(监视器)数量进行,单双屏跳转显示新页面. 由于是Web网站,项目是要发布在服务端上,通过后台去读硬件信息,也是读到的是服务器的硬件信息. 故考虑用JS中的ActiveXObject对象,读取到硬件的显示器(监视器)信息,比如数量.分辨率. 此处使用ActiveXObject对象,由于项目限制用的是IE9,打开窗口用的是window.open()

Android之Volley框架在实际开发过程中运用

这个章节我们来讲下Volley在实际开发中如何正确地运用它.废话不说,进入正题. 集成 Volley 如果使用Android Studio开发的读者可以直接添加远程依赖: compile 'com.mcxiaoke.volley:library:1.0.19' 如果使用Ecplise开发的读者可以在lib中加入jar,可以自己通过源码进行打包成jar,我这里就直接给出Volley.jar资源了.点此下载Volley.jar Volley的Requst final TextView mTextVi

java中通过代码获取java信息,如虚拟机,版本,路径等等

package com.itm.path; public class TestSystemproperty{ public static void main(String[] args){ System.out.println("Java运行时环境版本:\n"+System.getProperty("java.version")); System.out.println("Java 运行时环境供应商:\n"+System.getProperty(

H264裸流分析中,能获取哪些信息?

从H264的裸流中,PPS,SPS中,一定可以获取到的,有图像的宽,高信息. 这部分信息的提取,用Stream eye 分析: 这里需要特别提一下这两个参数:  pic_width_in_mbs_minus1 = 119(1920)  pic_height_in_map_units_minus1 = 67(1088)分别表示图像的宽和高,以宏块(16x16)为单位的值减1因此,实际的宽为 (119+1)*16 = 352,高:(67+1)*16=1088 开始的时候,我还以为是哪里不对,1080