Android 網(wǎng)絡(luò)(三) Volley使用解析

前言

前一篇我們講解了HttpURLConnection的使用郑叠,通過(guò)它我們可以發(fā)送和接收網(wǎng)絡(luò)數(shù)據(jù),在實(shí)際項(xiàng)目中使用率很高明棍。不過(guò)可能你們也發(fā)現(xiàn)了乡革,其用法還是有些復(fù)雜的,我們實(shí)際使用時(shí)還是需要對(duì)其再封裝摊腋。
本文將講述一個(gè)使用很簡(jiǎn)單的網(wǎng)絡(luò)通信框架Volley沸版。

文章篇幅略長(zhǎng),示例略多兴蒸,建議收藏 & 下載Demo配合閱讀

Demo地址:

Github:DemoVolley

相關(guān)文章

Android 網(wǎng)絡(luò)(一) HTTP協(xié)議
Android 網(wǎng)絡(luò)(二) HttpURLConnection用法解析
Android 網(wǎng)絡(luò)(四) Volley源碼解析
Android 網(wǎng)絡(luò)(五) OkHttp用法解析
Android 網(wǎng)絡(luò)(六) OkHttp源碼解析
Android 網(wǎng)絡(luò)(七) Retrofit用法解析
Android 網(wǎng)絡(luò)(八) Retrofit源碼解析

Volley簡(jiǎn)介

在2013年Google I/O大會(huì)上推出了一個(gè)新的網(wǎng)絡(luò)通信框架Volley视粮。Volley既可以訪問(wèn)網(wǎng)絡(luò)取得數(shù)據(jù),也可以加載圖片橙凳,并且在性能方面也進(jìn)行了大幅度的調(diào)整蕾殴。

特點(diǎn):

  • 自動(dòng)調(diào)度網(wǎng)絡(luò)請(qǐng)求
  • 支持多個(gè)并發(fā)的網(wǎng)絡(luò)連接
  • 支持請(qǐng)求優(yōu)先級(jí)
  • 可以取消單個(gè)或一系列請(qǐng)求
  • 易于定制,如自定義請(qǐng)求方式
  • 調(diào)試和跟蹤工具

使用場(chǎng)景:

  • 非常適合去進(jìn)行數(shù)據(jù)量不大痕惋,但通信頻繁的網(wǎng)絡(luò)操作
  • 不適合大數(shù)據(jù)量的網(wǎng)絡(luò)操作区宇,比如說(shuō)下載文件等

如何導(dǎo)入

  • 可以通過(guò)下載Volley庫(kù)導(dǎo)入到libs\下并add as a library
  • 也可以通過(guò)Maven
  • 當(dāng)然還是更推薦通過(guò)Gradle添加依賴(lài)

implementation 'com.android.volley:volley:1.1.0'

使用前提

  • 項(xiàng)目添加網(wǎng)絡(luò)訪問(wèn)權(quán)限

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

Volley網(wǎng)絡(luò)請(qǐng)求隊(duì)列

Volley請(qǐng)求網(wǎng)絡(luò)是基于請(qǐng)求隊(duì)列的,我們只要簡(jiǎn)單的將請(qǐng)求放到請(qǐng)求隊(duì)列中就可以了值戳,它可以緩存所有的HTTP請(qǐng)求议谷,然后按照一定的算法并發(fā)地發(fā)出這些請(qǐng)求。其內(nèi)部設(shè)計(jì)非常適合高并發(fā)堕虹,因此基本上一個(gè)應(yīng)用或一個(gè)Activity持有一個(gè)請(qǐng)求隊(duì)列就足夠了卧晓。

Request

Volley內(nèi)部為我們提供了一系列不同數(shù)據(jù)的Request API芬首,同時(shí)由于其良好的擴(kuò)展性,我們也可以自定義我們需要的Request逼裆,對(duì)Request的分類(lèi)如下圖所示:

類(lèi)型 相關(guān)API 說(shuō)明
基礎(chǔ)請(qǐng)求 StringRequest郁稍,JsonRequest Volley提供
圖片請(qǐng)求 ImageRequestImageLoader胜宇,NetworkImageView Volley提供
自定義請(qǐng)求 XMLRequest耀怜,GSONRequest 開(kāi)發(fā)者自己實(shí)現(xiàn)

下面我們一個(gè)一個(gè)進(jìn)行學(xué)習(xí)

StringRequest的用法

StringRequest是繼承自Request類(lèi)的,屬于最基本的實(shí)現(xiàn)桐愉。

使用步驟:

  1. 創(chuàng)建RequestQueue對(duì)象
  2. 創(chuàng)建StringRequest對(duì)象
  3. 添加StringRequest對(duì)象到RequestQueue對(duì)象中

是不是很簡(jiǎn)單财破!
下面展示一個(gè)實(shí)例,注釋已經(jīng)很詳細(xì)了从诲,就不再贅述:

//StringRequest
    private void sendStringRequest(){
        //當(dāng)然首先嘗試一下訪問(wèn)百度了
        String url = "https://www.baidu.com";

        /**
         * 創(chuàng)建一個(gè)StringRequest對(duì)象
         * 參數(shù)說(shuō)明:
         * 1.請(qǐng)求方法
         * 2.目標(biāo)服務(wù)器的URL地址
         * 3.服務(wù)器響應(yīng)成功的回調(diào)
         * 1.服務(wù)器響應(yīng)失敗的回調(diào)
        **/
        StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                mTextView.setText("The StringRequest's response is "+ response.substring(0,500));
            }
        }, new Response.ErrorListener(){
            @Override
            public void onErrorResponse(VolleyError error) {
                mTextView.setText("The StringRequest's response is: That didn't work!" );
            }
        });
        //將StringRequest放入請(qǐng)求隊(duì)列中即可
        mQueue.add(stringRequest);
        /*以下為POST方式左痢,需要傳遞數(shù)據(jù)時(shí)的處理
        StringRequest stringRequestPost = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {

            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {

            }
        }){
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                Map<String,String> map = new HashMap<String,String>();
                map.put("param1","value1");
                map.put("param2","value2");
                return map;
            }
        }
        mQueue.add(stringRequestPost);
        */

    }

JsonRequest

