第十八章 Android的數(shù)據(jù)存儲方案(二)

6.ContentProvider存儲

ContentProvider(內(nèi)容提供者)是Android 的四大組件之一。主要用于對外共享數(shù)據(jù),也就是說通過將ContentProvider將數(shù)據(jù)中的資源,分享給其他應(yīng)用訪問。其他應(yīng)用可以通過ContentProvider對指定應(yīng)用中的數(shù)據(jù)進(jìn)行操作。ContentProvider分為系統(tǒng)的和自定義的,系統(tǒng)的也就是例如聯(lián)系人,圖片等數(shù)據(jù)。交互關(guān)系如圖所示:

ContentProvider的數(shù)據(jù)交互

??看了這個會覺得很奇怪,為什么不直接和數(shù)據(jù)庫交互呢?還要通過ContentProvider進(jìn)行交互。主要是Android的安全性問題決定的,它的數(shù)據(jù)庫是私有的,所以外部數(shù)據(jù)無法直接訪問這個數(shù)據(jù)庫。所以提供了這個ContentProvider 內(nèi)容提供者,將數(shù)據(jù)庫的內(nèi)容提供給外部應(yīng)用,同時將外部應(yīng)用的數(shù)據(jù)存儲到數(shù)據(jù)庫中。如果外部應(yīng)用想要操作數(shù)據(jù)庫暴露的數(shù)據(jù)時,需要ContentResolver來操作ContentProvider暴露的數(shù)據(jù)。
??一旦某個應(yīng)用通過ContentProvider暴露了數(shù)據(jù),那么不管該應(yīng)用程序是否啟動,其他的應(yīng)用都能通過該接口操作暴露的數(shù)據(jù),對數(shù)據(jù)進(jìn)行增刪查改的操作。

6.1 ContentProvider的核心類

1、ContentProvider:(A應(yīng)用暴露數(shù)據(jù))

● 一個程序可以通過實現(xiàn)一個ContentProvider的抽象接口將自己的數(shù)據(jù)暴露出去;
● 外界根本看不到,也不用看到這個應(yīng)用暴露的數(shù)據(jù)在應(yīng)用當(dāng)中是如何存儲的,是用數(shù)據(jù)庫存儲還是用文件存儲,還是通過網(wǎng)上獲得,這些一切都不重要,重要的是外界可以通過這一套標(biāo)準(zhǔn)及統(tǒng)一的接口和程序里的數(shù)據(jù)打交道,可以讀取程序的數(shù)據(jù),也可以修改程序的數(shù)據(jù)。

2、ContentResolver:(操作A應(yīng)用所暴露的數(shù)據(jù))

● 外界的程序通過ContentResolver接口可以訪問ContentProvider提供的數(shù)據(jù);
● ContentResolver 可以理解成是HttpClient的作用。

3、 Uri:Uri是ContentResolver和ContentProvider進(jìn)行數(shù)據(jù)交換的標(biāo)識。

● 每個ContentProvider提供公共的URI來唯一標(biāo)識其數(shù)據(jù)集。管理多個數(shù)據(jù)集的(多個表)的 ContentProvider 為每個數(shù)據(jù)集提供了單獨的URI。

Uri 的標(biāo)準(zhǔn)前綴:以“content://”作為前綴,這個是標(biāo)準(zhǔn)的前綴,表示該數(shù)據(jù)由ContentProvider 管理。Android所提供的ContentProvider都存放在andriod.provider這個包里面 Android的ContentProvider URI有固定的形式:content://contract/people

● Uri 的authority部分:該部分是完整的類名。(使用小寫形式)。
● Uri 的path部分(資源部分、數(shù)據(jù)部分): 用于決定哪類數(shù)據(jù)被請求。
● 被請求的特定記錄的id值。如果請求不僅限于某個單條數(shù)據(jù),該部分及其前面的斜線應(yīng)該刪除。
● 為了將一個字符串轉(zhuǎn)換成Uri,Android中提供了Uri的parse()靜態(tài)方法來實現(xiàn)。

通配符的使用

這個 * :表示匹配任意長度的任意字符
這個 # :表示匹配任意長度的數(shù)字

【備注:】URI、URL、URN的區(qū)別:
● 首先,URI,是uniform resource identifier,統(tǒng)一資源標(biāo)識符,用來唯一的標(biāo)識一個資源。

