使用Retrofit

Retrofit 實(shí)際上并不能說是一個(gè)網(wǎng)絡(luò)請(qǐng)求框架鹰服,它其實(shí)是對(duì) okHttp 這個(gè)網(wǎng)絡(luò)請(qǐng)求框架在接口層面的封裝,網(wǎng)絡(luò)請(qǐng)求還是交給 okHttp 做的,就好像 HttpClient 和 Volley 的關(guān)系一樣。Retrofit 對(duì) Header、Url捡需、請(qǐng)求參數(shù)等信息進(jìn)行封裝,交給 okHttp 去做網(wǎng)絡(luò)請(qǐng)求忿等,okHttp 從服務(wù)器獲得的請(qǐng)求結(jié)果交給 Retrofit 去進(jìn)行解析栖忠,所以經(jīng)常有說 okHttp + Retrofit 這樣搭配使用。

依賴
compile 'com.squareup.retrofit2:retrofit:2.1.0'

因?yàn)?Retrofit2.X 里面內(nèi)部導(dǎo)入了 okHttp3,所以可以不用在導(dǎo)入 okHttp 的包庵寞。

使用 Retrofit 進(jìn)行網(wǎng)絡(luò)請(qǐng)求的步驟

1.獲得 Retrofit 實(shí)例狸相,可進(jìn)行某些功能的配置(響應(yīng)結(jié)果類型轉(zhuǎn)化、攔截器攔截請(qǐng)求日志等)捐川;
2.創(chuàng)建請(qǐng)求接口脓鹃,在該接口內(nèi)創(chuàng)建返回 Call 對(duì)象的相應(yīng)請(qǐng)求方法(在方法內(nèi)使用注解,靜態(tài)/動(dòng)態(tài)設(shè)置請(qǐng)求參數(shù)古沥、請(qǐng)求方式等)瘸右;
3.Retrofit 實(shí)例調(diào)用 create (請(qǐng)求接口)獲得接口對(duì)象,調(diào)用相應(yīng)請(qǐng)求方法獲得 Call 對(duì)象岩齿,Call 對(duì)象調(diào)用同步/異步請(qǐng)求方法發(fā)出請(qǐng)求,獲得響應(yīng)結(jié)果太颤;

獲得 Retrofit 實(shí)例

基本上,生成一個(gè) Retrofit 實(shí)例盹沈,需要配置三塊內(nèi)容:
1.baseUrl:.baseUrl()龄章,傳入請(qǐng)求地址的根目錄,通常傳入的是 String 乞封,也可以傳入 HttpUrl 對(duì)象做裙,其實(shí)傳入的 String 最后還是會(huì)生成一個(gè) HttpUrl 對(duì)象;
2.OkHttpClient 對(duì)象:.client(OkHttpClient client)/callFactory(okhttp3.Call.Factory factory)肃晚,其實(shí)前者只是后者的方便寫法锚贱,前者實(shí)際上內(nèi)部實(shí)現(xiàn)還是調(diào)用后者,而設(shè)置攔截器查看日志关串、設(shè)置Header等等拧廊,都是在構(gòu)造 OkHttpClient 對(duì)象的時(shí)候設(shè)置好的,怎么構(gòu)建 OKHttpClient 對(duì)象晋修,可以看我這一篇博客:使用okHttp 里面的相關(guān)內(nèi)容卦绣;
3.Converter.Factory 對(duì)象:.addConverterFactory(Converter.Factory factory),對(duì)相應(yīng)結(jié)果中的數(shù)據(jù)做類型轉(zhuǎn)換飞蚓,Retrofit 提供了很多數(shù)據(jù)類型的 ConverterFactory,直接導(dǎo)入即可使用廊蜒,譬如:

Gson: com.squareup.retrofit2:converter-gson
Jackson: com.squareup.retrofit2:converter-jackson
Moshi: com.squareup.retrofit2:converter-moshi
Protobuf: com.squareup.retrofit2:converter-protobuf
Wire: com.squareup.retrofit2:converter-wire
Simple XML: com.squareup.retrofit2:converter-simplexml
Scalars (primitives, boxed, and String): com.squareup.retrofit2:converter-scalars

