Rxjava2+Retrofit2+MVP的網(wǎng)絡(luò)請(qǐng)求封裝

一屎慢、概述

MVP的模式目前在網(wǎng)上已經(jīng)層出不窮瞭稼,大多數(shù)是通過(guò)接口建立關(guān)系,進(jìn)行了功能的實(shí)現(xiàn)腻惠』分猓看過(guò)很多類似的文章,受益良多集灌。

下面切入正題悔雹,本文對(duì)異常的處理和訂閱關(guān)系的動(dòng)態(tài)取消進(jìn)行了封裝。通過(guò)泛型模式接通了MVP的三層關(guān)系欣喧。下面簡(jiǎn)單介紹組成體在本模式中的各個(gè)優(yōu)點(diǎn):

Retrofit2:通過(guò)注解的形式反射出請(qǐng)求體腌零,像調(diào)用普通java方法一樣的去獲取請(qǐng)求對(duì)象,底層網(wǎng)絡(luò)請(qǐng)求基于Okhttp3唆阿。

Rxjava2 : 便捷的線程調(diào)度莱没,響應(yīng)式編程,錯(cuò)誤信息的簡(jiǎn)單追蹤酷鸦。

MVP:解耦饰躲,復(fù)用性好牙咏,代碼清晰,易維護(hù)嘹裂。

二妄壶、代碼實(shí)現(xiàn)

代碼結(jié)構(gòu)目錄
  1. 訂閱關(guān)系的處理:網(wǎng)絡(luò)請(qǐng)求不止一個(gè),Rxjava2訂閱關(guān)系就會(huì)很多寄狼,雖然Rxjava2內(nèi)部實(shí)現(xiàn)了自動(dòng)取消訂閱關(guān)系(請(qǐng)求完成丁寄,請(qǐng)求報(bào)錯(cuò)),但是在特殊情況下需要手動(dòng)關(guān)閉泊愧,在結(jié)束請(qǐng)求或者在應(yīng)有的生命周期結(jié)束時(shí)訂閱關(guān)系就要取消伊磺,比如在請(qǐng)求還沒(méi)有結(jié)束的時(shí)候,View在沒(méi)有執(zhí)行完畢就退出了删咱,那么它肯定不會(huì)自動(dòng)解綁屑埋,這個(gè)時(shí)候就需要我們手動(dòng)解除訂閱關(guān)系,否則會(huì)產(chǎn)生內(nèi)存泄漏痰滋。
import io.reactivex.disposables.Disposable;

public interface SubscriptionHelper<T> {
    void add(Disposable subscription);

    void cancel(Disposable t);

    void cancelall();
}

import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;

public class SubscriptionManager implements SubscriptionHelper<Object> {
    public static SubscriptionManager subscriptionManager;
    private CompositeDisposable mDisposables;

    public SubscriptionManager() {
        if (mDisposables == null) {
            mDisposables = new CompositeDisposable();
        }
    }

    @Override
    public void add(Disposable disposable) {
        if (disposable == null) return;
        mDisposables.add(disposable);
    }

    @Override
    public void cancel(Disposable disposable) {
        if (mDisposables != null) {
            mDisposables.delete(disposable);
        }
    }

    @Override
    public void cancelall() {
        if (mDisposables != null) {
            mDisposables.clear();
        }
    }

    public static SubscriptionManager getInstance() {
        if (subscriptionManager == null) {
            synchronized (SubscriptionManager.class) {
                if (subscriptionManager == null) {
                    subscriptionManager = new SubscriptionManager();
                }
            }
        }
        return subscriptionManager;
    }
}

2.網(wǎng)絡(luò)請(qǐng)求異常的處理:針對(duì)常見(jiàn)網(wǎng)絡(luò)請(qǐng)求異常進(jìn)行了封裝摘能。

public class ErrorBodyDTO {
    private String errCode;
    private String errMsg;

    public String getErrCode() {
        return errCode;
    }

    public void setErrCode(String errCode) {
        this.errCode = errCode;
    }

    public String getErrMsg() {
        return errMsg;
    }