JsonRequest是很類(lèi)似StringRequest的,同樣繼承自Request類(lèi)系洛,這也是為什么我把二者都?xì)w為簡(jiǎn)單Request的原因俊性。
不過(guò)JsonRequest是一個(gè)抽象類(lèi),其有兩個(gè)實(shí)現(xiàn)類(lèi)分別為JsonObjectRequestJsonArrayRequest描扯,從字面上我們都可以才得到:前者請(qǐng)求一段JSON數(shù)據(jù)定页,后者請(qǐng)求一段JSON數(shù)組

使用步驟:

  1. 創(chuàng)建RequestQueue對(duì)象
  2. 創(chuàng)建JsonObjectRequestJsonArrayRequest對(duì)象
  3. 2放入1中

實(shí)例:

//JSONRequest
    private void sendJSONRequest(){
        //網(wǎng)上找到的一個(gè)天氣的API,暫時(shí)可用荆烈,穩(wěn)定性待測(cè)= =
        String url = "https://www.sojson.com/open/api/weather/json.shtml?city=北京";
        //JsonObjectRequest和JsonArrayRequest是JsonRequest(抽象類(lèi))的子類(lèi)
        //前者請(qǐng)求JSON數(shù)據(jù)拯勉,后者請(qǐng)求JSON數(shù)組
        /**
         * 參數(shù)說(shuō)明:
         * 1:請(qǐng)求方法
         * 2:服務(wù)器的URL地址
         * 3:POST方式傳遞的JSON數(shù)據(jù)竟趾,如果為空則表示POST方式?jīng)]有要提交的參數(shù)
         * 4:接收響應(yīng)成功時(shí)返回的JSON數(shù)據(jù)的監(jiān)聽(tīng)器
         * 4:接收響應(yīng)失敗時(shí)返回的錯(cuò)誤信息的監(jiān)聽(tīng)器
         */
        JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject response) {
                mTextView.setText("The JSONRequest's response is " + response.toString());
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                mTextView.setText("The JSONRequest's response is: That didn't work!" );
            }
        });
        //將請(qǐng)求放入請(qǐng)求隊(duì)列
        mQueue.add(jsonObjectRequest);
    }

是不是發(fā)現(xiàn)JsonObjectRequest的用法和StringRequest的用法基本一致憔购?這也是Volley的強(qiáng)大之處,我們只要了解最基本的StringRequest岔帽,就很容易舉一反三玫鸟。
提前劇透以下,后續(xù)的自定義Request本質(zhì)上就是變了形的StringRequest

ImageRequest

ImageRequest是一個(gè)圖片請(qǐng)求對(duì)象犀勒,繼承自Request<Bitmap>屎飘,得到的結(jié)果是一個(gè)Bitmap。不過(guò)現(xiàn)在已經(jīng)是過(guò)時(shí)的方法了贾费。推薦后續(xù)下面兩種圖片請(qǐng)求方式钦购。

使用步驟:

  1. 創(chuàng)建RequestQueue對(duì)象。
  2. 創(chuàng)建ImageRequest對(duì)象褂萧。
  3. ImageRequest對(duì)象添加到RequestQueue里面押桃。

實(shí)例

/ImageRequest
    private void useImageRequest() {
        //url地址,我的簡(jiǎn)書(shū)的頭像= =
        String url = "https://upload.jianshu.io/users/upload_avatars/11024422/9960fc0a-0e86-4a1b-ba25-bca296e674c9.jpg?imageMogr2/auto-orient/strip|imageView2/1/w/300/h/300";
        //創(chuàng)建ImageRequest對(duì)象
        /**
         * 參數(shù)說(shuō)明:
         * 1. URL
         * 2. 圖片請(qǐng)求成功的回調(diào)
         * 34. 指定圖片最大的寬度和高度导犹,如果網(wǎng)絡(luò)圖片高度或?qū)挾却笥谶@里的最大值唱凯,就會(huì)對(duì)圖片進(jìn)行壓縮
         * 如果指定為0則表示不管圖片多大都不會(huì)壓縮圖片
         * 5. 指定顏色屬性
         * 6. 圖片請(qǐng)求失敗的回調(diào)
         */
        ImageRequest imageRequest = new ImageRequest(url, new Response.Listener<Bitmap>() {
            @Override
            public void onResponse(Bitmap response) {
                mImageView.setImageBitmap(response);
            }
        }, 0, 0, Bitmap.Config.RGB_565, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                mImageView.setImageResource(R.mipmap.ic_launcher);
            }
        });
        mQueue.add(imageRequest);
    }

是不是又雙發(fā)現(xiàn)羡忘,這個(gè)使用步驟驚人的相似!這是因?yàn)樗蜕鲜鰞煞N基本Request同繼承自Request磕昼,因此處理方式自然不會(huì)有很大差異卷雕。

ImageLoader

ImageLoader同樣用來(lái)加載網(wǎng)絡(luò)圖片,其內(nèi)部基于ImageRequest票从,但是比ImageRequest高效的多漫雕。它的構(gòu)造器可以傳入一個(gè)ImageCache緩存形參,實(shí)現(xiàn)了圖片緩存的功能峰鄙,同時(shí)還可以過(guò)濾重復(fù)鏈接蝎亚,避免重復(fù)發(fā)送請(qǐng)求。

  • 有一點(diǎn)顯著的不同的是先馆,ImageLoader加載圖片會(huì)先顯示默認(rèn)的圖片发框,等待圖片加載完成才會(huì)顯示在ImageView上。

使用步驟

  1. 創(chuàng)建RequestQueue對(duì)象煤墙。
  2. 創(chuàng)建ImageLoader對(duì)象梅惯。
  3. 獲取ImageListener對(duì)象。
  4. 調(diào)用ImageLoader.get()方法加載網(wǎng)絡(luò)上的圖片仿野。

實(shí)例:

private void useImageLoader() {
        //簡(jiǎn)書(shū)頭像的url
        String url = "https://upload.jianshu.io/users/upload_avatars/11024422/9960fc0a-0e86-4a1b-ba25-bca296e674c9.jpg?imageMogr2/auto-orient/strip|imageView2/1/w/300/h/300";
        //創(chuàng)建ImageLoader
        /**
         * 參數(shù)說(shuō)明:
         * 1. 請(qǐng)求隊(duì)列
         * 2. ImageCache铣减,顯然想實(shí)現(xiàn)一個(gè)性能好的緩存,避免不了使用LruChcae
         * 由于現(xiàn)在對(duì)LruCache不甚了解脚作,就放上一個(gè)空ImageCache
         */
        ImageLoader imageLoader = new ImageLoader(mQueue, new ImageLoader.ImageCache() {
            @Override
            public Bitmap getBitmap(String url) {
                return null;
            }

            @Override
            public void putBitmap(String url, Bitmap bitmap) {

            }
        });
        //創(chuàng)建ImageListener對(duì)象
        /**
         * 參數(shù)說(shuō)明:
         * 1. 指定顯示圖片的ImageView控件
         * 2. 加載過(guò)程中顯示的圖片
         * 3. 加載失敗時(shí)顯示的圖片
         */
        ImageLoader.ImageListener listener = ImageLoader.getImageListener(
                mImageView,R.mipmap.load,R.mipmap.failure);
        //加載圖片
        imageLoader.get(url,listener);
        /*
        //重載方法葫哗,可對(duì)大小進(jìn)行限制
        imageLoader.get(url, listener, 200, 200);
        */
    }

具體實(shí)現(xiàn)見(jiàn)示例注釋即可,參數(shù)說(shuō)明很詳細(xì)球涛。

NetworkImageView

NetworkImageView是一個(gè)自定義控制劣针,它是繼承自ImageView的,具備ImageView控件的所有功能亿扁,并且在原生的基礎(chǔ)之上加入了加載網(wǎng)絡(luò)圖片的功能捺典。

使用步驟:

  1. 創(chuàng)建RequestQueue對(duì)象。
  2. 創(chuàng)建ImageLoader對(duì)象从祝。
  3. 在布局文件中添加NetworkImageView控件襟己。
  4. 獲取控件的實(shí)例。
  5. 設(shè)置加載圖片地址牍陌。

實(shí)例:

private void useNetworkImageView() {
        //url
        String url = "https://upload.jianshu.io/users/upload_avatars/11024422/9960fc0a-0e86-4a1b-ba25-bca296e674c9.jpg?imageMogr2/auto-orient/strip|imageView2/1/w/300/h/300";

        //創(chuàng)建ImageLoader擎浴,參數(shù)說(shuō)明不在重復(fù)
        ImageLoader imageLoader = new ImageLoader(mQueue, new ImageLoader.ImageCache() {
            @Override
            public Bitmap getBitmap(String url) {
                return null;
            }

            @Override
            public void putBitmap(String url, Bitmap bitmap) {

            }
        });
        //下面兩個(gè)方法同ImageLoader.ImageListener listener = ImageLoader.getImageListener(mImageView,R.mipmap.load,R.mipmap.failure);
        //作用是設(shè)置加載過(guò)程中和加載失敗時(shí)顯示的圖片
        mNetworkImageView.setDefaultImageResId(R.mipmap.load);
        mNetworkImageView.setErrorImageResId(R.mipmap.failure);

        //設(shè)置加載的圖片地址
        mNetworkImageView.setImageUrl(url,imageLoader);
    }
 <com.android.volley.toolbox.NetworkImageView
            android:id="@+id/network_image_view"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="match_parent"/>
    </LinearLayout>

使用方法和具體實(shí)現(xiàn)和ImageLoader基本一致,不過(guò)需要注意的是:

NetworkImageView并沒(méi)有提供設(shè)置最大寬度和高度的方法毒涧,根據(jù)我們?cè)O(shè)置控件的寬和高結(jié)合網(wǎng)絡(luò)圖片的寬和高內(nèi)部會(huì)自動(dòng)去實(shí)現(xiàn)壓縮贮预,呈現(xiàn)給我們一張大小剛剛好的網(wǎng)絡(luò)圖片,不占用任何一點(diǎn)多于內(nèi)存,如果我們不想要壓縮可以設(shè)置NetworkImageView控件的寬和高都為wrap_content萌狂。

GSONRequest

前面我們提到過(guò)JsonRequest档玻,其返回結(jié)果是亂糟糟的JSON數(shù)據(jù),解析起來(lái)太麻煩了茫藏,那么有沒(méi)有什么辦法可以讓JSON數(shù)據(jù)解析變得簡(jiǎn)單呢答案當(dāng)然是肯定的误趴,我們可以借助GSON這個(gè)工具,遺憾的是Volley本身對(duì)此并不支持务傲,下面我們就來(lái)自己動(dòng)手寫(xiě)一個(gè)GSONRequest凉当。

首先我們需要添加GSON依賴(lài)

implementation 'com.google.code.gson:gson:2.8.2'

我們分析一下GSONRequest如何實(shí)現(xiàn)
我們的目的是要更簡(jiǎn)單的解析JSON數(shù)據(jù),為此我們引入了GSON工具售葡,那么我們就可以從JsonRequest入手看杭,而JsonRequestStringRequest挟伙、ImageRequest同繼承自Request類(lèi)楼雹,因此我們著手分析最基礎(chǔ)的StringRequest類(lèi),下面放上其源碼:

/**
 * A canned request for retrieving the response body at a given URL as a String.
 */
public class StringRequest extends Request<String> {

    /** Lock to guard mListener as it is cleared on cancel() and read on delivery. */
    private final Object mLock = new Object();

    // @GuardedBy("mLock")
    private Listener<String> mListener;

    /**
     * Creates a new request with the given method.
     *
     * @param method the request {@link Method} to use
     * @param url URL to fetch the string at
     * @param listener Listener to receive the String response
     * @param errorListener Error listener, or null to ignore errors
     */
    public StringRequest(int method, String url, Listener<String> listener,
            ErrorListener errorListener) {
        super(method, url, errorListener);
        mListener = listener;
    }

    /**
     * Creates a new GET request.
     *
     * @param url URL to fetch the string at
     * @param listener Listener to receive the String response
     * @param errorListener Error listener, or null to ignore errors
     */
    public StringRequest(String url, Listener<String> listener, ErrorListener errorListener) {
        this(Method.GET, url, listener, errorListener);
    }

    @Override
    public void cancel() {
        super.cancel();
        synchronized (mLock) {
            mListener = null;
        }
    }