當(dāng)然趴拧,也可以繼承 Converter.Factory 去自定義需要的 Factory 。
注意:Converter.Factory 對(duì)象可以添加多個(gè)山叮,但添加的順序是有影響的著榴,按照retrofit的邏輯,是從前往后進(jìn)行匹配屁倔,如果匹配上脑又,就忽略后面的,直接使用。
eg:當(dāng) Retrofit 試圖反序列化一個(gè) proto 格式问麸,它其實(shí)會(huì)被當(dāng)做 JSON 來對(duì)待往衷。所以 Retrofit 會(huì)先要檢查 proto buffer 格式,然后才是 JSON严卖。所以要先添加 ProtoConverterFactory席舍,然后是 GsonConverterFactory。

好了哮笆,看一下用代碼創(chuàng)建 Retrofit 實(shí)例:

// 請(qǐng)求地址的根目錄
String BASE_URL= "http://gank.avosapps.com/api/data/";
        
// 構(gòu)建做好相關(guān)配置的 OkHttpClient 對(duì)象
OkHttpClient okHttpClient = new OkHttpClient();

// 獲得 Converter.Factory 對(duì)象
GsonConverterFactory gsonConverterFactory =  GsonConverterFactory.create();
        
// 獲得 Retrofit 實(shí)例
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl(BASE_URL)
        .client(okHttpClient)
        .addConverterFactory(gsonConverterFactory)
        .build();

Retrofit 還可以有其它配置来颤,但這里不展開說了。

創(chuàng)建請(qǐng)求接口

這是Retrofit 使用上和 OKHttp 最不一樣的地方稠肘,重點(diǎn)是使用到了注解福铅。

同樣地,看一下最常用的 Get 請(qǐng)求项阴、Post 請(qǐng)求是怎么做的滑黔。

Get 請(qǐng)求

既然已經(jīng)在獲得 Retrofit 實(shí)例的時(shí)候傳入了根目錄,所以鲁冯,在請(qǐng)求的時(shí)候就可以直接寫完整請(qǐng)求地址除根目錄外的其它部分拷沸,根據(jù)不同的情況,Retrofit 給我們提供了下面幾種注解:

@Path
使用 @Path 可以動(dòng)態(tài)地訪問不同的url薯演,舉個(gè)例子:
簡書一篇文章的url是這樣的:

http://www.reibang.com/p/08ad8934ad2e

http://www.reibang.com 是根目錄撞芍,p 是文章目錄文件夾(猜測(cè)),08ad8934ad2e是文章 ID跨扮。那么很顯然只要傳入文章 ID序无,就可以請(qǐng)求對(duì)應(yīng)的文章,文章 ID 不是拼接的參數(shù)而是路徑的一部分衡创,那么就可以使用 @Path 了:

/**
 * 請(qǐng)求接口
 * Created by Eman on 2016/12/12.
 */
public interface TestApiService {

    // 完整目錄
    // http://www.reibang.com/p/08ad8934ad2e
    
    /**
     * 請(qǐng)求簡書文章的 API
     * @param articleId 文章 ID
     * @return Call
     */
    @GET("p/{articleId}")
    Call<ArticleBean> article(@Path("articleId") String articleId);
}

/**
 * 簡書文章實(shí)體
 * Created by Eman on 2016/12/12.
 */
public class ArticleBean {
    // 文章標(biāo)題
    String title;
    // 文章內(nèi)容
    String content;
}

這里一步步來解析:
① @GET表示請(qǐng)求方式帝嗡,Retrofit 支持的請(qǐng)求方式還有 @Post、@Delete璃氢、@Put 等哟玷,()里面的內(nèi)容是除根目錄外的剩余路徑;
② 請(qǐng)求接口的方法一定要返回 Call<T> 對(duì)象一也,T 是 Retrofit 對(duì)響應(yīng)內(nèi)容進(jìn)行數(shù)據(jù)類型轉(zhuǎn)換后的數(shù)據(jù)實(shí)體巢寡,上面例子的就是ArticleBean。

