[Android網(wǎng)絡(luò)庫]快速使用Android網(wǎng)絡(luò)

關(guān)于 Fast Android 網(wǎng)絡(luò)庫

Fast Android Networking Library 是一個強大的庫箕肃,用于在 Android 應(yīng)用程序中進(jìn)行任何類型的網(wǎng)絡(luò),它建立在OkHttp 網(wǎng)絡(luò)層之上咽安。

快速的 Android 網(wǎng)絡(luò)庫負(fù)責(zé)處理所有事情捍歪。因此,您無需執(zhí)行任何操作咒钟,只需發(fā)出請求并聽取響應(yīng)即可。

為什么使用快速安卓網(wǎng)絡(luò)若未?

  • 最近在 Android Marshmallow(Android M) 中刪除了 HttpClient朱嘴,這使得其他網(wǎng)絡(luò)庫過時了。
  • 沒有其他單個庫可以完成所有操作粗合,例如發(fā)出請求萍嬉、下載任何類型的文件、上傳文件隙疚、在 ImageView 中從網(wǎng)絡(luò)加載圖像等壤追。有一些庫,但它們已經(jīng)過時了供屉。
  • 沒有其他庫提供簡單的接口來執(zhí)行網(wǎng)絡(luò)中的所有類型的事情行冰,例如設(shè)置優(yōu)先級、取消等伶丐。
  • 由于它使用Okio资柔,因此在 android 應(yīng)用程序中沒有更多的 GC 開銷。 Okio用于在分配內(nèi)存時處理 GC 開銷撵割。 Okio做了一些聰明的事情來節(jié)省 CPU 和內(nèi)存贿堰。
  • 它使用OkHttp,更重要的是它支持 HTTP/2啡彬。

要求

Fast Android Networking Library 可以包含在任何 Android 應(yīng)用程序中羹与。

Fast Android Networking Library 支持 Android 2.3 (Gingerbread) 及更高版本。

在您的應(yīng)用程序中使用快速 Android 網(wǎng)絡(luò)庫

將此添加到您的 build.gradle

implementation 'com.amitshekhar.android:android-networking:1.0.2'

如果清單中不存在庶灿,請不要忘記在清單中添加互聯(lián)網(wǎng)權(quán)限

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

然后在應(yīng)用類的 onCreate() 方法中初始化:

AndroidNetworking.initialize(getApplicationContext());

通過一些自定義對其進(jìn)行初始化纵搁,因為它使用OkHttp作為網(wǎng)絡(luò)層,您可以在初始化時傳遞自定義 okHttpClient往踢。

// Adding an Network Interceptor for Debugging purpose :
OkHttpClient okHttpClient = new OkHttpClient() .newBuilder()
                        .addNetworkInterceptor(new StethoInterceptor())
                        .build();
AndroidNetworking.initialize(getApplicationContext(),okHttpClient);                        

使用帶有 Jackson Parser 的快速 Android 網(wǎng)絡(luò)

implementation 'com.amitshekhar.android:jackson-android-networking:1.0.2'
// Then set the JacksonParserFactory like below
AndroidNetworking.setParserFactory(new JacksonParserFactory());

發(fā)出 GET 請求

AndroidNetworking.get("https://fierce-cove-29863.herokuapp.com/getAllUsers/{pageNumber}")
                 .addPathParameter("pageNumber", "0")
                 .addQueryParameter("limit", "3")
                 .addHeaders("token", "1234")
                 .setTag("test")
                 .setPriority(Priority.LOW)
                 .build()
                 .getAsJSONArray(new JSONArrayRequestListener() {
                    @Override
                    public void onResponse(JSONArray response) {
                      // do anything with response
                    }
                    @Override
                    public void onError(ANError error) {
                      // handle error
                    }
                });                

發(fā)出 POST 請求

AndroidNetworking.post("https://fierce-cove-29863.herokuapp.com/createAnUser")
                 .addBodyParameter("firstname", "Amit")
                 .addBodyParameter("lastname", "Shekhar")
                 .setTag("test")
                 .setPriority(Priority.MEDIUM)
                 .build()
                 .getAsJSONObject(new JSONObjectRequestListener() {
                    @Override
                    public void onResponse(JSONObject response) {
                      // do anything with response
                    }
                    @Override
                    public void onError(ANError error) {
                      // handle error
                    }
                });

您還可以像這樣在 POST 請求中發(fā)布 java 對象腾誉、json、文件等。