    @Override
    protected void deliverResponse(String response) {
        Response.Listener<String> listener;
        synchronized (mLock) {
            listener = mListener;
        }
        if (listener != null) {
            listener.onResponse(response);
        }
    }

    @Override
    protected Response<String> parseNetworkResponse(NetworkResponse response) {
        String parsed;
        try {
            parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
        } catch (UnsupportedEncodingException e) {
            parsed = new String(response.data);
        }
        return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response));
    }
}

對(duì)源碼進(jìn)行分析:

  • Request可以指定泛型
  • StringRequest持有一個(gè)mListener尖阔,用來(lái)接收響應(yīng)成功的回調(diào)
  • mLock用來(lái)維護(hù)mListener
  • 提供兩個(gè)有參的構(gòu)造函數(shù)贮缅,前面我們不止一次提到參數(shù)的意義了,不再贅述

構(gòu)造函數(shù)必須調(diào)用super()介却,因?yàn)檎?qǐng)求和響應(yīng)在父類(lèi)中自動(dòng)處理

  • 抽象方法deliverResponse()谴供,調(diào)用mListener中的onResponse()方法,傳入response內(nèi)容齿坷,這樣我們就可以操作網(wǎng)絡(luò)響應(yīng)的數(shù)據(jù)了
  • 抽象方法parseNetworkResponse()桂肌,對(duì)服務(wù)器相應(yīng)的數(shù)據(jù)解析,字節(jié)形式存入response.data永淌,之后在取出數(shù)據(jù)組裝成String傳入Responsesuccess方法崎场。

下面我們就可以開(kāi)始編寫(xiě)我們的GsonRequest了,示例如下:

public class GsonRequest<T> extends Request<T> {

    private Gson mGson;
    private Class<T> mClass;
    //private final Map<String, String> headers;
    private final Response.Listener<T> mListener;

    public GsonRequest(int method, String url, Class<T> mClass, Response.Listener<T> listener, Response.ErrorListener errorListener) {
        super(Method.GET, url, errorListener);
        this.mClass = mClass;
        this.mListener = listener;
        mGson = new Gson();
    }
    public GsonRequest(String url, Class<T> clazz, Response.Listener<T> listener,
                       Response.ErrorListener errorListener){
        this(Method.GET,url,clazz,listener,errorListener);
    }

    @Override
    protected Response<T> parseNetworkResponse(NetworkResponse response) {
        try {
            String json = new String(response.data,
                    HttpHeaderParser.parseCharset(response.headers));
            return Response.success(mGson.fromJson(json,mClass),
                    HttpHeaderParser.parseCacheHeaders(response));
        }catch (Exception e){
            return Response.error(new ParseError(e));
        }
    }

    @Override
    protected void deliverResponse(T response) {
        mListener.onResponse(response);
    }
}

沒(méi)有什么太困難的仰禀,照貓畫(huà)虎即可照雁,除了設(shè)置泛型以外,核心是通過(guò)調(diào)用GSONfromJson()方法將數(shù)據(jù)組成JavaBean對(duì)象答恶,之后通過(guò)deliverResponse()方法進(jìn)行回調(diào)。

JSON數(shù)據(jù)示例:
API地址https://www.sojson.com/open/api/weather/json.shtml?city=北京

{
    "date": "20180404",
    "message": "Success !",
    "status": 200,
    "city": "北京",
    "count": 1365,
    "data": {
        "shidu": "85%",
        "pm25": 14.0,
        "pm10": 0.0,
        "quality": "優(yōu)",
        "wendu": "2",
        "ganmao": "各類(lèi)人群可自由活動(dòng)",
        "yesterday": {
            "date": "03日星期二",
            "sunrise": "05:58",
            "high": "高溫 13.0℃",
            "low": "低溫 4.0℃",
            "sunset": "18:40",
            "aqi": 88.0,
            "fx": "北風(fēng)",
            "fl": "3-4級(jí)",
            "type": "陰",
            "notice": "不要被陰云遮擋住好心情"
        },
        "forecast": [{
            "date": "04日星期三",
            "sunrise": "05:57",
            "high": "高溫 10.0℃",
            "low": "低溫 1.0℃",
            "sunset": "18:41",
            "aqi": 39.0,
            "fx": "東北風(fēng)",
            "fl": "<3級(jí)",
            "type": "雨夾雪",
            "notice": "道路濕滑萍诱,步行開(kāi)車(chē)要謹(jǐn)慎"
        }, {
            "date": "05日星期四",
            "sunrise": "05:55",
            "high": "高溫 11.0℃",
            "low": "低溫 1.0℃",
            "sunset": "18:42",
            "aqi": 62.0,
            "fx": "西南風(fēng)",
            "fl": "<3級(jí)",
            "type": "多云",
            "notice": "陰晴之間悬嗓,謹(jǐn)防紫外線侵?jǐn)_"
        }, {
            "date": "06日星期五",
            "sunrise": "05:53",
            "high": "高溫 12.0℃",
            "low": "低溫 4.0℃",
            "sunset": "18:43",
            "aqi": 56.0,
            "fx": "西北風(fēng)",
            "fl": "3-4級(jí)",
            "type": "多云",
            "notice": "陰晴之間,謹(jǐn)防紫外線侵?jǐn)_"
        }, {
            "date": "07日星期六",
            "sunrise": "05:52",
            "high": "高溫 14.0℃",
            "low": "低溫 3.0℃",
            "sunset": "18:44",
            "aqi": 48.0,
            "fx": "西北風(fēng)",
            "fl": "3-4級(jí)",
            "type": "晴",
            "notice": "愿你擁有比陽(yáng)光明媚的心情"
        }, {
            "date": "08日星期日",
            "sunrise": "05:50",
            "high": "高溫 16.0℃",
            "low": "低溫 5.0℃",
            "sunset": "18:45",
            "aqi": 67.0,
            "fx": "南風(fēng)",
            "fl": "<3級(jí)",
            "type": "多云",
            "notice": "陰晴之間裕坊,謹(jǐn)防紫外線侵?jǐn)_"
        }]
    }
}

對(duì)應(yīng)JavaBean類(lèi)包竹,強(qiáng)烈建議使用GsonFormat插件自動(dòng)生成

/GsonFormat對(duì)應(yīng)的JavaBean類(lèi)
public class Weather {