接下來就可以說一下 @Path 了:
① 動(dòng)態(tài)獲取的部分路徑用{}包含起來椰苟;
② @Path(XXX) 里面的 XXX 要最好和 {XXX} 保持一致(不一致其實(shí)也沒問題)抑月;
③ @Path 可以用于任何請(qǐng)求方式,包括 Post舆蝴,Put谦絮,Delete 等等题诵。

@Url
使用全路徑復(fù)寫 baseUrl,適用于非統(tǒng)一 baseUrl 的場(chǎng)景层皱。意思是性锭,我們?cè)趧?chuàng)建 Retrofit 實(shí)例的時(shí)候傳入了請(qǐng)求地址的根目錄,但有時(shí)候偏偏有些請(qǐng)求地址根本不是 baseUrl 下的奶甘,那么就可以使用 @Url 這個(gè)注解:

// 原BaseUrl
// http://www.reibang.com/

// 現(xiàn)在需要的Url
// http://www.reibang.com/writer#/notebooks/8255432/notes/7513289
    
/**
 * 請(qǐng)求編輯簡書文章的API
 * @param url 編輯簡書文章的請(qǐng)求地址
 * @return Call
 */
@GET
Call<WriteArticleBean> writeArticle(@Url String url);

注意:@Url 這個(gè)注解同樣可以給 @POST篷店、@PUT、@DELETE 這幾種請(qǐng)求使用臭家。

@Query
這個(gè)注解是用來完成 Get 請(qǐng)求的傳參的疲陕,繼續(xù)用獲取簡書文章作為例子,假設(shè)文章 ID 是請(qǐng)求參數(shù):

// 完整目錄
// http://www.reibang.com/p?userId=2653577186&articleId=08ad8934ad2e
    
/**
 * 請(qǐng)求簡書文章的API
 * @param userId用戶 ID
 * @param articleId 文章 ID
 * @return Call
 */
@GET("p")
Call<ArticleBean> article(@Query("userId") int userId, @Query("articleId") int articleId);

這樣就可以實(shí)現(xiàn) Get 請(qǐng)求的傳參了钉赁,不過需要注意的是:
① “?”不用寫進(jìn)去了蹄殃;
② 一個(gè)@Query 對(duì)應(yīng)一個(gè)參數(shù),注意參數(shù)名和參數(shù)類型你踩;
③ 如果請(qǐng)求參數(shù)為非必填诅岩,也就是說即使不傳該參數(shù),服務(wù)端也可以正常解析带膜,那么吩谦,請(qǐng)求方法定義處還是需要 完整的 Query 注解,某次請(qǐng)求如果不需要傳該參數(shù)的話膝藕,只需填充 null 即可式廷。

@QueryMap
雖然 @Query 就可以傳參了,但如果有多個(gè)請(qǐng)求參數(shù)芭挽,很難說不會(huì)寫錯(cuò)滑废,所以可以用 @QueryMap,直接傳入一個(gè)包含了多個(gè)請(qǐng)求參數(shù)的 Map:

// 完整目錄
// http://www.reibang.com/p?userId=2653577186&articleId=08ad8934ad2e
    
/**
 * 請(qǐng)求簡書文章的API
 * @param Map 請(qǐng)求參數(shù)集合
 * @return Call
 */
@GET("p")
Call<ArticleBean> article(@QueryMap Map<String, Object> params);

基本上 Get 請(qǐng)求使用這幾種注解就足夠了袜爪,Post 請(qǐng)求面對(duì)的情況更多蠕趁,來看一下 Post 請(qǐng)求。

Post請(qǐng)求

首先辛馆,Post 請(qǐng)求在不要求請(qǐng)求參數(shù)的時(shí)候和 Get 請(qǐng)求是一樣的俺陋,只是需要把注解換成 @Post,同樣使用 @Path 也是一樣的昙篙。所以來看 Post 請(qǐng)求各種需要請(qǐng)求參數(shù)的情況倔韭。