User user = new User();
user.firstname = "Amit";
user.lastname = "Shekhar";

AndroidNetworking.post("https://fierce-cove-29863.herokuapp.com/createUser")
                 .addBodyParameter(user) // posting java object
                 .setTag("test")
                 .setPriority(Priority.MEDIUM)
                 .build()
                 .getAsJSONArray(new JSONArrayRequestListener() {
                    @Override
                    public void onResponse(JSONArray response) {
                      // do anything with response
                    }
                    @Override
                    public void onError(ANError error) {
                      // handle error
                    }
                });

JSONObject jsonObject = new JSONObject();
try {
    jsonObject.put("firstname", "Amit");
    jsonObject.put("lastname", "Shekhar");
} catch (JSONException e) {
  e.printStackTrace();
}

AndroidNetworking.post("https://fierce-cove-29863.herokuapp.com/createUser")
                 .addJSONObjectBody(jsonObject) // posting json
                 .setTag("test")
                 .setPriority(Priority.MEDIUM)
                 .build()
                 .getAsJSONArray(new JSONArrayRequestListener() {
                    @Override
                    public void onResponse(JSONArray response) {
                      // do anything with response
                    }
                    @Override
                    public void onError(ANError error) {
                      // handle error
                    }
                });

AndroidNetworking.post("https://fierce-cove-29863.herokuapp.com/postFile")
                 .addFileBody(file) // posting any type of file
                 .setTag("test")
                 .setPriority(Priority.MEDIUM)
                 .build()
                 .getAsJSONObject(new JSONObjectRequestListener() {
                    @Override
                    public void onResponse(JSONObject response) {
                      // do anything with response
                    }
                    @Override
                    public void onError(ANError error) {
                      // handle error
                    }
                });               

將它與您自己的 JAVA 對象一起使用 - JSON Parser

/*--------------Example One -> Getting the userList----------------*/
AndroidNetworking.get("https://fierce-cove-29863.herokuapp.com/getAllUsers/{pageNumber}")
                .addPathParameter("pageNumber", "0")
                .addQueryParameter("limit", "3")
                .setTag(this)
                .setPriority(Priority.LOW)
                .build()
                .getAsObjectList(User.class, new ParsedRequestListener<List<User>>() {
                    @Override
                    public void onResponse(List<User> users) {
                      // do anything with response
                      Log.d(TAG, "userList size : " + users.size());
                      for (User user : users) {
                        Log.d(TAG, "id : " + user.id);
                        Log.d(TAG, "firstname : " + user.firstname);
                        Log.d(TAG, "lastname : " + user.lastname);
                      }
                    }
                    @Override
                    public void onError(ANError anError) {
                     // handle error
                    }
                });
/*--------------Example Two -> Getting an user----------------*/
AndroidNetworking.get("https://fierce-cove-29863.herokuapp.com/getAnUserDetail/{userId}")
                .addPathParameter("userId", "1")
                .setTag(this)
                .setPriority(Priority.LOW)
                .build()
                .getAsObject(User.class, new ParsedRequestListener<User>() {
                     @Override
                     public void onResponse(User user) {
                        // do anything with response
                        Log.d(TAG, "id : " + user.id);
                        Log.d(TAG, "firstname : " + user.firstname);
                        Log.d(TAG, "lastname : " + user.lastname);
                     }
                     @Override
                     public void onError(ANError anError) {
                        // handle error
                     }
                 }); 
/*-- Note : YourObject.class, getAsObject and getAsObjectList are important here --*/              

從服務(wù)器下載文件

AndroidNetworking.download(url,dirPath,fileName)
                 .setTag("downloadTest")
                 .setPriority(Priority.MEDIUM)
                 .build()
                 .setDownloadProgressListener(new DownloadProgressListener() {
                    @Override
                    public void onProgress(long bytesDownloaded, long totalBytes) {
                      // do anything with progress  
                    }
                 })
                 .startDownload(new DownloadListener() {
                    @Override
                    public void onDownloadComplete() {
                      // do anything after completion
                    }
                    @Override
                    public void onError(ANError error) {
                      // handle error    
                    }
                });                 

上傳文件到服務(wù)器