● URL是uniform resource locator,統(tǒng)一資源定位器,它是一種具體的URI,即URL可以用來標(biāo)識一個資源,而且還指明了如何locate這個資源。

● URN,uniform resource name,統(tǒng)一資源命名,是通過名字來標(biāo)識資源,比如mailto:java-net@java.sun.com

也就是說,URI是以一種抽象的,高層次概念定義統(tǒng)一資源標(biāo)識,而URL和URN則是具體的資源標(biāo)識的方式。URL和URN都是一種URI。
總結(jié)一下:URL是一種具體的URI,它不僅唯一標(biāo)識資源,而且還提供了定位該資源的信息。URI是一種語義上的抽象概念,可以是絕對的,也可以是相對的,而URL則必須提供足夠的信息來定位,所以,是絕對的。

6.2 ContentProvider 訪問其他程序中的數(shù)據(jù)

ContentProvider 的用法有兩種:一種是使用現(xiàn)有的內(nèi)容提供器來讀取和操作相應(yīng)的程序中的數(shù)據(jù),另一種是創(chuàng)建者自己的內(nèi)容提供器暴露程序的外部數(shù)據(jù)。Android 系統(tǒng)中自帶的電話簿,短信,媒體庫等程序都提供了類似的訪問接口,這就使得第三應(yīng)用程序可以充分利用這部分?jǐn)?shù)據(jù)來實現(xiàn)更好的功能。

6.2.1 ContentResolver的基本用法

如果一個外部應(yīng)用程序想訪問內(nèi)容提供器中暴露的數(shù)據(jù),那么就一定要借助ContentResolver()方法。Context類中提供了getContentResolver()的方法獲取該類的實例。此外ContentResolver還提供了一系列的方法對數(shù)據(jù)進(jìn)行CRUD操作。和SQLiteDatabase的使用的方法一樣,insert()插入數(shù)據(jù),update()更新數(shù)據(jù),delete()刪除數(shù)據(jù),query()查詢數(shù)據(jù)。不同的是ContentResolver中的增刪查改方法方法都是不接受表名的,而是用Uri來替代。
??上面說了Uri的一些知識點,這里再詳細(xì)說一下。Uri給內(nèi)容提供器的數(shù)據(jù)創(chuàng)建了一個唯一的標(biāo)識符,它由兩部分組成:authority 和path。authority是對不同應(yīng)用程序做區(qū)分的,一般為了避免沖突,設(shè)置為包名。eg:我的項目包名為 com.demo.filesavedemo,那么這個程序的authority 就設(shè)置為com.demo.filesavedemo.provider。path是在該應(yīng)用程序內(nèi)的對不同的表的區(qū)分。通常加到authority的后面。eg:數(shù)據(jù)庫里面有兩張表 tab1和tab2,然后path 分別命名為/tab1和/tab2,最后別忘了在頭部加上前綴content:// 。所以Uri最標(biāo)準(zhǔn)的寫法為:
content://com.demo.filesavedemo.provider/tab1
content://com.demo.filesavedemo.provider/tab2
??通過這樣的Uri,我們就可以很清楚的表達(dá)了我們想要訪問的哪個程序里面的哪張表的數(shù)據(jù)了。如果你還想訪問表tab1里面的某個數(shù)據(jù)的話,可以在/tab1的后面加上你想訪問的數(shù)據(jù)。eg:加入你想訪問表tab1里面的person變量的某一個值,那么首先找到它對應(yīng)的id 的值,比如是10,所以Uri的寫法為:content://com.demo.filesavedemo.provider/tab1/person/10。這樣你就能找到對應(yīng)的值了。如果要找10這個id對應(yīng)的name字段,再加上/name。content://com.demo.filesavedemo.provider/tab1/person/10/name。依次類推

Uri的結(jié)構(gòu)圖
6.2.1.1 查詢數(shù)據(jù)的操作

得到Uri對應(yīng)的字符串之后,還要將它解析成Uri對象才可以作為參數(shù)傳入。需要調(diào)用ri.parse()方法。

Uri uri=Uri.parse("content://com.demo.filesavedemo.provider/tab1")
//查詢tabl
Cursor cursor = getContentResolver().query(
     uri,
    projection,
    selection,
    selectionArgs,
    sortOrder);