@Field

/**
 * 簡書登錄 API
 * @param username 用戶名
 * @param password 密碼
 * @return Call
 */
@FormUrlEncoded
@POST("login/")
Call<UserBean> login(@Field("username") String username, @Field("password") String password);

同樣的,也可以把請(qǐng)求參數(shù)放在一起瓢对,使用注解 @FieldMap

@FieldMap

/**
 * 簡書登錄 API
 * @param params 請(qǐng)求參數(shù)集合
 * @return Call
 */
@FormUrlEncoded
@POST("login/")
Call<UserBean> login(@FieldMap HashMap<String, String> params);

注意:
① @Field 和 @FieldMap 都屬于表單傳值,要加上 @FormUrlEncoded 胰苏,它將會(huì)自動(dòng)將請(qǐng)求參數(shù)的類型調(diào)整為application/x-www-form-urlencoded硕蛹;
② @Field 將每一個(gè)請(qǐng)求參數(shù)都存放至請(qǐng)求體中醇疼,還可以添加 encoded 參數(shù),該參數(shù)為 boolean 型法焰,具體的用法為:

@Field(value = "username", encoded = true) String username

encoded 參數(shù)為 true 的話秧荆,key-value-pair 將會(huì)被編碼,即將中文和特殊字符進(jìn)行編碼轉(zhuǎn)換埃仪。

@Body
如果請(qǐng)求參數(shù)不是基本數(shù)據(jù)類型乙濒,譬如想直接上傳一個(gè) JSON,或者一個(gè)封裝好的實(shí)體類對(duì)象(與后臺(tái)協(xié)商好卵蛉,將一堆請(qǐng)求參數(shù)封裝進(jìn)一個(gè)對(duì)象里面簡直太方便)颁股,就可以使用這個(gè)注解,直接把對(duì)象通過ConverterFactory轉(zhuǎn)化成對(duì)應(yīng)的參數(shù):

/**
 * 簡書登錄 API
 * @param user 用戶實(shí)體
 * @return Call
 */
@POST("login/")
Call<UserBean> login(@Body User user);

@Part
如果想實(shí)現(xiàn)上傳更多不同類型的請(qǐng)求參數(shù)數(shù)據(jù)呢傻丝?譬如文件的上傳甘有,請(qǐng)看:

/**
 * 簡書上傳圖片 API
 * @param imgName 圖片名
 * @param description 圖片描述
 * @param imgFile 圖片文件
 * @return Call
 */
@Multipart
@POST("p/unload")
Call<ArticleBean> upload(@Part("imgName") String imgName,
                         @Part("description") RequestBody description,
                         @Part MultipartBody.Part imgFile);

這里要注意了:
① @Multipart 表示允許使用多個(gè) @Part;
② 每一個(gè) @Part 對(duì)應(yīng)的是一個(gè) key-value,value 可以是任何值葡缰,譬如上面例子的 String亏掀,但最好是 RequestBody,就算 description 的內(nèi)容是String泛释,那也要構(gòu)造出一個(gè) RequestBody 再放進(jìn)請(qǐng)求方法內(nèi)滤愕;eg:

// description 內(nèi)容
String description = "It is the description";
// 構(gòu)造成 RequestBody
RequestBody qbDescription = RequestBody.create(MediaType.parse(multipart/form-data), description);

③ File 不是直接使用 RequestBody,而是使用它的子類 MultipartBody 的內(nèi)部類 Part怜校,對(duì)應(yīng) @Part间影;eg:

// 1.獲得File對(duì)象
File file = new File(Environment.getExternalStorageDirectory(), "icon.png");
// 2.構(gòu)造RequestBody對(duì)象
RequestBody qbImgFile = RequestBody.create(MediaType.parse("image/png"), file);
// 3.添上 key,key為 String 類型韭畸,代表上傳的鍵值對(duì)的 key 
// (與服務(wù)器接受的 key 對(duì)應(yīng))宇智,value 是我們構(gòu)造的 MultipartBody.Part對(duì)象
MultipartBody.Part imgFile = MultipartBody.Part
                               .createFormData("imgFile", "icon.png", qbImgFile);

