目錄結構

Paste_Image.png
Weather.java
天氣數(shù)據(jù)的抽象
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
統(tǒng)一拋出網(wǎng)絡的所有異常
package org.chitarra.tiny.myapplication.presenter;
public interface INetworkError {
void error(int errorCode);
}
IWeatherData.java
天氣數(shù)據(jù)的接口
package org.chitarra.tiny.myapplication.presenter;
import org.chitarra.tiny.myapplication.bean.Weather;
public interface IWeatherData {
void weatherDate(Weather weather);
}
WeatherPresenter.java
獲取天氣數(shù)據(jù),這里把業(yè)務邏輯寫在了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請求, 獲取服務器上的數(shù)據(jù)
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框架會把請求添加到隊列中,然后一一去執(zhí)行,同時我們也不需要為每一個請求都new一個volley的對象,所以我把它封裝到了一個單例模式中,創(chuàng)建的時候參數(shù)的context傳遞的是getApplicationContext,保證所有請求都使用一個volley對象,所以我就這樣去實現(xiàn)
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的對象,然后對對象的數(shù)據(jù)在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秒的耗時操作來模擬網(wǎng)絡環(huán)境,之后再通過handler將結果傳到ui線程,同時Volley的到數(shù)據(jù)的接口也是運行在ui線程中的
測試結果

Paste_Image.png
‘
使用Volley 向服務端post一個數(shù)據(jù), 這里面服務器我用了node,至于怎么創(chuàng)建的跟android沒什么關系,之后有時間我會寫一下如何搭建的這個服務端

Paste_Image.png

Paste_Image.png
圖中,服務器能接受到android 端發(fā)來的post請求,同時也讀取了android端的參數(shù),服務端也返回了一個json,在android端也能解析餓了