Android Weekly Notes Issue #222

Android Weekly Issue #222

September 11th, 2016
Android Weekly Issue #222

ARTICLES & TUTORIALS

Forcing bytes download in Okio

這是Jake Wharton的文章, 關(guān)于Okio的BufferedSink.

okio 是一個java io庫, 包裝了一套API用來讀寫和處理數(shù)據(jù). 文檔見: okio doc.

很多庫都是在其之上寫的, 比如okhttp, Retrofit, Moshi. 這里有個視頻: A Few OK libraries

有三個方法可以強(qiáng)制把bytes放入底層的Sink.

flush(), emit() and emitCompleteSegments()

flush()

調(diào)用這個方法會使得所有緩存的字節(jié)移動到Sink, 然后Sink立即flush自己. 所以調(diào)用flush()方法返回后, 你可以保證所有的字節(jié)都到了目的地Sink.

當(dāng)用多級buffer時, flush()會清除所有l(wèi)evel的buffer. Okio中多級buffer的花銷很小, 一個flush會讓每一級把自己的segments移到下一級.

java io中的多級buffer每一級都自己管理自己的字節(jié), 所以flush操作會讓每一級都拷貝數(shù)據(jù)到下一級.

流類型的close()flush()的行為類似, 在關(guān)閉流之前把所有的字節(jié)都寫了.

emit()

發(fā)射字節(jié)的行為和flush類似, 但是不是遞歸的. 調(diào)用emit()會使得所有緩存的字節(jié)移動到Sink, 但是與flush()不同, 此時Sink并不會做其他的操作.

emitCompleteSegments()

調(diào)用這個emitCompleteSegments()方法僅僅移動那些完整segment的字節(jié)移動到Sink.

segment是okio的一個概念.

原文中有動圖圖解, 看起來更清楚一些.

Use cases

Writing messages to a WebSocket -> flush()

Encoding a video to a file -> emitCompleteSegments() + emit()/flush() at the end

Serializing an object to JSON -> emit()

Using Android Studio's Performance Monitors

作者他的音樂應(yīng)用遇到了不響應(yīng)的問題, 然后他打開Android Studio的performance monitor看到了是內(nèi)存問題, 然后他track了一下出問題的時候的memory allocation, 最后發(fā)現(xiàn)是有一張要下載的圖太大了.

The hidden cost of code coverage

測試覆蓋率是一個很好的方法來激勵你和你的團(tuán)隊多寫一些測試, 但是你知道嗎, 打開測試覆蓋率的檢測會讓你的build變慢.

要測量build時間:

./gradlew clean assembleDebug --profile

然后作者發(fā)現(xiàn)其中:app:transformClassesWithJacocoForDailyDebug占用的時間達(dá)到了build時間的14%.

就是因為這句:

buildTypes {
    debug {
        ...
        testCoverageEnabled true
    }
}

解決辦法
只在需要測試覆蓋率的時候用它, 所以加一個變量:
/gradlew -Pcoverage clean connectedDebugAndroidTest

gradle里這樣寫:

buildTypes {
    debug {
        ...
        testCoverageEnabled (project.hasProperty('coverage') ? true : false)
    }
}

當(dāng)你不加這個flag的時候就不會檢查測試覆蓋率.

Android Development Useful Tools

methodscount 可以統(tǒng)計library的方法數(shù), 因為Android有64k的方法數(shù)限制.

Stetho
可以看網(wǎng)絡(luò)請求, 數(shù)據(jù)庫, shared preferences等.

LeakCanary 檢測內(nèi)存泄露的庫.

apk-method-count 這個網(wǎng)站可以檢測apk中的方法數(shù), 根據(jù)包分別顯示.

Android Asset Studio
生成圖片, 9-patch等的一系列工具.

Buck Facebook開發(fā)的一套build系統(tǒng).

Gradle, please 輸入你要的庫, 然后就可以找到對應(yīng)的dependencies里應(yīng)該寫的 compile xxx.

ProguardDexGuard

Genymotion

Material Design Icons

Introduction to Automated Android Testing - Part 6

系列文章的最后一篇, 作者講用Espresso寫UI測試.

如果數(shù)據(jù)是動態(tài)的, 那么要測試View包含指定的信息是很難的. 數(shù)據(jù)有可能變化, 但是我們的測試不能因此而失敗. 所以為了測試可靠和可重復(fù), 我們不應(yīng)該調(diào)用production的API.