這里就有個(gè)疑惑了?不是一個(gè) @Part 對(duì)應(yīng)一個(gè) RequestBody 嗎胰丁?那到了第二步就應(yīng)該可以了才對(duì)随橘,那是因?yàn)?retrofit2 并沒有對(duì)文件做特殊處理,具體分析可以看鴻洋大神的Retrofit2 完全解析 探索與okhttp之間的關(guān)系里面的4.3.1點(diǎn)锦庸;

@PartMap

/**
 * 簡書上傳圖片 API
 * @param params part集合
 * @return Call
 */
@Multipart
@POST("p/unload")
Call<ArticleBean> upload(@PartMap Map<String, RequestBody> params);

注意:這里可以看到机蔗,value 是 RequestBody,那么文件又怎么辦呢甘萧?不是 MultipartBody.Part萝嘁,如果看了上面說明為什么文件不用 RequestBody 就明白了,構(gòu)造好 key 就沒問題了:

···
// 創(chuàng)建Map<String, RequestBody>對(duì)象
Map<String, RequestBody> map = new HashMap();
// 1.獲得File對(duì)象
File file = new File(Environment.getExternalStorageDirectory(), "icon.png");
// 2.構(gòu)造RequestBody對(duì)象
RequestBody qbImgFile = RequestBody.create(MediaType.parse("image/png"), file);
// 構(gòu)造上傳文件對(duì)應(yīng)的 key
String key = "imgFile" + ""; filename="" + file.getName();
map.put(key, qbImgFile);
···

第一個(gè) " 前面拼接的是服務(wù)器的 key扬卷,第二個(gè) " 后面拼接的是上傳的文件的文件名牙言。

當(dāng)然,多文件上傳也可以不用 @PathMap 的方式怪得,使用 @Part 有多少個(gè)文件要上傳咱枉,就構(gòu)建多少個(gè) MultipartBody 去對(duì)應(yīng)多少個(gè) @Path卑硫,但這樣上傳文件的請(qǐng)求方法里面參數(shù)就不確定了,如果每次固定上傳三個(gè)蚕断、五個(gè)欢伏,我覺得直接用 @Path ,而不是去拼接 key 亿乳,代碼看起來好很多硝拧。

獲得接口對(duì)象,調(diào)用請(qǐng)求方法發(fā)出請(qǐng)求

上面搞定了獲得 Retrofit 實(shí)例葛假,創(chuàng)建了請(qǐng)求接口障陶,并說了 Get 請(qǐng)求和 Post 請(qǐng)求的各種情況,那么桐款,接下來就是到怎么用它們?nèi)グl(fā)起請(qǐng)求了咸这。

TestApiService test = retrofit.create(TestApiService.class);

就這么簡單!接下來只要設(shè)置好請(qǐng)求參數(shù)魔眨,調(diào)用 TestApiService 里面的各個(gè)請(qǐng)求方法就可以發(fā)出請(qǐng)求了:

// 使用了@Path 的 Get 請(qǐng)求媳维,獲得Call對(duì)象
String articleId = "08ad8934ad2e";
Call<ArticleBean> call = test.article(articleId);

// Call調(diào)用異步請(qǐng)求
call.enqueue(new Callback<ArticleBean>() {
    @Override
    public void onResponse(Call<ArticleBean> call, Response<ArticleBean> response) {
        // 請(qǐng)求成功
        String result = response.body().string();
        System.out.println("異步請(qǐng)求結(jié)果: " + result);
    }
    @Override
    public void onFailure(Call<ArticleBean> call, Throwable t) {
        // 請(qǐng)求失敗
        String error = t.getMessage();
        System.out.println("請(qǐng)求出錯(cuò): " + error);
    }
});