    public void setErrMsg(String errMsg) {
        this.errMsg = errMsg;
    }
}
import android.net.ParseException;

import com.google.gson.Gson;
import com.google.gson.JsonParseException;
import com.jakewharton.retrofit2.adapter.rxjava2.HttpException;

import org.json.JSONException;

import java.io.IOException;
import java.net.ConnectException;

import okhttp3.ResponseBody;

public class ExceptionHandle {
    private static final int UNAUTHORIZED = 401;
    private static final int FORBIDDEN = 403;
    private static final int NOT_FOUND = 404;
    private static final int REQUEST_TIMEOUT = 408;
    private static final int INTERNAL_SERVER_ERROR = 500;
    private static final int BAD_GATEWAY = 502;
    private static final int SERVICE_UNAVAILABLE = 503;
    private static final int GATEWAY_TIMEOUT = 504;
    private static final int FAIL_QUEST = 406;//無(wú)法使用請(qǐng)求的內(nèi)容特性來(lái)響應(yīng)請(qǐng)求的網(wǎng)頁(yè)
    private static final int BAD_REQUEST = 400;
    private static ResponseBody body;

    public static ResponeThrowable handleException(Throwable e) {
        ResponeThrowable ex;
        if (e instanceof HttpException) {
            HttpException httpException = (HttpException) e;
            ex = new ResponeThrowable(e, ERROR.HTTP_ERROR);
            switch (httpException.code()) {
                case UNAUTHORIZED:
                   /* body = ((HttpException) e).response().errorBody();
                    try {
                        String message = body.string();
                        Gson gson = new Gson();
                        Exception_401DTO exceptionDTO_401 = gson.fromJson(message, Exception_401DTO.class);
                        //[size=106 text={"error":"invalid_token","error_description":"Invalid access tok…]
                        if (exceptionDTO_401.getError().toString().equals("invalid_token")) {
                            ex.message = "請(qǐng)退出后登錄";
                            //發(fā)出廣播,然后跳轉(zhuǎn)登錄
                            ToLoginBean toLoginBean = new ToLoginBean();
                            toLoginBean.setFlag(true);
                            EventBus.getDefault().post(toLoginBean);
                        }
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }*/
                    break;
                case FORBIDDEN:
                    ex.message = "服務(wù)器已經(jīng)理解請(qǐng)求敲街,但是拒絕執(zhí)行它";
                    break;
                case NOT_FOUND:
                    ex.message = "服務(wù)器異常团搞,請(qǐng)稍后再試";
                    break;
                case REQUEST_TIMEOUT:
                    ex.message = "請(qǐng)求超時(shí)";
                    break;
                case GATEWAY_TIMEOUT:
                case INTERNAL_SERVER_ERROR:
                    ex.message = "服務(wù)器遇到了一個(gè)未曾預(yù)料的狀況,無(wú)法完成對(duì)請(qǐng)求的處理";
                    break;
                case BAD_REQUEST:
                    /*body = ((HttpException) e).response().errorBody();
                    try {
                        String message = body.string();
                        Gson gson = new Gson();
                        Exception_401DTO exceptionDTO_401 = gson.fromJson(message, Exception_401DTO.class);
                        //[size=106 text={"error":"invalid_token","error_description":"Invalid access tok…]
                        *//**
                 * {"error":"invalid_grant","error_description":"Bad credentials"}
                 *//*
                        if (exceptionDTO_401.getError().toString().equals("invalid_grant")) {
                            ex.message = "用戶名或密碼錯(cuò)誤";
                        }
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }*/
                    break;
                case BAD_GATEWAY:
                case SERVICE_UNAVAILABLE:
                case FAIL_QUEST:
                    body = ((HttpException) e).response().errorBody();
                    try {
                        String message = body.string();
                        Gson gson = new Gson();
                        ErrorBodyDTO globalExceptionDTO = gson.fromJson(message, ErrorBodyDTO.class);
                        if (globalExceptionDTO.getErrMsg() != null) {
                            ex.message = globalExceptionDTO.getErrMsg();
                        } else {
                            ex.message = "";
                        }
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                    break;
                default:
                    ex.message = "網(wǎng)絡(luò)錯(cuò)誤";
                    break;
            }
            return ex;
        } else if (e instanceof ServerException) {
            ServerException resultException = (ServerException) e;
            ex = new ResponeThrowable(resultException, resultException.code);
            ex.message = resultException.message;
            return ex;
        } else if (e instanceof JsonParseException
                || e instanceof JSONException
                || e instanceof ParseException) {
            ex = new ResponeThrowable(e, ERROR.PARSE_ERROR);
            ex.message = "解析錯(cuò)誤";
            return ex;
        } else if (e instanceof ConnectException) {
            ex = new ResponeThrowable(e, ERROR.NETWORD_ERROR);
            ex.message = "連接失敗";
            return ex;
        } else if (e instanceof javax.net.ssl.SSLHandshakeException) {
            ex = new ResponeThrowable(e, ERROR.SSL_ERROR);
            ex.message = "證書驗(yàn)證失敗";
            return ex;
        } else if (e instanceof java.net.SocketTimeoutException) {
            ex = new ResponeThrowable(e, ERROR.TIMEOUT_ERROR);
            //ex.message = "連接超時(shí)";
            ex.message = "當(dāng)前網(wǎng)絡(luò)連接不順暢多艇,請(qǐng)稍后再試逻恐!";
            return ex;
        } else if (e instanceof java.net.UnknownHostException) {
            ex = new ResponeThrowable(e, ERROR.TIMEOUT_ERROR);
            ex.message = "網(wǎng)絡(luò)中斷,請(qǐng)檢查網(wǎng)絡(luò)狀態(tài)峻黍!";
            return ex;
        } else if (e instanceof javax.net.ssl.SSLException) {
            ex = new ResponeThrowable(e, ERROR.TIMEOUT_ERROR);
            ex.message = "網(wǎng)絡(luò)中斷复隆,請(qǐng)檢查網(wǎng)絡(luò)狀態(tài)!";
            return ex;
        } else if (e instanceof java.io.EOFException) {
            ex = new ResponeThrowable(e, ERROR.PARSE_EmptyERROR);
            ex.message = "1007";
            return ex;
        } else if (e instanceof java.lang.NullPointerException) {
            ex = new ResponeThrowable(e, ERROR.PARSE_EmptyERROR);
            ex.message = "數(shù)據(jù)為空奸披,顯示失敗";
            return ex;
        } else {
            ex = new ResponeThrowable(e, ERROR.UNKNOWN);
            ex.message = "未知錯(cuò)誤";
            return ex;
        }
    }


    /**
     * 約定異常
     */
    public class ERROR {
        /**
         * 未知錯(cuò)誤
         */
        public static final int UNKNOWN = 1000;
        /**
         * 解析錯(cuò)誤
         */
        public static final int PARSE_ERROR = 1001;
        /**
         * 解析no content錯(cuò)誤
         */
        public static final int PARSE_EmptyERROR = 1007;
        /**
         * 網(wǎng)絡(luò)錯(cuò)誤
         */
        public static final int NETWORD_ERROR = 1002;
        /**
         * 協(xié)議出錯(cuò)
         */
        public static final int HTTP_ERROR = 1003;

        /**
         * 證書出錯(cuò)
         */
        public static final int SSL_ERROR = 1005;

        /**
         * 連接超時(shí)
         */
        public static final int TIMEOUT_ERROR = 1006;

        public static final int LOGIN_ERROR = -1000;
        public static final int DATA_EMPTY = -2000;


    }

    public static class ResponeThrowable extends Exception {
        public int code;
        public String message;

        public ResponeThrowable(Throwable throwable, int code) {
            super(throwable);
            this.code = code;
        }

        public ResponeThrowable(String message, int code) {
            this.code = code;
            this.message = message;
        }
    }

    public class ServerException extends RuntimeException {
        public int code;
        public String message;

        public ServerException(int code, String message) {
            this.code = code;
            this.message = message;
        }
    }
}

3.Retrofit2請(qǐng)求體的創(chuàng)建。

import io.reactivex.Observable;
import retrofit2.http.Body;
import retrofit2.http.GET;
import retrofit2.http.Path;
import retrofit2.http.Query;
import utils.BeanGSchaxun;

public interface Apiservice {
    @GET("{fenzhi}{bianhao}/orderinfo")
    Observable<List<BeanGSchaxun>> getGSxin(@Path("fenzhi") String fenzhi,
                                            @Path("bianhao") String bianhao,
                                            @Query("batchNo") String batchNo);

}

4.RetrofitManager管理器的創(chuàng)建涮雷,保證Retrofit在類中只有一個(gè)實(shí)例阵面,避免請(qǐng)求體的多次創(chuàng)建。

import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import com.neuqsoft.sipay.neuq.Mvp.Service.Apiservice;

import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class RetrofitManager {
    private volatile static RetrofitManager retrofitManager;
    private Retrofit retrofit;

    //無(wú)參的單利模式
    public static RetrofitManager getSingleton() {
        if (retrofitManager == null) {
            synchronized (RetrofitManager.class) {
                retrofitManager = new RetrofitManager();
            }
        }
        return retrofitManager;
    }


    //無(wú)參的構(gòu)造方法
    private RetrofitManager() {
        initRetrofitManager();
    }

    //構(gòu)造方法創(chuàng)建Retrofit實(shí)例
    private void initRetrofitManager() {
        retrofit = new Retrofit.Builder().baseUrl("url" + "/")
                
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .build();
    }

    public Apiservice Apiservice() {
        return retrofit.create(Apiservice.class);
    }
}

5.M層:業(yè)務(wù)邏輯的處理洪鸭,實(shí)現(xiàn)了觀察者中的方法样刷,將其中請(qǐng)求的結(jié)果傳遞到抽象方法中,方便其他類的實(shí)現(xiàn)览爵。(注意這里異常的傳遞和訂閱關(guān)系的添加)

import java.util.List;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import utils.BeanGSchaxun;
import utils.houtai;

/**
 * Created by Gy 
 */

public class GsModel {