    /**
     * date : 20180404
     * message : Success !
     * status : 200
     * city : 北京
     * count : 1026
     * data : {"shidu":"85%","pm25":14,"pm10":0,"quality":"優(yōu)","wendu":"2","ganmao":"各類(lèi)人群可自由活動(dòng)","yesterday":{"date":"03日星期二","sunrise":"05:58","high":"高溫 13.0℃","low":"低溫 4.0℃","sunset":"18:40","aqi":88,"fx":"北風(fēng)","fl":"3-4級(jí)","type":"陰","notice":"不要被陰云遮擋住好心情"},"forecast":[{"date":"04日星期三","sunrise":"05:57","high":"高溫 10.0℃","low":"低溫 1.0℃","sunset":"18:41","aqi":39,"fx":"東北風(fēng)","fl":"<3級(jí)","type":"雨夾雪","notice":"道路濕滑,步行開(kāi)車(chē)要謹(jǐn)慎"},{"date":"05日星期四","sunrise":"05:55","high":"高溫 11.0℃","low":"低溫 1.0℃","sunset":"18:42","aqi":62,"fx":"西南風(fēng)","fl":"<3級(jí)","type":"多云","notice":"陰晴之間,謹(jǐn)防紫外線侵?jǐn)_"},{"date":"06日星期五","sunrise":"05:53","high":"高溫 12.0℃","low":"低溫 4.0℃","sunset":"18:43","aqi":56,"fx":"西北風(fēng)","fl":"3-4級(jí)","type":"多云","notice":"陰晴之間周瞎,謹(jǐn)防紫外線侵?jǐn)_"},{"date":"07日星期六","sunrise":"05:52","high":"高溫 14.0℃","low":"低溫 3.0℃","sunset":"18:44","aqi":48,"fx":"西北風(fēng)","fl":"3-4級(jí)","type":"晴","notice":"愿你擁有比陽(yáng)光明媚的心情"},{"date":"08日星期日","sunrise":"05:50","high":"高溫 16.0℃","low":"低溫 5.0℃","sunset":"18:45","aqi":67,"fx":"南風(fēng)","fl":"<3級(jí)","type":"多云","notice":"陰晴之間苗缩,謹(jǐn)防紫外線侵?jǐn)_"}]}
     */

    private String date;
    private String message;
    private int status;
    private String city;
    private int count;
    private DataBean data;

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }

    public DataBean getData() {
        return data;
    }

    public void setData(DataBean data) {
        this.data = data;
    }

    public static class DataBean {
        /**
         * shidu : 85%
         * pm25 : 14.0
         * pm10 : 0.0
         * quality : 優(yōu)
         * wendu : 2
         * ganmao : 各類(lèi)人群可自由活動(dòng)
         * yesterday : {"date":"03日星期二","sunrise":"05:58","high":"高溫 13.0℃","low":"低溫 4.0℃","sunset":"18:40","aqi":88,"fx":"北風(fēng)","fl":"3-4級(jí)","type":"陰","notice":"不要被陰云遮擋住好心情"}
         * forecast : [{"date":"04日星期三","sunrise":"05:57","high":"高溫 10.0℃","low":"低溫 1.0℃","sunset":"18:41","aqi":39,"fx":"東北風(fēng)","fl":"<3級(jí)","type":"雨夾雪","notice":"道路濕滑,步行開(kāi)車(chē)要謹(jǐn)慎"},{"date":"05日星期四","sunrise":"05:55","high":"高溫 11.0℃","low":"低溫 1.0℃","sunset":"18:42","aqi":62,"fx":"西南風(fēng)","fl":"<3級(jí)","type":"多云","notice":"陰晴之間声诸,謹(jǐn)防紫外線侵?jǐn)_"},{"date":"06日星期五","sunrise":"05:53","high":"高溫 12.0℃","low":"低溫 4.0℃","sunset":"18:43","aqi":56,"fx":"西北風(fēng)","fl":"3-4級(jí)","type":"多云","notice":"陰晴之間酱讶,謹(jǐn)防紫外線侵?jǐn)_"},{"date":"07日星期六","sunrise":"05:52","high":"高溫 14.0℃","low":"低溫 3.0℃","sunset":"18:44","aqi":48,"fx":"西北風(fēng)","fl":"3-4級(jí)","type":"晴","notice":"愿你擁有比陽(yáng)光明媚的心情"},{"date":"08日星期日","sunrise":"05:50","high":"高溫 16.0℃","low":"低溫 5.0℃","sunset":"18:45","aqi":67,"fx":"南風(fēng)","fl":"<3級(jí)","type":"多云","notice":"陰晴之間,謹(jǐn)防紫外線侵?jǐn)_"}]
         */

        private String shidu;
        private double pm25;
        private double pm10;
        private String quality;
        private String wendu;
        private String ganmao;
        private YesterdayBean yesterday;
        private List<ForecastBean> forecast;

        public String getShidu() {
            return shidu;
        }

        public void setShidu(String shidu) {
            this.shidu = shidu;
        }

        public double getPm25() {
            return pm25;
        }

        public void setPm25(double pm25) {
            this.pm25 = pm25;
        }

        public double getPm10() {
            return pm10;
        }

        public void setPm10(double pm10) {
            this.pm10 = pm10;
        }

        public String getQuality() {
            return quality;
        }

        public void setQuality(String quality) {
            this.quality = quality;
        }

        public String getWendu() {
            return wendu;
        }

        public void setWendu(String wendu) {
            this.wendu = wendu;
        }

        public String getGanmao() {
            return ganmao;
        }

        public void setGanmao(String ganmao) {
            this.ganmao = ganmao;
        }

        public YesterdayBean getYesterday() {
            return yesterday;
        }

        public void setYesterday(YesterdayBean yesterday) {
            this.yesterday = yesterday;
        }

        public List<ForecastBean> getForecast() {
            return forecast;
        }

        public void setForecast(List<ForecastBean> forecast) {
            this.forecast = forecast;
        }

        public static class YesterdayBean {
            /**
             * date : 03日星期二
             * sunrise : 05:58
             * high : 高溫 13.0℃
             * low : 低溫 4.0℃
             * sunset : 18:40
             * aqi : 88.0
             * fx : 北風(fēng)
             * fl : 3-4級(jí)
             * type : 陰
             * notice : 不要被陰云遮擋住好心情
             */

            private String date;
            private String sunrise;
            private String high;
            private String low;
            private String sunset;
            private double aqi;
            private String fx;
            private String fl;
            private String type;
            private String notice;

            public String getDate() {
                return date;
            }

            public void setDate(String date) {
                this.date = date;
            }

            public String getSunrise() {
                return sunrise;
            }

            public void setSunrise(String sunrise) {
                this.sunrise = sunrise;
            }

            public String getHigh() {
                return high;
            }

            public void setHigh(String high) {
                this.high = high;
            }

            public String getLow() {
                return low;
            }

            public void setLow(String low) {
                this.low = low;
            }

            public String getSunset() {
                return sunset;
            }

            public void setSunset(String sunset) {
                this.sunset = sunset;
            }

            public double getAqi() {
                return aqi;
            }

            public void setAqi(double aqi) {
                this.aqi = aqi;
            }

            public String getFx() {
                return fx;
            }

            public void setFx(String fx) {
                this.fx = fx;
            }

            public String getFl() {
                return fl;
            }

            public void setFl(String fl) {
                this.fl = fl;
            }

            public String getType() {
                return type;
            }

            public void setType(String type) {
                this.type = type;
            }

            public String getNotice() {
                return notice;
            }

            public void setNotice(String notice) {
                this.notice = notice;
            }
        }

        public static class ForecastBean {
            /**
             * date : 04日星期三
             * sunrise : 05:57
             * high : 高溫 10.0℃
             * low : 低溫 1.0℃
             * sunset : 18:41
             * aqi : 39.0
             * fx : 東北風(fēng)
             * fl : <3級(jí)
             * type : 雨夾雪
             * notice : 道路濕滑彼乌,步行開(kāi)車(chē)要謹(jǐn)慎
             */

            private String date;
            private String sunrise;
            private String high;
            private String low;
            private String sunset;
            private double aqi;
            private String fx;
            private String fl;
            private String type;
            private String notice;

            public String getDate() {
                return date;
            }

            public void setDate(String date) {
                this.date = date;
            }

            public String getSunrise() {
                return sunrise;
            }

            public void setSunrise(String sunrise) {
                this.sunrise = sunrise;
            }

            public String getHigh() {
                return high;
            }

            public void setHigh(String high) {
                this.high = high;
            }

            public String getLow() {
                return low;
            }

            public void setLow(String low) {
                this.low = low;
            }

            public String getSunset() {
                return sunset;
            }

            public void setSunset(String sunset) {
                this.sunset = sunset;
            }

            public double getAqi() {
                return aqi;
            }

            public void setAqi(double aqi) {
                this.aqi = aqi;
            }

            public String getFx() {
                return fx;
            }

            public void setFx(String fx) {
                this.fx = fx;
            }

            public String getFl() {
                return fl;
            }

            public void setFl(String fl) {
                this.fl = fl;
            }

            public String getType() {
                return type;
            }

            public void setType(String type) {
                this.type = type;
            }

            public String getNotice() {
                return notice;
            }

            public void setNotice(String notice) {
                this.notice = notice;
            }
        }
    }
}