// Call 調(diào)用同步請(qǐng)求
Response<ArticleBean> response = call.excute();
if(response.isSuccessful()) {
    System.out.println("同步請(qǐng)求成功");
} else {
    System.out.println("同步請(qǐng)求失敗");
}

上面那么多個(gè)例子,請(qǐng)求的方式都是一樣的遏暴,構(gòu)造好請(qǐng)求調(diào)用方法需要的請(qǐng)求參數(shù)侄刽,通過請(qǐng)求方法獲得 Call 對(duì)象,然后 Call 對(duì)象調(diào)用異步或者同步的請(qǐng)求方法獲得響應(yīng)朋凉,然后處理響應(yīng)就好州丹。

自定義Converter

這一塊我還是建議看一下鴻洋大神的Retrofit2 完全解析 探索與okhttp之間的關(guān)系里面的第4.4點(diǎn)。

Header

這里要特別說一下在 Retrofit 里面添加 Header杂彭,使用注解 @Header(動(dòng)態(tài)添加)墓毒、@Headers(靜態(tài)添加)、自定義攔截器定義 Header 并在 okHttpClient 里面添加亲怠。

@Header

/**
 * 請(qǐng)求簡書文章的 API
 * @param articleId 文章 ID
 * @param authoId 驗(yàn)證 ID
 * @return Call
 */
//動(dòng)態(tài)設(shè)置Header值
@GET("p/{articleId}")
Call<ArticleBean> article(@Path("articleId") String articleId, @Header("authoId") String authoId);

@Headers

/**
 * 請(qǐng)求簡書文章的 API
 * @param articleId 文章 ID
 * @return Call
 */
//靜態(tài)設(shè)置Header值所计,這里authorizationId就是上面方法里傳進(jìn)來變量的值
@Headers("authoId: authorizationId")
@GET("p/{articleId}")
Call<ArticleBean> article(@Path("articleId") String articleId);

// 設(shè)置多個(gè)Header值
@Headers({
    "Accept: application/vnd.github.v3.full+json", 
    "User-Agent: TestApp"
})

**自定義攔截器定義 Header **

public class RequestInterceptor implements Interceptor { 
    @Override 
    public Response intercept(Chain chain) throws IOException { 
        Request original = chain.request(); 
        Request request = original.newBuilder() 
                   .header("User-Agent", "TestApp") 
                   .header("Accept", "application/vnd.github.v3.full+json")
                   .method(original.method(), original.body()) 
                   .build(); 
        return chain.proceed(request); 
    }
}

在構(gòu)造 okHttpClient 對(duì)象的時(shí)候添加進(jìn)去就好。

在緩存中使用

// 設(shè)置 單個(gè)請(qǐng)求的 緩存時(shí)間
@Headers("Cache-Control: max-age=640000")
@GET("p/{articleId}")
Call<ArticleBean> article(@Path("articleId") String articleId);

其實(shí)緩存策略主要在 okHttpClient 里面就可以設(shè)置了团秽,具體的請(qǐng)看我這一篇博客:使用okHttp 里面的相關(guān)內(nèi)容主胧,但是現(xiàn)在 Retrofit 里面有 @Headers 設(shè)置單個(gè)請(qǐng)求緩存,就可以將緩存策略進(jìn)一步優(yōu)化(起碼攔截器實(shí)現(xiàn)緩存的缺點(diǎn)就不存在了),這里參考了這篇文章內(nèi)關(guān)于緩存的部分

// 離線讀取本地緩存习勤,在線獲取最新數(shù)據(jù)(讀取單個(gè)請(qǐng)求的請(qǐng)求頭踪栋,亦可統(tǒng)一設(shè)置)
private Interceptor cacheInterceptor() {
        return new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();

                if (!AppUtil.isNetworkReachable(sContext)) {
                    request = request.newBuilder()
                            //強(qiáng)制使用緩存
                            .cacheControl(CacheControl.FORCE_CACHE)
                            .build();
                }

                Response response = chain.proceed(request);

                if (AppUtil.isNetworkReachable(sContext)) {
                    //有網(wǎng)的時(shí)候讀接口上的@Headers里的配置,你可以在這里進(jìn)行統(tǒng)一的設(shè)置
                    String cacheControl = request.cacheControl().toString();
                    Logger.i("has network ,cacheControl=" + cacheControl);
                    return response.newBuilder()
                            .header("Cache-Control", cacheControl)
                            .removeHeader("Pragma")
                            .build();
                } else {
                    int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale
                    Logger.i("network error ,maxStale="+maxStale);
                    return response.newBuilder()
                            .header("Cache-Control", "public, only-if-cached, max-stale="+maxStale)
                            .removeHeader("Pragma")
                            .build();
                }

            }
        };
    }