    public void getxinxi(String fenzhi, String bianhao, String shijian, Observer<List<BeanGSchaxun>> observer) {
        Observable<List<BeanGSchaxun>> gSxin = RetrofitManager.getSingleton().Apiservice().getGSxin(fenzhi, bianhao, shijian);
        gSxin.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(observer);

    }

}

import io.reactivex.disposables.Disposable;



public abstract class Observer<T> implements io.reactivex.Observer<T> {
    @Override
    public void onSubscribe(Disposable d) {
        //添加訂閱關(guān)系
        OnDisposable(d);
    }

    @Override
    public void onNext(T t) {
        OnSuccess(t);
    }

    @Override
    public void onError(Throwable e) {
        //自定義異常的傳遞
        OnFail(ExceptionHandle.handleException(e));
    }

    @Override
    public void onComplete() {
        OnCompleted();
    }

    public abstract void OnSuccess(T t);

    public abstract void OnFail(ExceptionHandle.ResponeThrowable e);

    public abstract void OnCompleted();

    public abstract void OnDisposable(Disposable d);
}

6.MVP:這里就涉及到泛型的使用了置鼻。一般我們建立P和V層是通過(guò)實(shí)現(xiàn)接口的形式,這里通過(guò)泛型的類型規(guī)定來(lái)綁定我們的P和V蜓竹。注意的一點(diǎn)是:我們的用戶需要什么功能箕母,V層接口就實(shí)現(xiàn)幾個(gè)功能储藐。因?yàn)槭蔷W(wǎng)絡(luò)請(qǐng)求的封裝,因此要有請(qǐng)求成功和請(qǐng)求失敗嘶是「撇看代碼(V層接口)。