所以第一步是mock API, 有幾種方法:

    1. WireMock (需要server).
    1. 用OkHttp的MockWebServer, 在你的設(shè)備上跑一個webserver.
    1. 創(chuàng)建一個Retrofit REST接口, 返回一些dummy對象.

Mock數(shù)據(jù)的時候利用了Gradle的flavor, 可以創(chuàng)建一個mockDebug flavor, 然后在src目錄下建一個mock目錄, 放一些mock的代碼進(jìn)去, 然后再建一個prod目錄, 把真實的實現(xiàn)移動到那里去.

Espresso基礎(chǔ)

Espresso寫測試, 基本格式是這樣:

onView(withId(R.id.menu_search))      // withId(R.id.menu_search) is a ViewMatcher
  .perform(click())               // click() is a ViewAction
  .check(matches(isDisplayed())); // matches(isDisplayed()) is a ViewAssertion

ViewMatchers 是用來定位View的 有withId, withText, withTag等.

ViewActions 是用來跟View交互的, 比如點擊, 輸入等.

ViewAssertations 是用來做出斷言的.

這里有個cheat-sheet可以查: android-expresso-testing.pdf

Writing Espresso UI Tests

這部分具體講了作者例子的UI測試寫法, 見原文.
最后作者還看了一下測試覆蓋率.

What 2 years of Android Development Have Taught Me

作者講了他兩年來的心路歷程, 以及他總結(jié)的一些To do和Not to do.

  1. 不要重復(fù)造輪子.
    可以用android-arsenal來查庫.

  2. 明智地選擇庫.
    選擇庫的時候看看星多不多, 作者有沒有什么其他流行的庫. 再看看issues, 有時間的話可以看代碼.
    Dryrun可以用來跑sample.

  3. 坐下來看代碼. 我們應(yīng)該花費(fèi)多數(shù)的時間閱讀別人的代碼, 而不是寫自己的代碼.
    你能寫出來的代碼是你已經(jīng)知道的東西的一個反映, 要不斷成長和提高自己, 只能不斷閱讀和學(xué)習(xí)別人的代碼.
    這里有Library列表app列表.

  4. 保持一個好的代碼風(fēng)格. 這里有一些參考: code-style, android-guidelines.

  5. 用Proguard, 這樣release版本不但縮小了代碼也做了混淆. 這里還有一個DexGuard.

  6. 使用一個合理的架構(gòu). 可以用MVP來解耦, 這里有個demo: Android-CleanArchitecture, 這里是它相關(guān)的Guide文章: Guide on Clean Architecture.
    更多資源:
    androidmvp,
    mosby,
    android-architecture.

  7. 對于獨(dú)立工作的開發(fā), 還需要注意一些UI/UX相關(guān)的原則. 可以上DribbleMaterialUp多看看.

  8. 分析是你的好朋友. 分析包括了crash報告和app使用記錄, 可以用Firebase.

  9. 做一個市場忍者. 對于獨(dú)立開發(fā)者來說, 需要marketing. 這是一個市場分析工具: sensor tower.

  10. 優(yōu)化你的App. 推薦檢查內(nèi)存泄露的工具: leakcanary.

  11. 優(yōu)化gradle的build時間. 這里有兩個Guides: speeding up gradle build, making gradle builds faster

  12. 多做測試. 發(fā)布前花時間測試, 不要急.

  13. 兼顧多種機(jī)型, 包括屏幕尺寸, API level, 不同廠商的OS等.

  14. 用Git. 這是一個Git branch model. 如果你不能負(fù)擔(dān)github上的private repo, 你可以試試BitBucket

  15. 讓黑客覺得難處理. Android很容易被攻擊, app可以被輕易地反編譯和分析. 你需要知道如何處理你的API keys, 如果你需要處理用戶的敏感信息, 你應(yīng)該知道如何加密. 秘鑰也要妥善存儲. 任何存儲在數(shù)據(jù)庫中的敏感信息也都要加密. 相關(guān)的資料可以看Adding Tampering Detection to Your appHiding Secrets in Android Apps.

  16. 在低級設(shè)備上開發(fā). 低級的設(shè)備容易暴露問題.

  17. 學(xué)習(xí)設(shè)計模式. 這里有一個repo講了所有的Java中的設(shè)計模式: java-design-patterns. 另外還推薦書籍: GoF的設(shè)計模式, Martin Fowler的重構(gòu), Joshua Bloch的Effective Java.

  18. 貢獻(xiàn)自己的力量. StackOverflow, Github, blog posts...