同樣地图毕,將這個(gè)攔截器在 okHttpClient 創(chuàng)建的時(shí)候添加上就OK了夷都。

攔截器查看日志

這里也請(qǐng)看我這一篇博客:使用okHttp 里面的相關(guān)內(nèi)容,同樣是自定義好攔截器之后添加到 okHttpClient中予颤。

Retrofit 的基本使用就記錄到這里囤官,當(dāng)然還有一個(gè) CallAdapterFactory 的內(nèi)容厢破,這個(gè)我打算學(xué)習(xí) RxJava 之后,放進(jìn)去講治拿。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市笆焰,隨后出現(xiàn)的幾起案子劫谅,更是在濱河造成了極大的恐慌,老刑警劉巖嚷掠,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件捏检,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡不皆,警方通過查閱死者的電腦和手機(jī)贯城,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來霹娄,“玉大人能犯,你說我怎么就攤上這事∪埽” “怎么了踩晶?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長枕磁。 經(jīng)常有香客問我渡蜻,道長,這世上最難降的妖魔是什么计济? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任茸苇,我火速辦了婚禮,結(jié)果婚禮上沦寂,老公的妹妹穿的比我還像新娘学密。我一直安慰自己,他們只是感情好凑队,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布则果。 她就那樣靜靜地躺著,像睡著了一般漩氨。 火紅的嫁衣襯著肌膚如雪西壮。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天叫惊,我揣著相機(jī)與錄音款青,去河邊找鬼。 笑死霍狰,一個(gè)胖子當(dāng)著我的面吹牛抡草,可吹牛的內(nèi)容都是我干的饰及。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼康震,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼燎含!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起腿短,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤屏箍,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后橘忱,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體赴魁,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年钝诚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了颖御。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡凝颇,死狀恐怖潘拱,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情祈噪,我是刑警寧澤泽铛,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站辑鲤,受9級(jí)特大地震影響盔腔,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜月褥,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一弛随、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧宁赤,春花似錦舀透、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至佛猛,卻和暖如春惑芭,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背继找。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來泰國打工遂跟, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓幻锁,卻偏偏與公主長得像凯亮,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子哄尔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

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

  • 介紹 Retrofit把HTTP API改造成java接口. 使用Retrofit類生成一個(gè)GitHubServi...
    梵依然閱讀 1,219評(píng)論 2 6
  • 前言 2016年以來假消,越來越多Android開發(fā)者使用Retrofit作為HTTP請(qǐng)求框架。原因其一岭接,Google...
    鍵盤男閱讀 14,225評(píng)論 123 212
  • Retrofit是squareup公司的開源力作亿傅,和同屬squareup公司開源的OkHttp,一個(gè)負(fù)責(zé)網(wǎng)絡(luò)調(diào)度瘟栖,...
    藍(lán)灰_q閱讀 41,474評(píng)論 23 281
  • 往事成煙已飛去葵擎? 紅塵看淡誰在意? 雨上清明無人影半哟, 佳人已逝誰會(huì)意酬滤。
    雅俗共賞Y閱讀 196評(píng)論 0 0
  • 我是說不出什么的。只覺得內(nèi)心安靜而彷徨寓涨。杭州此時(shí)浸泡在三月的春雨里盯串,被洗滌成溫柔明媚的模樣。我們像一個(gè)小湯圓戒良,溫吞...
    Magalier閱讀 137評(píng)論 0 0