具體解析調(diào)用:

private void useGSONRequest() {
        String url = "https://www.sojson.com/open/api/weather/json.shtml?city=北京";

        GsonRequest<Weather> gsonRequest = new GsonRequest<Weather>(url, Weather.class,
                new Response.Listener<Weather>() {
                    @Override
                    public void onResponse(Weather response) {
                        Weather.DataBean dataBean = response.getData();
                        List<Weather.DataBean.ForecastBean> forecastList = dataBean.getForecast();
                        Weather.DataBean.YesterdayBean yesterday = dataBean.getYesterday();

                        StringBuilder builder = new StringBuilder();
                        builder.append("日期:"+ response.getDate() + "\n");
                        builder.append("城市:"+ response.getCity() + "\n" + "\n");

                        builder.append("當(dāng)前天氣" + "\n");
                        builder.append("濕度: "+dataBean.getShidu()+"\n");
                        builder.append("PM25: "+dataBean.getPm25()+"\n");
                        builder.append("PM10: "+dataBean.getPm10()+"\n");
                        builder.append("空氣質(zhì)量: "+dataBean.getQuality()+"\n");
                        builder.append("溫度: "+dataBean.getWendu()+"\n");
                        builder.append("感冒指數(shù): "+dataBean.getGanmao()+"\n"+ "\n");

                        builder.append("昨日天氣" + "\n");
                        builder.append("日期: "+yesterday.getDate()+"\n");
                        builder.append("日出時(shí)間: "+yesterday.getSunrise()+"\n");
                        builder.append("最高溫度: "+yesterday.getHigh()+"\n");
                        builder.append("最低溫度: "+yesterday.getLow()+"\n");
                        builder.append("日落時(shí)間: "+yesterday.getSunset()+"\n");
                        builder.append("AQI: "+yesterday.getAqi()+"\n");
                        builder.append("風(fēng)向: "+yesterday.getFx()+"\n");
                        builder.append("風(fēng)力: "+yesterday.getFl()+"\n");
                        builder.append("天氣: "+yesterday.getType()+"\n");
                        builder.append("注意: "+yesterday.getNotice()+"\n"+ "\n");
                       for (Weather.DataBean.ForecastBean forecast : forecastList){
                            builder.append("未來(lái)天氣:" + "\n");
                           builder.append("日期: "+forecast.getDate()+"\n");
                           builder.append("日出時(shí)間: "+forecast.getSunrise()+"\n");
                           builder.append("最高溫度: "+forecast.getHigh()+"\n");
                           builder.append("最低溫度: "+forecast.getLow()+"\n");
                           builder.append("日落時(shí)間: "+forecast.getSunset()+"\n");
                           builder.append("AQI: "+forecast.getAqi()+"\n");
                           builder.append("風(fēng)向: "+forecast.getFx()+"\n");
                           builder.append("風(fēng)力: "+forecast.getFl()+"\n");
                           builder.append("天氣: "+forecast.getType()+"\n");
                           builder.append("注意: "+forecast.getNotice()+"\n"+ "\n");
                        }
                        mTextView.setText(builder);
                    }
                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                mTextView.setText(error.getMessage());
            }
        });
        mQueue.add(gsonRequest);
    }