AndroidNetworking.upload(url)
                 .addMultipartFile("image",file)    
                 .addMultipartParameter("key","value")
                 .setTag("uploadTest")
                 .setPriority(Priority.HIGH)
                 .build()
                 .setUploadProgressListener(new UploadProgressListener() {
                    @Override
                    public void onProgress(long bytesUploaded, long totalBytes) {
                      // do anything with progress 
                    }
                 })
                 .getAsJSONObject(new JSONObjectRequestListener() {
                    @Override
                    public void onResponse(JSONObject response) {
                      // do anything with response                
                    }
                    @Override
                    public void onError(ANError error) {
                      // handle error 
                    }
                 }); 

在另一個線程執(zhí)行器中獲取響應(yīng)和完成

(注意:錯誤和進(jìn)度將始終在應(yīng)用程序的主線程中返回)

AndroidNetworking.upload(url)
                 .addMultipartFile("image",file)  
                 .addMultipartParameter("key","value")  
                 .setTag("uploadTest")
                 .setPriority(Priority.HIGH)
                 .build()
                 .setExecutor(Executors.newSingleThreadExecutor()) // setting an executor to get response or completion on that executor thread
                 .setUploadProgressListener(new UploadProgressListener() {
                    @Override
                    public void onProgress(long bytesUploaded, long totalBytes) {
                      // do anything with progress 
                    }
                 })
                 .getAsJSONObject(new JSONObjectRequestListener() {
                    @Override
                    public void onResponse(JSONObject response) {
                      // below code will be executed in the executor provided
                      // do anything with response                
                    }
                    @Override
                    public void onError(ANError error) {
                      // handle error 
                    }
                 }); 

如果請求已完成給定閾值利职,則設(shè)置不取消請求的百分比閾值

AndroidNetworking.download(url,dirPath,fileName)
                 .setTag("downloadTest")
                 .setPriority(Priority.MEDIUM)
                 .setPercentageThresholdForCancelling(50) // even if at the time of cancelling it will not cancel if 50% 
                 .build()                                 // downloading is done.But can be cancalled with forceCancel.
                 .setDownloadProgressListener(new DownloadProgressListener() {
                    @Override
                    public void onProgress(long bytesDownloaded, long totalBytes) {
                      // do anything with progress  
                    }
                 })
                 .startDownload(new DownloadListener() {
                    @Override
                    public void onDownloadComplete() {
                      // do anything after completion
                    }
                    @Override
                    public void onError(ANError error) {
                      // handle error    
                    }
                });   

取消請求趣效。

任何帶有給定標(biāo)簽的請求都可以被取消。就這樣吧猪贪。

AndroidNetworking.cancel("tag"); // All the requests with the given tag will be cancelled.
AndroidNetworking.forceCancel("tag");  // All the requests with the given tag will be cancelled , even if any percent threshold is
                                       // set , it will be cancelled forcefully. 
AndroidNetworking.cancelAll(); // All the requests will be cancelled.  
AndroidNetworking.forceCancelAll(); // All the requests will be cancelled , even if any percent threshold is
                               // set , it will be cancelled forcefully.                           

從網(wǎng)絡(luò)加載圖像到 ImageView

      <com.androidnetworking.widget.ANImageView
          android:id="@+id/imageView"
          android:layout_width="100dp"
          android:layout_height="100dp"
          android:layout_gravity="center" />

      imageView.setDefaultImageResId(R.drawable.default);
      imageView.setErrorImageResId(R.drawable.error);
      imageView.setImageUrl(imageUrl);          

使用某些指定參數(shù)從 url 獲取位圖

AndroidNetworking.get(imageUrl)
                 .setTag("imageRequestTag")
                 .setPriority(Priority.MEDIUM)
                 .setBitmapMaxHeight(100)
                 .setBitmapMaxWidth(100)
                 .setBitmapConfig(Bitmap.Config.ARGB_8888)
                 .build()
                 .getAsBitmap(new BitmapRequestListener() {
                    @Override
                    public void onResponse(Bitmap bitmap) {
                    // do anything with bitmap
                    }
                    @Override
                    public void onError(ANError error) {
                      // handle error
                    }
                });

錯誤代碼處理

public void onError(ANError error) {
   if (error.getErrorCode() != 0) {
        // received error from server
        // error.getErrorCode() - the error code from server
        // error.getErrorBody() - the error body from server
        // error.getErrorDetail() - just an error detail
        Log.d(TAG, "onError errorCode : " + error.getErrorCode());
        Log.d(TAG, "onError errorBody : " + error.getErrorBody());
        Log.d(TAG, "onError errorDetail : " + error.getErrorDetail());
        // get parsed error object (If ApiError is your class)
        ApiError apiError = error.getErrorAsObject(ApiError.class);
   } else {
        // error.getErrorDetail() : connectionError, parseError, requestCancelledError
        Log.d(TAG, "onError errorDetail : " + error.getErrorDetail());
   }
}

