目录结构
Weather.java
天气数据的抽象
package org.chitarra.tiny.myapplication.bean;
public class Weather {
private WeatherInfo weatherinfo;
public WeatherInfo getWeatherinfo() {
return weatherinfo;
}
public void setWeatherinfo(WeatherInfo weatherinfo) {
this.weatherinfo = weatherinfo;
}
public class WeatherInfo {
private String city;
private String temp;
private String time;
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getTemp() {
return temp;
}
public void setTemp(String temp) {
this.temp = temp;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
}
}
INetworkError.java
统一抛出网络的所有异常
package org.chitarra.tiny.myapplication.presenter;
public interface INetworkError {
void error(int errorCode);
}
IWeatherData.java
天气数据的接口
package org.chitarra.tiny.myapplication.presenter;
import org.chitarra.tiny.myapplication.bean.Weather;
public interface IWeatherData {
void weatherDate(Weather weather);
}
WeatherPresenter.java
获取天气数据,这里把业务逻辑写在了Presenter中,没有再写module
package org.chitarra.tiny.myapplication.presenter;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import org.chitarra.tiny.myapplication.service.GsonRequest;
import org.chitarra.tiny.myapplication.service.VolleySingleton;
import org.chitarra.tiny.myapplication.bean.Weather;
import java.util.HashMap;
import java.util.Map;
public class WeatherPresenter
{
VolleySingleton queue;
Map<String, String> map;
INetworkError networkErrorLister;
IWeatherData weatherDataLister;
public WeatherPresenter(final INetworkError networkErrorLister, final IWeatherData weatherDataLister, VolleySingleton queue)
{
this.networkErrorLister = networkErrorLister;
this.weatherDataLister = weatherDataLister;
this.queue = queue;
map = new HashMap<>();
map.put("key", "value");
GsonRequest<Weather> gsonRequest = new GsonRequest<Weather>(Request.Method.POST,
map,
"http://www.weather.com.cn/data/sk/101010100.html",
Weather.class,
new Response.Listener<Weather>()
{
@Override
public void onResponse(Weather weather)
{
weatherDataLister.weatherDate(weather);
}
},
new Response.ErrorListener()
{
@Override
public void onErrorResponse(VolleyError volleyError)
{
networkErrorLister.error(0x00);
}
});
queue.addRequestQueue(gsonRequest);
}
}
上面的post写法其实没有用到, 这个api是通过get请求的,只是为了实验这个写法对不对
在文章后面我会实验一下post请求, 获取服务器上的数据
GsonRequest.java
封装了一下Request
package org.chitarra.tiny.myapplication.service;
import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.toolbox.HttpHeaderParser;
import com.google.gson.Gson;
import java.io.UnsupportedEncodingException;
import java.util.Map;
public class GsonRequest<T> extends Request<T>
{
private Response.Listener<T> mListener;
private Map<String, String> mParams;
private Gson mGson;
private Class<T> mClass;
/**
* @param url
* @param clazz
* @param listener
* @param errorListener
*/
public GsonRequest(String url, Class<T> clazz, Response.Listener<T> listener,
Response.ErrorListener errorListener)
{
this(Method.GET, url, clazz, listener, errorListener);
}
@Override
protected Map<String, String> getParams() throws AuthFailureError
{
if (mParams != null)
{
return mParams;
}
return super.getParams();
}
public GsonRequest(int method, Map<String, String> params, String url, Class<T> clazz, Response.Listener listener, Response.ErrorListener errorListener)
{
this(Method.POST, url, clazz, listener, errorListener);
mParams = params;
}
/**
* @param method
* @param url
* @param clazz
* @param listener
* @param errorListener
*/
public GsonRequest(int method, String url, Class<T> clazz, Response.Listener listener, Response.ErrorListener errorListener)
{
super(method, url, errorListener);
this.mListener = listener;
this.mGson = new Gson();
this.mClass = clazz;
setTag(listener);
}
@Override
protected Response<T> parseNetworkResponse(NetworkResponse response)
{
try
{
String jsonString = new String(response.data, "utf-8");
return Response.success(mGson.fromJson(jsonString, mClass), HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e)
{
e.printStackTrace();
}
return null;
}
@Override
protected void deliverResponse(T response)
{
mListener.onResponse(response);
}
}
setTag(listener);使用在activity中调用取消请求队列的操作,tag使用了listener作为一个标记
VolleySingleton.java
用单利封装了一下Volley,这里有些疑问,Volley框架会把请求添加到队列中,然后一一去执行,同时我们也不需要为每一个请求都new一个volley的对象,所以我把它封装到了一个单例模式中,创建的时候参数的context传递的是getApplicationContext,保证所有请求都使用一个volley对象,所以我就这样去实现
package org.chitarra.tiny.myapplication.service;
import android.content.Context;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.Volley;
public class VolleySingleton
{
private static VolleySingleton ourInstance;
private RequestQueue mRequestQuene;
public static synchronized VolleySingleton getInstance(Context context)
{
if (ourInstance == null)
{
ourInstance = new VolleySingleton(context);
}
return ourInstance;
}
private VolleySingleton(Context context)
{
mRequestQuene = Volley.newRequestQueue(context);
}
public RequestQueue getRequestQuene()
{
return this.mRequestQuene;
}
public <T> void addRequestQueue(Request<T> request)
{
getRequestQuene().add(request);
}
public void cancelRequest(Object object)
{
getRequestQuene().cancelAll(object);
}
}
DemoActivity.java
在activity中,结合了mvp这么使用了volley
package org.chitarra.tiny.myapplication.view;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import org.chitarra.tiny.myapplication.R;
import org.chitarra.tiny.myapplication.service.VolleySingleton;
import org.chitarra.tiny.myapplication.bean.Weather;
import org.chitarra.tiny.myapplication.presenter.DemoImpl;
import org.chitarra.tiny.myapplication.presenter.INetworkError;
import org.chitarra.tiny.myapplication.presenter.IWeatherData;
import org.chitarra.tiny.myapplication.presenter.WeatherPresenter;
public class DemoActivity extends AppCompatActivity implements IWeatherData, INetworkError
{
VolleySingleton mNetworkQuene;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo);
mNetworkQuene = VolleySingleton.getInstance(getApplicationContext());
new WeatherPresenter(this, this, mNetworkQuene);
new DemoImpl(this);
}
@Override
public void error(int errorCode)
{
Log.d("TAG", Thread.currentThread().getName());
Log.e("TAG", errorCode + "");
}
@Override
public void weatherDate(Weather weather)
{
Log.d("TAG", Thread.currentThread().getName());
Weather.WeatherInfo weatherInfo = weather.getWeatherinfo();
Log.d("TAG", weatherInfo.getCity());
Log.d("TAG", weatherInfo.getTemp());
Log.d("TAG", weatherInfo.getTime());
}
}
这里在回中获取了Weather的对象,然后对对象的数据在ui线程中进行输出
同时也留有了cancel的接口, 用于取消在队列中的请求
DemoImpl.java
是为了实验同时抛出错误, 使用同一个接口
package org.chitarra.tiny.myapplication.presenter;
import android.os.Handler;
import android.os.Message;
public class DemoImpl
{
INetworkError networkErrorLister;
Handler myHandler = new Handler(){
@Override
public void handleMessage(Message msg)
{
networkErrorLister.error(msg.what);
super.handleMessage(msg);
}
};
public DemoImpl(INetworkError networkErrorLister)
{
this.networkErrorLister = networkErrorLister;
new Thread(new Runnable()
{
@Override
public void run()
{
try
{
Thread.sleep(6000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
myHandler.sendEmptyMessage(0x00);
}
}).start();
}
}
这里增加6秒的耗时操作来模拟网络环境,之后再通过handler将结果传到ui线程,同时Volley的到数据的接口也是运行在ui线程中的
测试结果
‘
使用Volley 向服务端post一个数据, 这里面服务器我用了node,至于怎么创建的跟android没什么关系,之后有时间我会写一下如何搭建的这个服务端
图中,服务器能接受到android 端发来的post请求,同时也读取了android端的参数,服务端也返回了一个json,在android端也能解析饿了