XMLRequest

了解上面的原理之后泻肯,我們可以很容易的編寫(xiě)XMLRequest
實(shí)例:

public class XMLRequest extends Request<XmlPullParser> {

    private final Response.Listener<XmlPullParser> mListener;

    public XMLRequest(int method, String url, Response.Listener<XmlPullParser> listener, Response.ErrorListener errorListener) {

        super(method, url, errorListener);
        mListener = listener;
    }

    public XMLRequest(String url, Response.Listener<XmlPullParser> listener, Response.ErrorListener errorListener){
        this(Method.GET,url,listener,errorListener);
    }

    @Override
    protected Response<XmlPullParser> parseNetworkResponse(NetworkResponse response) {
        try {
            String xmlString = new String(response.data,
                    HttpHeaderParser.parseCharset(response.headers));
            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
            XmlPullParser parser = factory.newPullParser();
            parser.setInput(new StringReader(xmlString));
            return Response.success(parser,HttpHeaderParser.parseCacheHeaders(response));
        }catch (Exception e){
            return Response.error(new ParseError(e));
        }
    }

    @Override
    protected void deliverResponse(XmlPullParser response) {
        mListener.onResponse(response);
    }
}

我們通過(guò)PULL方式進(jìn)行解析,因此最后返回一個(gè)XmlPullParser對(duì)象慰照。

XML文件示例
API地址https://www.sojson.com/open/api/weather/xml.shtml?city=北京

<resp>
<city>北京</city>
<updatetime>23:31</updatetime>
<wendu>3</wendu>
<fengli>
<![CDATA[ 2級(jí) ]]>
</fengli>
<shidu>85%</shidu>
<fengxiang>東風(fēng)</fengxiang>
<sunrise_1>05:57</sunrise_1>
<sunset_1>18:41</sunset_1>
<sunrise_2/>
<sunset_2/>
<environment>
<aqi>34</aqi>
<pm25>13</pm25>
<suggest>各類(lèi)人群可自由活動(dòng)</suggest>
<quality>優(yōu)</quality>
<MajorPollutants/>
<o3>44</o3>
<co>0</co>
<pm10>10</pm10>
<so2>2</so2>
<no2>27</no2>
<time>23:00:00</time>
</environment>
<yesterday>
<date_1>2日星期一</date_1>
<high_1>高溫 26℃</high_1>
<low_1>低溫 11℃</low_1>
<day_1>
<type_1>多云</type_1>
<fx_1>東北風(fēng)</fx_1>
<fl_1>
<![CDATA[ <3級(jí) ]]>
</fl_1>
</day_1>
<night_1>
<type_1>多云</type_1>
<fx_1>東北風(fēng)</fx_1>
<fl_1>
<![CDATA[ 3-4級(jí) ]]>
</fl_1>
</night_1>
</yesterday>
<forecast>
<weather>
<date>3日星期二</date>
<high>高溫 13℃</high>
<low>低溫 2℃</low>
<day>
<type>陰</type>
<fengxiang>北風(fēng)</fengxiang>
<fengli>
<![CDATA[ 3-4級(jí) ]]>
</fengli>
</day>
<night>
<type>陰</type>
<fengxiang>東北風(fēng)</fengxiang>
<fengli>
<![CDATA[ <3級(jí) ]]>
</fengli>
</night>
</weather>
<weather>
<date>4日星期三</date>
<high>高溫 10℃</high>
<low>低溫 1℃</low>
<day>
<type>雨夾雪</type>
<fengxiang>東北風(fēng)</fengxiang>
<fengli>
<![CDATA[ <3級(jí) ]]>
</fengli>
</day>
<night>
<type>雨夾雪</type>
<fengxiang>北風(fēng)</fengxiang>
<fengli>
<![CDATA[ <3級(jí) ]]>
</fengli>
</night>
</weather>
<weather>
<date>5日星期四</date>
<high>高溫 11℃</high>
<low>低溫 1℃</low>
<day>
<type>多云</type>
<fengxiang>西南風(fēng)</fengxiang>
<fengli>
<![CDATA[ <3級(jí) ]]>
</fengli>
</day>
<night>
<type>多云</type>
<fengxiang>西風(fēng)</fengxiang>
<fengli>
<![CDATA[ <3級(jí) ]]>
</fengli>
</night>
</weather>
<weather>
<date>6日星期五</date>
<high>高溫 12℃</high>
<low>低溫 4℃</low>
<day>
<type>多云</type>
<fengxiang>西北風(fēng)</fengxiang>
<fengli>
<![CDATA[ 3-4級(jí) ]]>
</fengli>
</day>
<night>
<type>多云</type>
<fengxiang>西北風(fēng)</fengxiang>
<fengli>
<![CDATA[ <3級(jí) ]]>
</fengli>
</night>
</weather>
<weather>
<date>7日星期六</date>
<high>高溫 14℃</high>
<low>低溫 3℃</low>
<day>
<type>晴</type>
<fengxiang>西北風(fēng)</fengxiang>
<fengli>
<![CDATA[ 3-4級(jí) ]]>
</fengli>
</day>
<night>
<type>多云</type>
<fengxiang>東北風(fēng)</fengxiang>
<fengli>
<![CDATA[ <3級(jí) ]]>
</fengli>
</night>
</weather>
</forecast>
<zhishus>
<zhishu>
<name>晨練指數(shù)</name>
<value>較不宜</value>
<detail>有降水灶挟,較不宜晨練,室外鍛煉請(qǐng)攜帶雨具毒租。建議年老體弱人群適當(dāng)減少晨練時(shí)間稚铣。</detail>
</zhishu>
<zhishu>
<name>舒適度</name>
<value>較舒適</value>
<detail>白天會(huì)有降雪,這種天氣條件下墅垮,人們會(huì)感到有些涼意榛泛,但大部分人完全可以接受。</detail>
</zhishu>
<zhishu>
<name>穿衣指數(shù)</name>
<value>較冷</value>
<detail>建議著厚外套加毛衣等服裝噩斟。年老體弱者宜著大衣曹锨、呢外套加羊毛衫。</detail>
</zhishu>
<zhishu>
<name>感冒指數(shù)</name>
<value>較易發(fā)</value>
<detail>天氣較涼剃允,較易發(fā)生感冒沛简,請(qǐng)適當(dāng)增加衣服。體質(zhì)較弱的朋友尤其應(yīng)該注意防護(hù)斥废。</detail>
</zhishu>
<zhishu>
<name>晾曬指數(shù)</name>
<value>不宜</value>
<detail>有降雪椒楣,不適宜晾曬。若需要晾曬牡肉,請(qǐng)?jiān)谑覂?nèi)準(zhǔn)備出充足的空間捧灰。</detail>
</zhishu>
<zhishu>
<name>旅游指數(shù)</name>
<value>適宜</value>
<detail>溫度適宜,同時(shí)又有微風(fēng)伴您一路同行统锤。比較適宜旅游煤篙,但有降雪,出行請(qǐng)注意攜帶雨具厢岂。</detail>
</zhishu>
<zhishu>
<name>紫外線強(qiáng)度</name>
<value>最弱</value>
<detail>屬弱紫外線輻射天氣捆交,無(wú)需特別防護(hù)。若長(zhǎng)期在戶外逾雄,建議涂擦SPF在8-12之間的防曬護(hù)膚品阀溶。</detail>
</zhishu>
<zhishu>
<name>洗車(chē)指數(shù)</name>
<value>不宜</value>
<detail>不宜洗車(chē)腻脏,未來(lái)24小時(shí)內(nèi)有雨,如果在此期間洗車(chē)银锻,雨水和路上的泥水可能會(huì)再次弄臟您的愛(ài)車(chē)永品。</detail>
</zhishu>
<zhishu>
<name>運(yùn)動(dòng)指數(shù)</name>
<value>較不宜</value>
<detail>有降雪,推薦您在室內(nèi)進(jìn)行低強(qiáng)度運(yùn)動(dòng)击纬;若堅(jiān)持戶外運(yùn)動(dòng)鼎姐,請(qǐng)選擇合適運(yùn)動(dòng)并注意保暖。</detail>
</zhishu>
<zhishu>
<name>約會(huì)指數(shù)</name>
<value>較不適宜</value>
<detail>室外有風(fēng)掉弛,而且有降雪症见,會(huì)給室外約會(huì)帶來(lái)不便,如果外出約會(huì)殃饿,請(qǐng)一定做好準(zhǔn)備谋作。</detail>
</zhishu>
<zhishu>
<name>雨傘指數(shù)</name>
<value>帶傘</value>
<detail>將有降雪,您在外出的時(shí)候一定要帶雨傘乎芳,以免弄濕衣物著涼遵蚜。</detail>
</zhishu>
</zhishus>
</resp>