從緩存中刪除位圖或清除緩存

AndroidNetworking.evictBitmap(key); // remove a bitmap with key from LruCache
AndroidNetworking.evictAllBitmap(); // clear LruCache

預(yù)取請求(以便在需要時立即從緩存中返回)

AndroidNetworking.get("https://fierce-cove-29863.herokuapp.com/getAllUsers/{pageNumber}")
                .addPathParameter("pageNumber", "0")
                .addQueryParameter("limit", "30")
                .setTag(this)
                .setPriority(Priority.LOW)
                .build()
                .prefetch();

為特定請求自定義 OkHttpClient

OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
                .addInterceptor(new GzipRequestInterceptor())
                .build();

AndroidNetworking.get("https://fierce-cove-29863.herokuapp.com/getAllUsers/{pageNumber}")
                 .addPathParameter("pageNumber", "0")
                 .addQueryParameter("limit", "3")
                 .addHeaders("token", "1234")
                 .setTag("test")
                 .setPriority(Priority.LOW)
                 .setOkHttpClient(okHttpClient) // passing a custom okHttpClient 
                 .build()
                 .getAsJSONArray(new JSONArrayRequestListener() {
                    @Override
                    public void onResponse(JSONArray response) {
                      // do anything with response
                    }
                    @Override
                    public void onError(ANError error) {
                    // handle error
                    }
                });

提出條件請求(構(gòu)建請求)

ANRequest.GetRequestBuilder getRequestBuilder = new ANRequest.GetRequestBuilder(ApiEndPoint.BASE_URL + ApiEndPoint.CHECK_FOR_HEADER);

if(isHeaderRequired){
 getRequestBuilder.addHeaders("token", "1234");
}

if(executorRequired){
 getRequestBuilder.setExecutor(Executors.newSingleThreadExecutor());
}

ANRequest anRequest = getRequestBuilder.build();       

anRequest.getAsJSONObject(new JSONObjectRequestListener() {
    @Override
    public void onResponse(JSONObject response) {
      // do anything with response
    }
    @Override
    public void onError(ANError error) {
      // handle error
    }
});

ConnectionClass Listener 獲取當(dāng)前網(wǎng)絡(luò)質(zhì)量和帶寬

// Adding Listener
AndroidNetworking.setConnectionQualityChangeListener(new ConnectionQualityChangeListener() {
            @Override
            public void onChange(ConnectionQuality currentConnectionQuality, int currentBandwidth) {
              // do something on change in connectionQuality
            }
        });

// Removing Listener   
AndroidNetworking.removeConnectionQualityChangeListener();

// Getting current ConnectionQuality
ConnectionQuality connectionQuality = AndroidNetworking.getCurrentConnectionQuality();
if(connectionQuality == ConnectionQuality.EXCELLENT) {
  // do something
} else if (connectionQuality == ConnectionQuality.POOR) {
  // do something
} else if (connectionQuality == ConnectionQuality.UNKNOWN) {
  // do something
}
// Getting current bandwidth
int currentBandwidth = AndroidNetworking.getCurrentBandwidth(); // Note : if (currentBandwidth == 0) : means UNKNOWN

通過設(shè)置 AnalyticsListener 來獲取請求的分析

AndroidNetworking.download(url,dirPath,fileName)
                 .setTag("downloadTest")
                 .setPriority(Priority.MEDIUM)
                 .build()
                 .setAnalyticsListener(new AnalyticsListener() {
                      @Override
                      public void onReceived(long timeTakenInMillis, long bytesSent, long bytesReceived, boolean isFromCache) {
                          Log.d(TAG, " timeTakenInMillis : " + timeTakenInMillis);
                          Log.d(TAG, " bytesSent : " + bytesSent);
                          Log.d(TAG, " bytesReceived : " + bytesReceived);
                          Log.d(TAG, " isFromCache : " + isFromCache);
                      }
                  })
                 .setDownloadProgressListener(new DownloadProgressListener() {
                    @Override
                    public void onProgress(long bytesDownloaded, long totalBytes) {
                      // do anything with progress  
                    }
                 })
                 .startDownload(new DownloadListener() {
                    @Override
                    public void onDownloadComplete() {
                      // do anything after completion
                    }
                    @Override
                    public void onError(ANError error) {
                      // handle error    
                    }
                });  