query() 方法參數(shù) 對應(yīng)的SQL部分 描 述
uri from table_name 指定查詢某個應(yīng)用的表名
projection select column1 ,column2 指定查詢的列名
selection where column1 = value 指定where的約束條件
selectionArgs - 為where的占位符提供具體的值
sortOrder order by column1,colimn2 指定查詢結(jié)果的排序方式

查詢完成之后還是返回一個Cursor對象。取出每行中相應(yīng)列的數(shù)據(jù)。

if(cursor!=null){
while(cursor.moveToNext()){
String  column1=cursor.getString(cursor.getColumnIndex("列的名字"));
int  column2=cursor.getInt(cursor.getColumnIndex("列的名字"));
}
cursor.close();
}

方法上大致和SQLDatabase差不多。

6.2.1.2 添加數(shù)據(jù)的操作

SQLDatabase的添加數(shù)據(jù)庫操作,需要用上ContentValues對象,這里也是一樣:

ContentValues  values=new ContentValues();
values.put("name","小王");
values.put("age",18);
getContentResolver().insert(uri,values);
6.2.1.3 更新數(shù)據(jù)庫操作

如果想要更新這新添加的數(shù)據(jù)庫的數(shù)據(jù),把name的值改為小六,然后借用update()的方法。

ContentValues  values=new ContentValues();
values.put("name","小六");
getContentResolver().update(uri,values,"name=? and age = ?",new String[]{"小王","18"});

這里指定了selection 和selectionArgs,控制范圍,放置別的行受影響。

6.2.1.4 刪除數(shù)據(jù)庫的操作

加入需要刪除掉 age=18 這一列

getContentResolver.delete(uri,"age=?",new String []{"18"});

到這里,增刪查改都過了一遍,和之前的差別不大,很容易理解,不過要注意參數(shù)的意思。

6.3 創(chuàng)建自己的內(nèi)容提供器

6.3.1 UriMatcher類的介紹

我們知道Uri是ContentProvider暴露數(shù)據(jù)的關(guān)鍵,通過Uri可以指定需要查詢的表。假設(shè)有這么一個場景,在一個數(shù)據(jù)源包含有多個內(nèi)容(多張表),那么我們查詢的時候就需要多個Uri來指向?qū)?yīng)的表。那么在查詢了tab1之后還需要查詢tab2怎么辦呢?可不可以從tab1過濾到tab2呢?顯然是可以的。這時候使用UriMatcher就可以幫助我們方便的過濾到TableA還是TableB, 然后進(jìn)行下一步查詢, 如果不用UriMatcher也可以,我們就需要手動過濾字符串,用起來有點麻煩,可維護(hù)性也不好。

6.3.2 UriMatcher的使用

在使用之前可以看下UriMatcher的源碼。

   private static final int PEOPLE = 1;
    private static final int PEOPLE_ID = 2;
    private static final int PEOPLE_PHONES = 3;
    private static final int PEOPLE_PHONES_ID = 4;
    private static final int PEOPLE_CONTACTMETHODS = 7;
    private static final int PEOPLE_CONTACTMETHODS_ID = 8;

    private static final int DELETED_PEOPLE = 20;

    private static final int PHONES = 9;
    private static final int PHONES_ID = 10;
    private static final int PHONES_FILTER = 14;

    private static final int CONTACTMETHODS = 18;
    private static final int CONTACTMETHODS_ID = 19;

    private static final int CALLS = 11;
    private static final int CALLS_ID = 12;
    private static final int CALLS_FILTER = 15;

 private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    static
    {
        sURIMatcher.addURI("contacts", "people", PEOPLE);
        sURIMatcher.addURI("contacts", "people/#", PEOPLE_ID);
        sURIMatcher.addURI("contacts", "people/#/phones", PEOPLE_PHONES);
        sURIMatcher.addURI("contacts", "people/#/phones/#", PEOPLE_PHONES_ID);
        sURIMatcher.addURI("contacts", "people/#/contact_methods", PEOPLE_CONTACTMETHODS);
        sURIMatcher.addURI("contacts", "people/#/contact_methods/#", PEOPLE_CONTACTMETHODS_ID);
        sURIMatcher.addURI("contacts", "deleted_people", DELETED_PEOPLE);
        sURIMatcher.addURI("contacts", "phones", PHONES);
        sURIMatcher.addURI("contacts", "phones/filter/*", PHONES_FILTER);
        sURIMatcher.addURI("contacts", "phones/#", PHONES_ID);
        sURIMatcher.addURI("contacts", "contact_methods", CONTACTMETHODS);
        sURIMatcher.addURI("contacts", "contact_methods/#", CONTACTMETHODS_ID);
        sURIMatcher.addURI("call_log", "calls", CALLS);
        sURIMatcher.addURI("call_log", "calls/filter/*", CALLS_FILTER);
        sURIMatcher.addURI("call_log", "calls/#", CALLS_ID);
    }