//SimpleView——Activity里面要實(shí)現(xiàn)的方法在這里面定義
public interface SimpleView {
    void onSuccess(Object object);

    void onFail(ExceptionHandle.ResponeThrowable t);

    void OnCompleted();
}

然后V和P的關(guān)系建立聂喇,先創(chuàng)建基本的P層辖源,它的作用是綁定和解除與V的關(guān)系。代碼里面有注釋希太】巳模看代碼(基本的P層)。

//<里面?zhèn)魅氲膮?shù)必須是BaseView的子類或者本身>
//這個(gè)類的作用就是獲取到當(dāng)前的View
public class BasePresenter<V> {

    public V view;

    //加載View,建立連接
    public void addView(V v) {
        this.view = v;
    }

    //斷開(kāi)連接
    public void detattch() {
        if (view != null) {
            view = null;
        }
    }
}

import java.util.List;

import io.reactivex.disposables.Disposable;
import utils.BeanGSchaxun;
import utils.BeanGSlist;
import utils.BeanGsSecond;
import utils.BeanGsXiadan;


//(Presenter與View交互是通過(guò)接口),里面放一個(gè)接口
public class Gspresent extends BasePresenter<SimpleView> {
    private GsModel gsModel;

    public Gspresent() {
        gsModel = new GsModel();
    }