Note : If bytesSent or bytesReceived is -1 , it means it is unknown                

在響應(yīng)中獲取 OkHttpResponse

AndroidNetworking.get("https://fierce-cove-29863.herokuapp.com/getAnUserDetail/{userId}")
                .addPathParameter("userId", "1")
                .setTag(this)
                .setPriority(Priority.LOW)
                .setUserAgent("getAnUser")
                .build()
                .getAsOkHttpResponseAndParsed(new TypeToken<User>() {
                }, new OkHttpResponseAndParsedRequestListener<User>() {
                    @Override
                    public void onResponse(Response okHttpResponse, User user) {
                      // do anything with okHttpResponse and user
                    }
                    @Override
                    public void onError(ANError anError) {
                      // handle error
                    }
                });

發(fā)出同步請求

ANRequest request = AndroidNetworking.get("https://fierce-cove-29863.herokuapp.com/getAllUsers/{pageNumber}")
                        .addPathParameter("pageNumber", "0")
                        .addQueryParameter("limit", "3")
                        .build();
ANResponse<List<User>> response = request.executeForObjectList(User.class);
if (response.isSuccess()) {
   List<User> users = responseTwo.getResult();
} else {
   //handle error
}                                        

緩存如何工作跷敬?

  • 首先,服務(wù)器必須在標(biāo)頭中發(fā)送緩存控制热押,以便開始工作西傀。
  • 響應(yīng)將根據(jù)緩存控制 max-age,max-stale 進(jìn)行緩存。
  • 如果互聯(lián)網(wǎng)已連接并且年齡未過期桶癣,它將從緩存中返回拥褂。
  • 如果互聯(lián)網(wǎng)已連接并且年齡已過期,并且如果服務(wù)器返回 304(未修改)牙寞,它將從緩存中返回饺鹃。
  • 如果您使用 getResponseOnlyIfCached() 時未連接互聯(lián)網(wǎng) - 即使日期已過期,它也會從緩存中返回碎税。
  • 如果未連接互聯(lián)網(wǎng)尤慰,如果您不使用 getResponseOnlyIfCached() - 它不會返回任何內(nèi)容馏锡。
  • 如果您使用 getResponseOnlyFromNetwork() 雷蹂,它只會在服務(wù)器驗證后返回響應(yīng)。
  • 如果設(shè)置了緩存控制杯道,它將根據(jù)服務(wù)器返回的 max-age,max-stale 工作匪煌。
  • 如果未連接互聯(lián)網(wǎng),則獲取緩存響應(yīng)的唯一方法是使用 getResponseOnlyIfCached()党巾。

啟用日志記錄

AndroidNetworking.enableLogging(); // simply enable logging
AndroidNetworking.enableLogging(LEVEL.HEADERS); // enabling logging with level

啟用從客戶端到服務(wù)器的 GZIP

// Enabling GZIP for Request (Not needed if your server doesn't support GZIP Compression), anyway responses 
// from server are automatically unGzipped if required. So enable it only if you need your request to be 
// Gzipped before sending to server(Make sure your server support GZIP Compression).
OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
                .addInterceptor(new GzipRequestInterceptor())
                .build();
AndroidNetworking.initialize(getApplicationContext(),okHttpClient);                

重要的提示

  • 謹(jǐn)慎使用 IMMEDIATE 優(yōu)先級 - 僅在需要 1 或 2 個(最多 2 個)IMMEDIATE 請求時才在適當(dāng)?shù)奈恢檬褂梦ァ7駝t使用高優(yōu)先級。

  • 已知錯誤:如果您在客戶端到服務(wù)器之間使用 GZIP 攔截器齿拂,則上傳進(jìn)度在 Multipart 中無法正常工作驳规。

    如果您將 Proguard 與 Gradle 構(gòu)建系統(tǒng)一起使用(通常是這種情況),則無需執(zhí)行任何操作署海。將自動應(yīng)用相應(yīng)的 Proguard 規(guī)則吗购。如果還需要應(yīng)用中的規(guī)則proguard-rules.pro,如下:

    -dontwarn okio.**
    
    

快速 Android 網(wǎng)絡(luò)庫支持

  • Fast Android Networking Library 支持所有類型的 HTTP/HTTPS 請求砸狞,例如 GET捻勉、POST、DELETE刀森、HEAD踱启、PUT、PATCH
  • Fast Android Networking Library 支持下載任何類型的文件
  • Fast Android Networking Library 支持上傳任何類型的文件(支持分段上傳)
  • Fast Android Networking Library 支持取消請求
  • Fast Android Networking Library 支持為任何請求設(shè)置優(yōu)先級(LOW、MEDIUM埠偿、HIGH透罢、IMMEDIATE)
  • Fast Android Networking Library 支持RxJava