Android Support Annotations

使用Annotation library:

compile 'com.android.support:support-annotations:<latest-library-version>'

如果你已經(jīng)用了appcompat library, 你就已經(jīng)可以用annotations了, 因為appcompat自己就用了它.

annotations按照用法和功能來分組:

  • Nullness Annotations
  • Resource Annotations
  • Thread Annotations
  • Value Constraints Annotations
  • Others : Permissions Annotations, CheckResults Annotations and CallSuper Annotations.

Nullness Annotations

@Nullalbe@NonNull用來檢查變量, 參數(shù)和方法返回值為null與否.

@NonNull表示變量, 參數(shù)或返回值不能為null, 如果為null了編譯器會給出警告.

@Nullalbe表示可能為null, 用這個注解的時候表示代碼中應(yīng)該加上null check.

Resource Annotations

因為資源號都是int值, 所以如果你把一個drawable的int傳給一個期待string resource的代碼, 編譯器是會接受的.
資源注解就是用來做這種情況的類型檢查的.

比如用@StringRes來標(biāo)記參數(shù), 如果你傳入一個drawable的id, IDE就會把它標(biāo)記出來.

每一個Android的資源類型都有一個對應(yīng)的資源注解, 比如類型是Foo, 那么對應(yīng)的資源類型注解就是FooRes.

有一個特殊的@AnyRes, 用來表示任意的資源類型.

Thread Annotations

這種注解用來檢查方法是不是在特定的線程調(diào)用的. 有:

  • @UiThread
  • @MainThread
  • @WorkerThread
  • @BinderThread

@UiThread@MainThread是可互換的.

如果一個類中的所有方法都是從同樣的線程調(diào)用搞得, 那么可以直接把類給標(biāo)記了.

Value Constraints Annotations

@IntRange, @FloatRange@Size注解是用來驗證參數(shù)的值的. 比如@IntRange就驗證參數(shù)是在一個給定的int范圍之內(nèi).
比如下面的方法確保傳入的參數(shù)是0到255:

public void setAlpha(@IntRange(from=0, to=255) int alpha) {
    //set alpha
}

相應(yīng)的@FloatRange檢查參數(shù)是在一個指定范圍內(nèi)的浮點數(shù).

@Size注解是用來檢查集合的大小, 還有字符串的長度. 比如@Size(min=1)用來檢查集合不為空, @Size(2)檢查集合有兩個元素.

CheckResult Annotations

這個注解是用來檢查一個方法的返回值確實被使用了.
一個比較好的例子是String.trim方法, 當(dāng)這個方法被@CheckResult標(biāo)注, 如果它的返回值沒有被使用, IDE就會報錯.

另外一些比較值得看的注解有@CallSuper, @Keep@RequiresPermission.
可以直接查看support annotations的reference.

其他參考資料:

Improve code Inspection with Annotations

Support Annotation documentation

Improving your code with android support annotations

ActivityTestRule: Espresso's Test "Lifecycle"

作者這篇文章的目的是講講用Espresso的ActivityTestRule寫的測試中的操作順序, 討論像beforeActivityLaunched(), afterActivityLaunched(), 和 afterActivityFinished()這些方法相對于測試和Activity的生命周期都是什么時候被調(diào)用的.

首先作者介紹了Espresso 2.0及之前的舊的ActivityInstrumentationTestCase2.

ActivityTestRule的"生命周期".

新的寫法是這樣:

@RunWith(AndroidJUnit4.class)
public MyNewTest {
  @Rule
  public MyCustomRule<MyActivity> testRule = new MyCustomRule<>(MyActivity.class);
  
  @Test
  public void testStuff() {
    // Wow where's all the boilerplate code?
    
    // Verify Oscar Grouch is no longer grouchy.
  }
}

而其中的MyCustomRule:

public class MyCustomRule<A extends MyActivity> extends ActivityTestRule<A> {
  public MyCustomRule(Class<A> activityClass) {
    super(activityClass);
  }
  
  @Override
  protected void beforeActivityLaunched() {
    super.beforeActivityLaunched();
    // Maybe prepare some mock service calls
    // Maybe override some depency injection modules with mocks
  }
    
  @Override
  protected Intent getActivityIntent() {
    Intent customIntent = new Intent();
    // add some custom extras and stuff
    return customIntent;
  }
  