    //Presenter與View交互
    public void getGSxinxi(String fenzhi, String bianhao, String shijian) {
        gsModel.getxinxi(fenzhi, bianhao, shijian, new Observer<List<BeanGSchaxun>>() {
            @Override
            public void OnSuccess(List<BeanGSchaxun> beanGSchaxuns) {
                //繼承關(guān)系誊辉,可以使用泛型里面的屬性矾湃。
                view.onSuccess(beanGSchaxuns);

            }

            @Override
            public void OnFail(ExceptionHandle.ResponeThrowable e) {
                view.onFail(e);
            }

            @Override
            public void OnCompleted() {
                view.OnCompleted();
            }

            @Override
            public void OnDisposable(Disposable d) {
                SubscriptionManager.getInstance().add(d);
            }

        });
    }

}

我們分析下代碼,這里涉及到泛型的使用芥映。Gspresent繼承BasePresenter<SimpleView>洲尊,那么子類就繼承了BasePresenter和SimpleView的屬性,這樣就可以使用BasePresenter里面的變量view去調(diào)用SimpleView里面的方法奈偏。P和M層的關(guān)系建立通過(guò)New創(chuàng)建實(shí)例即可坞嘀。
那么Activity的view是怎么傳給P的呢?看下面代碼惊来。(MVPActivity)

import utils.BaseActivity;
//MvpActivity<P extends BasePresenter>:p繼承了BasePresenter丽涩,就可以用P的參數(shù)去調(diào)用BasePresenter
//繼承關(guān)系
public abstract class MvpActivity<p extends BasePresenter> extends BaseActivity {
    public p presener;

    @Override
    public void initBefore(Bundle savedInstanceState) {
        super.initBefore(savedInstanceState);
        presener = initPresener();
        //把所有繼承此類的Activity都綁定到這里了,這樣View就和Present聯(lián)系起來(lái)了裁蚁。
        presener.addView(this);
    }

    protected abstract p initPresener();

    @Override
    protected void onDestroy() {
        super.onDestroy();
        presener.detattch();
        //View消除時(shí)取消訂閱關(guān)系
        SubscriptionManager.getInstance().cancelall();
    }
}

在基本的P層中看方法名就知道它是通過(guò)addview建立對(duì)外關(guān)系的矢渊,通過(guò)addview給view定義屬性。這里面的泛型是BasePresenter(基本的P)枉证,調(diào)用泛型里面的屬性方法 presener.addView(this)將Activity的上下文傳賦值給view矮男,這樣P層就和Activity的View綁定到一起了。
MVPActivity建立了室谚,使用的時(shí)候直接繼承即可毡鉴。

import java.util.List;

import butterknife.Bind;
import utils.Title;


public class WXPayEntryActivityc extends MvpActivity<Gspresent> implements SimpleView {

    @Bind(R.id.a)
    Title a;
    @Bind(R.id.xuanzetime)
    Button xuanzetime;
    @Bind(R.id.xinxi)
    Button xinxi;
    @Bind(R.id.time)
    TextView time;
    @Bind(R.id.next)
    Button next;
    @Bind(R.id.Gsxinxi)
    LinearLayout Gsxinxi;
    @Bind(R.id.lvGS)
    ListView lvGS;
    @Bind(R.id.scrollViewa)
    ScrollView scrollViewa;