由于它使用OkHttp作為網(wǎng)絡(luò)層,它支持:

  • Fast Android Networking Library 支持 HTTP/2 支持允許對同一主機的所有請求共享一個套接字
  • Fast Android Networking Library 使用連接池來減少請求延遲(如果 HTTP/2 不可用)
  • 透明 GZIP 縮小下載大小
  • Fast Android Networking Library 支持響應(yīng)緩存胚想,完全避免網(wǎng)絡(luò)重復(fù)請求

與其他網(wǎng)絡(luò)庫的區(qū)別

  • 在 Fast Android Networking Library 中琐凭,OkHttpClient 可以很容易地為每個請求定制——比如每個請求的超時定制等。
  • 由于 Fast Android Networking Library 使用OkHttp和Okio浊服,因此速度更快统屈。
  • 適用于所有類型網(wǎng)絡(luò)的單一庫。
  • 支持 RxJava牙躺、RxJava2 愁憔。
  • 可以獲取當(dāng)前的帶寬和連接質(zhì)量來決定代碼的邏輯。
  • Executor 可以傳遞給任何請求以在另一個線程中獲取響應(yīng)孽拷。
  • 可以獲得任何請求的完整分析吨掌。
  • 所有類型的定制都是可能的。
  • 即時請求現(xiàn)在真的是即時的脓恕。
  • 可以對任何請求進(jìn)行預(yù)取膜宋,以便在需要時從緩存中提供即時數(shù)據(jù)。
  • 適當(dāng)?shù)恼埱笕∠?/li>
  • 如果完成的請求超過特定閾值百分比炼幔,則防止取消請求秋茫。
  • 一個簡單的接口,可以發(fā)出任何類型的請求乃秀。
  • 適當(dāng)?shù)捻憫?yīng)緩存——這會導(dǎo)致帶寬使用減少肛著。

全部

  • 與其他庫集成
  • 當(dāng)然還有許多功能和錯誤修復(fù)

學(xué)分

  • Square - 由于Fast Android Networking 使用的OkHttp和Okio 都是由Square開發(fā)的。
  • Volley-As Fast Android Networking 使用由Volley開發(fā)的 ImageLoader 跺讯。
  • Prashant Gupta - 對于 RxJava枢贿,RxJava2 支持 - RxJava 支持。

作者:amitshekhariitbhu
鏈接:https://github.com/amitshekhariitbhu/Fast-Android-Networking

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末刀脏,一起剝皮案震驚了整個濱河市局荚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌愈污,老刑警劉巖耀态,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異钙畔,居然都是意外死亡茫陆,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門擎析,熙熙樓的掌柜王于貴愁眉苦臉地迎上來簿盅,“玉大人挥下,你說我怎么就攤上這事〗按祝” “怎么了棚瘟?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長喜最。 經(jīng)常有香客問我偎蘸,道長,這世上最難降的妖魔是什么瞬内? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任迷雪,我火速辦了婚禮,結(jié)果婚禮上虫蝶,老公的妹妹穿的比我還像新娘章咧。我一直安慰自己,他們只是感情好能真,可當(dāng)我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布赁严。 她就那樣靜靜地躺著,像睡著了一般粉铐。 火紅的嫁衣襯著肌膚如雪疼约。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天蝙泼,我揣著相機與錄音程剥,去河邊找鬼。 笑死踱承,一個胖子當(dāng)著我的面吹牛倡缠,可吹牛的內(nèi)容都是我干的哨免。 我是一名探鬼主播茎活,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼琢唾!你這毒婦竟也來了载荔?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤采桃,失蹤者是張志新(化名)和其女友劉穎懒熙,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體普办,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡工扎,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了衔蹲。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片肢娘。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出橱健,到底是詐尸還是另有隱情而钞,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響熔萧,放射性物質(zhì)發(fā)生泄漏审轮。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一缚陷、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦途凫、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至促王,卻和暖如春犀盟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蝇狼。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工阅畴, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人迅耘。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓贱枣,卻偏偏與公主長得像,于是被迫代替她去往敵國和親颤专。 傳聞我的和親對象是個殘疾皇子纽哥,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,762評論 2 345

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