很簡單,首先是實例化UriMatcher ,然后是addURI()注冊需要的Uri。源碼中是放在一個靜態(tài)塊中的,我們在開發(fā)的時候只需要這樣寫就好,后面的PEOPLE,PEOPLE_ID這些都是在返回碼。有了這些返回碼,我們才能區(qū)別Uri,也可以自己定義。
總之,UriMatcher本質(zhì)上是一個文本過濾器,用在contentProvider中幫助我們過濾,分辨出查詢者想要查詢哪個數(shù)據(jù)表。

6.3.3 創(chuàng)建自己的內(nèi)容提供器

首先點擊包->New->Other->Content Provider ,彈出的頁面上,如下所示,新建MyContentProvider 類繼承 ContentProvider,然后重寫這6個方法,再借助UriMatch類就可以實現(xiàn)匹配Uri了。

新建一個ContentProvider類

Exported屬性,表示是否允許外部程序訪問ContentProvider;Enable表示是否啟用這個ContentProvider。這樣就會自動在AndroidManifest.xml自動注冊

        <provider
            android:name=".ContentProvider.MyContentProvider"
            android:authorities="com.demo.filesavedemo"
            android:enabled="true"
            android:exported="true"></provider>

下面對著幾個方法做一個簡單的介紹:

1.onCreate() ,初始化ContentProvider 的時候調(diào)用,在這里完成數(shù)據(jù)庫的創(chuàng)建和升級。返回true表示成功,返回false 表示失敗。注意只有當(dāng)ContentResolver嘗試訪問成熟中的數(shù)據(jù)的時候,內(nèi)容提供器才會初始化。
2.query() 查詢數(shù)據(jù) ,之前提過。
3.insert() 插入數(shù)據(jù) ,之前提過。
4.delete() 刪除數(shù)據(jù) , 之前提過。
5.update() 更新數(shù)據(jù),之前提過。
6.getType() 這個方法有點特別,它根據(jù)傳入的URI來返回相應(yīng)的MIME類型( MIME (Multipurpose Internet Mail Extensions) 是描述消息內(nèi)容類型的因特網(wǎng)標(biāo)準(zhǔn)。 MIME 消息能包含文本、圖像、音頻、視頻以及其他應(yīng)用程序?qū)S玫臄?shù)據(jù)。)。可以看到幾乎每個方法都帶有Uri這個參數(shù),這個參數(shù)也正是調(diào)用ContentResolver的增刪查改方法傳過來的。現(xiàn)在需要對Uri進(jìn)行解析,從中分析出希望訪問的表和數(shù)據(jù)。一個Uri所對應(yīng)的MIME字符串主要由3部分組成。Android 對這3個部分做了格式規(guī)定:

  • 必須以 vnd開頭
  • 如果URI以路徑結(jié)尾,則后接android.cursor.dir/,如果URI以id結(jié)尾,則后接上android.cursor.item/
  • 最后接上vnd.<authority>.<path>
    例如:1. content://com.demo.filesavedemo.provider/tab1 ,所對應(yīng)的MIME類型為:
    ???vnd.android.cursor.dir/vnd.com.demo.filesavedemo.provider.tab1
    ??2. content://com.demo.filesavedemo.provider/tab1/person/10,所對應(yīng)的MIME類型為:
    ???vnd.android.cursor.item/vnd.com.demo.filesavedemo.provider.tab1
public class Myprovider extends ContentProvider {