代碼中具體解析示例

private void useXMLRequest() {
        String url = "https://www.sojson.com/open/api/weather/xml.shtml?city=%E5%8C%97%E4%BA%AC";
        XMLRequest xmlRequest = new XMLRequest(url, new Response.Listener<XmlPullParser>() {
            @Override
            public void onResponse(XmlPullParser response) {
                try {
                    int eventType = response.getEventType();
                    while (eventType != XmlPullParser.END_DOCUMENT){
                        switch (eventType){
                            case XmlPullParser.START_TAG:
                                String name = response.getName();
                                if ("city".equals(name)){
                                    mTextView.setText(response.nextText());                                }
                                break;
                        }
                        eventType = response.next();
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                mTextView.setText(error.getMessage());
            }
        });
        mQueue.add(xmlRequest);
    }

偷個(gè)懶,我就不具體解析這段XML了(笑~)奈惑,大家可以自己練練手吭净,熟悉XMLRequest的同時(shí)也可以復(fù)習(xí)以下基于PULL方式的XML解析。


總結(jié)

  • 本文詳細(xì)介紹了Volley肴甸,包括簡(jiǎn)單請(qǐng)求寂殉、圖片請(qǐng)求以及自定義請(qǐng)求的使用。
  • 筆者水平有限原在,如有錯(cuò)漏友扰,歡迎指正。
  • 接下來(lái)我將持續(xù)推出Android網(wǎng)絡(luò)相關(guān)的一系列文章庶柿,包括HttpURLConnection村怪、Volley、OkHttp3浮庐、Retrofit2的使用等甚负,有興趣可以關(guān)注whd_Alive的Android開(kāi)發(fā)筆記

歡迎關(guān)注whd_Alive的簡(jiǎn)書(shū)

  • 不定期分享Android開(kāi)發(fā)相關(guān)的技術(shù)干貨,期待與你的交流审残,共勉梭域。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市维苔,隨后出現(xiàn)的幾起案子碰辅,更是在濱河造成了極大的恐慌,老刑警劉巖介时,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡沸柔,警方通過(guò)查閱死者的電腦和手機(jī)循衰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)褐澎,“玉大人会钝,你說(shuō)我怎么就攤上這事」と” “怎么了迁酸?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)俭正。 經(jīng)常有香客問(wèn)我奸鬓,道長(zhǎng),這世上最難降的妖魔是什么掸读? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任串远,我火速辦了婚禮,結(jié)果婚禮上儿惫,老公的妹妹穿的比我還像新娘澡罚。我一直安慰自己,他們只是感情好肾请,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布留搔。 她就那樣靜靜地躺著,像睡著了一般铛铁。 火紅的嫁衣襯著肌膚如雪隔显。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,462評(píng)論 1 302
  • 那天避归,我揣著相機(jī)與錄音荣月,去河邊找鬼。 笑死梳毙,一個(gè)胖子當(dāng)著我的面吹牛哺窄,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播账锹,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼萌业,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了奸柬?” 一聲冷哼從身側(cè)響起生年,我...
    開(kāi)封第一講書(shū)人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎廓奕,沒(méi)想到半個(gè)月后抱婉,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體档叔,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年蒸绩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了衙四。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡患亿,死狀恐怖传蹈,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情步藕,我是刑警寧澤惦界,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站咙冗,受9級(jí)特大地震影響沾歪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜乞娄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一瞬逊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧仪或,春花似錦确镊、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至到旦,卻和暖如春旨巷,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背添忘。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工采呐, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人搁骑。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓斧吐,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親仲器。 傳聞我的和親對(duì)象是個(gè)殘疾皇子煤率,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容