  @Override
  protected void afterActivityLaunched() {
    super.afterActivityLaunched();
   // maybe you want to do something here 
  }
    
  @Override
  protected void afterActivityFinished() {
    super.afterActivityFinshed();
    // Clean up mocks
  }
}

ActivityTestRule: launchActivity=false;

ActivityTestRule的第三個參數(shù)允許開發(fā)者明確指定對每一個test case啟動一個Activity.

public ActivityTestRule(Class activityClass, boolean initialTouchMode, boolean launchActivity).

把第三個參數(shù)設(shè)置為false, 就可以寫出這樣的測試:

@RunWith(AndroidJUnit4.class)
public class MultipleIntentsTest {
  @Rule
  public ActivityTestRule<MyActivity> testRule = new ActivityTestRule<>(MyActivity.class,
          false,    // initialTouchMode
          false);  // launchActivity. False to set intent per test);

  @Test
  public void testOscarGrouchy() {
    Intent grouchyIntent = new Intent();
    // intent stuff
    grouchyIntent.putExtra("EXTRA_IS_GROUCHY", true);
    testRule.launchActivity(grouchyIntent);
    // verify Oscar is grouchy
  }
  
  @Test
  public void testOscarNotGrouchy() {
    Intent happyIntent = new Intent();
    // intent stuff
    happyIntent.putExtra("EXTRA_IS_GROUCHY", false);
    testRule.launchActivity(happyIntent);
    // verify Oscar is not grouchy
  }
}

這個lauchActivity的值默認(rèn)是為true. 設(shè)置為false之后我們在每一個test case里面自己啟動activity. 對生命周期產(chǎn)生的影響作者也做了圖對比分析, 見原文.

作者最后還講了幾個點, 關(guān)于測試遷移, 以及Activity的生命周期方法中啟動Intent相關(guān)的需要注意的地方.

People and resources to learn Android programming from

作者分享了關(guān)于Android編程學(xué)習(xí)中他積累的人和資源.

Twitter

Chiu-Ki Chan

Donn Felker, 他的博客: blog. 他和Kaushik Gopal一起弄了Fragmented Podcast. 這里還有一個視頻教程的網(wǎng)站: Caster.io.

Jake Wharton, 這個大家都知道啦, 這是他的博客: blog.

Kristin V Marsicano, 這里有一個她的關(guān)于Activity生命周期的演講Activities in the Wild, 可能有一些你沒有想過的東西.

Ryan Harter

The Practical Dev

最后這有一個列表: Tweet Android List

Podcasts

Fragmented 兩個獨(dú)立開發(fā)者辦的.

Android Developers Backstage 寫Android的那些人辦的.

Material 這不是一個技術(shù)廣播, 講一些Google新聞.

Videos

Caster.io

Realm.io

Android Dialogs (YouTube)

Newsletters

Android Weekly

Kotline Weekly

General Reading

Medium: 標(biāo)簽androiddevandroid-app-development

Conferences

GoogleIO

360|AnDev

Droid Con NYC

ThirtyInch - a new MVP library for Android

近年來MVP已經(jīng)變成了Android社區(qū)中很流行的一種設(shè)計模式, MVC和MVVM也有人用. 這些模式的共同點就是把業(yè)務(wù)邏輯從Activity中抽取來.

這樣做的好處首先是我們可以盡量把需要測試的邏輯用JVM上的單元測試測, 而不是用模擬器上的androidTests.
當(dāng)然有些需要UI測試的地方仍然會用Espresso.

作者介紹了他們的MVP庫: ThirtyInch.

這個庫開始的時候mosby還沒有release, 建議讀一下mosby作者關(guān)于MVP的文章: mosby, 其中關(guān)于passive View的概念也在ThirtyInch中用到.

ThirtyInch:

ThirtyInch.

TiPresenter, TiView.
TiView是一個接口, 可以被attach和detach.

TiPresenter有四個生命周期事件:

  • onCreate(): 初始化的時候調(diào)用一次, 此時view還沒有attach.
  • onWakeUp(): view attach了, 并且對用戶變?yōu)榭梢?
  • onSleep(): 在這個調(diào)用之后, view將被detach, 并且變?yōu)閷τ脩舨豢梢?
  • onDestroy(): 在Activity/Fragment完全銷毀的時候調(diào)用一次.