    @Override
    public int getLayoutid() {
        return R.layout.activity_wxpay_entry_activityc;
    }


    @Override
    public void initView() {
    }

    @Override
    public void initData() {
    }


    @Override
    public void OnCompleted() {
    }

    @Override
    public void onSuccess(Object object) {
        if (object instanceof List) {
           //請(qǐng)求成功
        }

    }


    @Override
    public void onFail(ExceptionHandle.ResponeThrowable t) {
        Log.i(getPackageName(), t.message.toString());
        Toast.makeText(this, t.message.toString(), Toast.LENGTH_SHORT).show();
    }

    @Override
    protected Gspresent initPresener() {
        return new Gspresent();
    }

    }

這里面實(shí)現(xiàn)SimpleView 重寫Onsuccess方法就可以拿到P層中請(qǐng)求的結(jié)果,而不用去做網(wǎng)絡(luò)請(qǐng)求秒赤。

總結(jié)

使用泛型可以增加代碼的擴(kuò)展性猪瞬。
MVP核心就是P層和V層的交互處理,根據(jù)V的需求定義P層接口入篮。
歡迎大家的討論陈瘦。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市潮售,隨后出現(xiàn)的幾起案子痊项,更是在濱河造成了極大的恐慌锅风,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件线婚,死亡現(xiàn)場(chǎng)離奇詭異遏弱,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)塞弊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門漱逸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人游沿,你說(shuō)我怎么就攤上這事饰抒。” “怎么了诀黍?”我有些...
    開(kāi)封第一講書人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵袋坑,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我眯勾,道長(zhǎng)枣宫,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任吃环,我火速辦了婚禮也颤,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘郁轻。我一直安慰自己翅娶,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布好唯。 她就那樣靜靜地躺著竭沫,像睡著了一般。 火紅的嫁衣襯著肌膚如雪骑篙。 梳的紋絲不亂的頭發(fā)上蜕提,一...
    開(kāi)封第一講書人閱讀 49,185評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音靶端,去河邊找鬼谎势。 笑死,一個(gè)胖子當(dāng)著我的面吹牛躲查,可吹牛的內(nèi)容都是我干的它浅。 我是一名探鬼主播译柏,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼镣煮,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了鄙麦?” 一聲冷哼從身側(cè)響起典唇,我...
    開(kāi)封第一講書人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤镊折,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后介衔,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體恨胚,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年炎咖,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了赃泡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡乘盼,死狀恐怖升熊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情绸栅,我是刑警寧澤级野,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站粹胯,受9級(jí)特大地震影響蓖柔,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜风纠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一况鸣、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧议忽,春花似錦懒闷、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至速址,卻和暖如春玩焰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背芍锚。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工昔园, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人并炮。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓默刚,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親逃魄。 傳聞我的和親對(duì)象是個(gè)殘疾皇子荤西,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

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

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,528評(píng)論 25 707
  • 許多不管怎么做、怎么想都沒(méi)結(jié)果的事,要懂得交給時(shí)間邪锌。有些事無(wú)論你怎么努力怎么勉強(qiáng)勉躺,時(shí)間不夠,還是耐心的等待吧觅丰。 一...
    Kerry202閱讀 1,189評(píng)論 6 2
  • 我愛(ài)你饵溅,無(wú)論世界多污穢,有多少虛偽不純粹妇萄,都有我在你身邊蜕企,拼死給你一方碧海藍(lán)天。 這句我愛(ài)你也代表父母獻(xiàn)給孩子們冠句,...
    氣球先生閱讀 288評(píng)論 2 4
  • 一句問(wèn)候代表一顆心糖赔,話沒(méi)了……心也沒(méi)了……
    吳楚紅閱讀 206評(píng)論 0 0
  • 中醫(yī)雖然沒(méi)有專門 針對(duì)筋縮的療法基茵,但各種撐拉的方法在習(xí)武奋构、氣功、瑜加鍛煉中一直存在拱层。 目前西醫(yī)還沒(méi)有筋縮的概念弥臼,很...
    藍(lán)蝶_8263閱讀 348評(píng)論 0 0