    private static final int TABLE_DIR = 0;
    private static final int TABLE_ITEM = 1;
    private static final int TABLE2_DIR = 2;
    private static final int TABLE2_ITEM = 3;
    private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    static {
        sURIMatcher.addURI("com.demo.filesavedemo.ContentProvider","table1",TABLE_DIR);
        sURIMatcher.addURI("com.demo.filesavedemo.ContentProvider","table1/#",TABLE_ITEM);
        sURIMatcher.addURI("com.demo.filesavedemo.ContentProvider","table2",TABLE2_DIR);
        sURIMatcher.addURI("com.demo.filesavedemo.ContentProvider","table2/#",TABLE2_ITEM);
    }
    @Override
    public boolean onCreate() {
        return false;
    }

    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        switch (sURIMatcher.match(uri)){
            case TABLE_DIR:
             return "vnd.android.cursor.dir/vnd.com.demo.filesavedemo.ContentProvider.table1";
            case TABLE_ITEM:
                return "vnd.android.cursor.item/vnd.com.demo.filesavedemo.ContentProvider.table1";
            case TABLE2_DIR:
                return "vnd.android.cursor.dir/vnd.com.demo.filesavedemo.ContentProvider.table2";
            case TABLE2_ITEM:
                return "vnd.android.cursor.item/vnd.com.demo.filesavedemo.ContentProvider.table2";
            default:
                break;
        }
        return null;
    }
    
    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] strings, @Nullable String s, @Nullable String[] strings1, @Nullable String s1) {
        switch (sURIMatcher.match(uri)){
            case TABLE_DIR:
                //查詢table1表中的所有的數(shù)據(jù)
                break;
            case TABLE_ITEM:
                //查詢table1表中的單條的數(shù)據(jù)
                break;
            case TABLE2_DIR:
                //查詢table2表中的所有的數(shù)據(jù)
                break;
            case TABLE2_ITEM:
                //查詢table2表中的單條的數(shù)據(jù)
                break;
        }
        return null;
    }

   
//其他的方法和query方法一樣,都會攜帶uri,然后根據(jù)UriMatcher的match()方法來判斷,
// 出調(diào)方希望返回哪張表,再根據(jù)表來操作
    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues contentValues) {
        return null;
    }

    @Override
    public int delete(@NonNull Uri uri, @Nullable String s, @Nullable String[] strings) {
        return 0;
    }

    @Override
    public int update(@NonNull Uri uri, @Nullable ContentValues contentValues, @Nullable String s, @Nullable String[] strings) {
        return 0;
    }
}

7.網(wǎng)絡(luò)存儲

網(wǎng)絡(luò)存儲一般都是將數(shù)據(jù)存儲在服務(wù)器或者第三方服務(wù)器等,然后android 端通過http協(xié)議/Tcp協(xié)議等網(wǎng)絡(luò)請求來獲取數(shù)據(jù)。因為首先需要自己準(zhǔn)備服務(wù)器,所以這里給一個網(wǎng)上的例子。

import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import android.app.Activity;
import andorid.os.Bundle;
public class MyAndroidWeatherActivity extends Activity{

private static final String SERVER_URL="http://www.webservicex.net/WeatherForecast.asmx/GetWeatherByPlaceName";

public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
HttpPost request=new HttpPost(SERVER_URL);//根據(jù)內(nèi)容來源地址創(chuàng)建一個Http請求
//添加一個變量
List<NameValuePair> params=new ArrayList<NameValuePair>();
//設(shè)置一個地區(qū)名稱
params.add(new BasicNameValuePair("PlaceName","NewYork"));//添加必須的參數(shù)
try{
//設(shè)置參數(shù)的編碼
request.setEntity(new UrlEncodedFormEntity(params,HTTP.UTF_8));
//發(fā)送請求并獲取反饋
HttpResponse httpResponse=new DefaultHttpClient().execute(request);
//解析返回的內(nèi)容
if(httpResponse.getStatusLine().getStatusCode()!=404){
String result=EntityUtils.toString(httpResponse.getEntity());
System.out.printlin(result);
}
}catch(Exception e){
e.printStackTrace();
}}}

github地址:https://github.com/wangxin3119/myContentProvider

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,197評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,415評論 3 415
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,104評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,884評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,647評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,130評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,208評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,366評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,887評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,737評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,939評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,478評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,174評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,586評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,827評論 1 283
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,608評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,914評論 2 372

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