onWakeUp()onSleep()對應(yīng)了onStart()onStop(), onResume/onPause沒有對應(yīng)的回調(diào)支持, 因為這些生命周期回調(diào)應(yīng)該在View層處理, 見: Presenters dont need lifecycle

ThirtyInch有什么不同

  • 可配置. 可以傳TiConfiguration對象給TiPresenter, 去掉一些features.
  • 所有Presenter的生命周期都按照正確的順序調(diào)用, onCreate()onDestroy()只調(diào)用一次.
  • 不依賴RxJava. 它有一個獨(dú)立的Rx module.
  • View接口的方法注解. 比如@CallOnMainThread@DistinctUntilChanged.
  • Public API. 一些基層API可以被所有人利用起來.
  • 不用繼承TiActivity. 你可以利用CompositeAndrodi, 把plugin module作為你的依賴, 然后把TiActivityPlugin加到你的Activity.

之后作者舉了一個Hello World的例子, 附圖講解很好, 見原文.

不是嚴(yán)格的MVP, MVVM也可以

作者又列出了一個ViewModel的圖.
ViewModel存儲了當(dāng)前UI的狀態(tài)數(shù)據(jù).
當(dāng)ViewModel中的數(shù)據(jù)變化時立即應(yīng)用到View, 這里@DistinctUtilChanged的使用避免了數(shù)據(jù)不變時候的重復(fù)操作.

測試, Keep Android At Arm's Length

MVP的初衷之一是為了方便寫測試, 因為Android SDK中的一些方法和類不好mock, 所以Presenter中應(yīng)該是沒有Android相關(guān)的東西的, 比如Context和Fragment等, Presenter只知道View接口和其中的方法, 是純java的.

這就是"Keep Android At Arm's Length."的意思, 不要把Android和邏輯代碼綁在一起, 庫的名字ThirtyInch也是來自于這個原則, 因為三十寸是人類手臂, 肩膀到手指的平均長度.

How does the Presenter survive the configuration change?

Activity在屏幕方向旋轉(zhuǎn)時會被重建. 此時沒有被序列化保存的信息就會丟失, 網(wǎng)絡(luò)請求要么被取消, 要么被忽略, 重新請求.

序列化數(shù)據(jù)會費(fèi)時, 而且在這種情況下, 序列話的數(shù)據(jù)幾秒之后就要被反序列化.

Android Framework提供了兩個方法來避免這種不必要的序列化:

  • Fragment的setRetainInstance(true), 之前的那個Fragment實例會被保存.
  • 使用Activity#onRetainNonConfigurationInstance()Activity#getLastNonConfigurationInstance()來存儲和恢復(fù)對象. 這也是Android保存上面retained Fragments的方法. 這個方法最近被廢棄了.

在Java中還有一個比較簡單粗暴的方法是保存一個應(yīng)用級別的單例.

ThirtyInch使用了上述的三種方法來確保TiPresenter在configuration變化的時候不死. 單例的解決方法盡在一些邊緣情況必須.

當(dāng)使用TiPresenter的時候不需要再實現(xiàn)onSaveInstanceState(Bundle)方法了, 因為數(shù)據(jù)都存在Presenter中.

Firebase Analytics VS Google Analytics

作者之前對比過 Firebase Crash Reporting和Crashlytics.

在這篇文章里, 作者對比Firebase和Google的分析工具, 下面簡稱FA和GA.

首先GA是2005年就推出了, 那時候根本沒有Android和iOS, 所以GA最開始是網(wǎng)站用的, FA是今年推出的, 從一開始目標(biāo)就是移動應(yīng)用.

然后作者總結(jié)了FA的優(yōu)勢和當(dāng)前存在的幾個不足.

最后的結(jié)論就是:
如果你只有app, 用FA; 如果你只有網(wǎng)站, 用GA; 如果你兩個都有, 則兩個都用.

VectorDrawable Fill Windings

作者有一個Sketch做的資源, 是一個空洞圖, 結(jié)果放在程序里看的時候中間的洞沒有了, 變成實心的了.

作者分析并詳細(xì)解釋了出現(xiàn)這種問題的原因, 并提供了兩種解決方案.

DESIGN

Basic Patterns for Mobile Navigation

這篇文章作者分析了三種導(dǎo)航模式: hamburger menu, tab bar和gesture-base navigation.

Hamburger Menu

Pros: 導(dǎo)航選項多, 設(shè)計干凈, 給主要內(nèi)容留出了更多空間.

Cons: 不易被發(fā)現(xiàn).
在iOS實現(xiàn)時, 和iOS的基本導(dǎo)航元素沖突.
hamburger的icon并沒有給出上下文.
需要點兩下才到目標(biāo)頁面.

Tips: 給選項排列優(yōu)先級. 如果你的高優(yōu)先級選項不多, 可以考慮用tabs或者tab bar. 重審你的信息結(jié)構(gòu), 有沒有必要劃分成多個簡單的app.

Tab Bar

Pros: Tab bar可以反映出當(dāng)前在哪. 它們是永久存在的, 用戶可以單擊訪問.

Cons: 有限的選項數(shù). iOS和Android可能會有不同的設(shè)計規(guī)范.

Tips: 讓點擊區(qū)域足夠大. icon要經(jīng)過可用性測試. icon和label一起用.

Gesture-Based Navigation

Pros: 移除了UI雜項, 節(jié)約了屏幕空間. 自然的人機(jī)交互接口.

Cons: 導(dǎo)航不可見. 增加了用戶教育成本.

Tips: 確保不要必須教給用戶一種全新的交互方式, 設(shè)計相似的體驗. 使用過程動畫的形式教用戶如何使用.

Design Reviews: Going beyond the surface

關(guān)于設(shè)計的review.

LIBRARIES & CODE

green-coffee

一個Android庫, 讓你可以在instrumentation測試中跑Cucumber.

ThirtyInch

一個Android MVP庫.

Tools

Exynap

一個Android Studio插件, 可以生成實現(xiàn)代碼.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子缸剪,更是在濱河造成了極大的恐慌,老刑警劉巖息楔,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異扒披,居然都是意外死亡值依,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進(jìn)店門碟案,熙熙樓的掌柜王于貴愁眉苦臉地迎上來愿险,“玉大人,你說我怎么就攤上這事价说×究鳎” “怎么了?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵鳖目,是天一觀的道長扮叨。 經(jīng)常有香客問我,道長疑苔,這世上最難降的妖魔是什么甫匹? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任甸鸟,我火速辦了婚禮惦费,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘抢韭。我一直安慰自己薪贫,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布刻恭。 她就那樣靜靜地躺著瞧省,像睡著了一般扯夭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上鞍匾,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天交洗,我揣著相機(jī)與錄音,去河邊找鬼橡淑。 笑死构拳,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的梁棠。 我是一名探鬼主播置森,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼符糊!你這毒婦竟也來了凫海?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤男娄,失蹤者是張志新(化名)和其女友劉穎行贪,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體模闲,經(jīng)...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡瓮顽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了围橡。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片暖混。...
    茶點故事閱讀 38,650評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖翁授,靈堂內(nèi)的尸體忽然破棺而出拣播,到底是詐尸還是另有隱情,我是刑警寧澤收擦,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布贮配,位于F島的核電站,受9級特大地震影響塞赂,放射性物質(zhì)發(fā)生泄漏泪勒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一宴猾、第九天 我趴在偏房一處隱蔽的房頂上張望圆存。 院中可真熱鬧,春花似錦仇哆、人聲如沸沦辙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽油讯。三九已至详民,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間陌兑,已是汗流浹背沈跨。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留兔综,地道東北人谒出。 一個月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像邻奠,于是被迫代替她去往敵國和親笤喳。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,527評論 2 349

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,777評論 25 707
  • 太長了碌宴,還是轉(zhuǎn)載吧...今天在看博客的時候杀狡,無意中發(fā)現(xiàn)了@Trinea在GitHub上的一個項目Android開源...
    龐哈哈哈12138閱讀 20,154評論 3 283
  • 近幾年隨著國人海外出游人數(shù)的不斷增加,中國游客的一舉一動一直是熱議話題贰镣。中國人是訪日外國游客的主力軍呜象,“爆買”給日...
    在日本閱讀 409評論 0 0
  • 要習(xí)慣有人陪, 也要習(xí)慣一切都會抽身而去碑隆。 愛的人恭陡, 執(zhí)著的事。 終將上煤, 了無影蹤休玩。
    清雨云升閱讀 235評論 0 0
  • 2四月的天 應(yīng)該春光明媚拴疤,微風(fēng)和煦 又是一個天氣突變的早晨 我身著一身輕薄春裝出門 一身著裝非黑即白 就如我追求的...
    傾蓶閱讀 239評論 0 1