ContentProvider基礎(chǔ)操作

ContentProvider是Android四大組件之一,它為存儲和獲取數(shù)據(jù)提供統(tǒng)一的接口。即將應(yīng)用程序的數(shù)據(jù)提供給外部程序使用的一種手段和方法。最大特點是可以實現(xiàn)不同的應(yīng)用程序之間共享數(shù)據(jù)。

對于ContentProvider來說,無論數(shù)據(jù)的來源是什么留储,他都認為是一種表,它會把數(shù)據(jù)組織成表格咙轩。

兩種使用情景:1.A應(yīng)用訪問B應(yīng)用获讳,2A應(yīng)用訪問系統(tǒng)應(yīng)用(通訊錄)

1A應(yīng)用訪問B應(yīng)用:(主要是實現(xiàn)定義一個ContentProvider的操作)

(1)自定義一個類繼承于ContentProvider,并且實現(xiàn)它的方法:注意操作步驟

想要建立文件的地方->右鍵->new->other->Content Provider->修改名稱,填寫唯一的uri->完成活喊。

public class OutContentProvider extends ContentProvider {
    public OutContentProvider() {
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        // Implement this to handle requests to delete one or more rows.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public String getType(Uri uri) {
        // TODO: Implement this to handle requests for the MIME type of the data
        // at the given URI.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        // TODO: Implement this to handle requests to insert a new row.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public boolean onCreate() {
        // TODO: Implement this to initialize your content provider on startup.
        return false;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
                        String[] selectionArgs, String sortOrder) {
        // TODO: Implement this to handle query requests from clients.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection,
                      String[] selectionArgs) {
        // TODO: Implement this to handle requests to update one or more rows.
        throw new UnsupportedOperationException("Not yet implemented");
    }
}

然后看一下manifest.xml:

  <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <provider
            android:name=".OutContentProvider"
            android:authorities="com.stone.mycontentprovider.outcp"
            android:enabled="true"
            android:exported="true"></provider>

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

當然也可以先自定義個類丐膝,然后繼承ContentProvider,實現(xiàn)他的方法,然后配置mainfest.xml帅矗。

ok偎肃,下一步。

(2)由于這是一個簡單的使用步驟浑此,所以就簡單的按照sqlite數(shù)據(jù)庫來寫累颂,當然數(shù)據(jù)的來源還可以是其他的任何的一種,這里只是舉個例子

由于ContentProvider的創(chuàng)建是在應(yīng)用第一次打開的時候就創(chuàng)建的凛俱,所以為了方便吧數(shù)據(jù)也在ContentProvider中創(chuàng)建了

 SQLiteDatabase sqLiteDatabase;

  @Override
    public boolean onCreate() {
        // TODO: Implement this to initialize your content provider on startup.
        //創(chuàng)建數(shù)據(jù)庫
        Log.e("###", "onCreate");
        SQLiteOpenHelper helper = new SQLiteOpenHelper(getContext(), "outcp.db", null, 1) {
            @Override
            public void onCreate(SQLiteDatabase db) {
                //創(chuàng)建表格
                String sql = "create table demo_table(_id integer primary key autoincrement," +
                        "name varchar(20)," +
                        "age integer," +
                        "gender varchar(2))";
                db.execSQL(sql);
            }

            @Override
            public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

            }
        };
        sqLiteDatabase = helper.getReadableDatabase();
        //返回true紊馏,這樣才能會返回數(shù)據(jù)
        return true;
    }

注意返回值改成true。

(3)insert()方法:增加數(shù)據(jù)蒲犬,在OutContentProvider中

  @Override
    public Uri insert(Uri uri, ContentValues values) {
        // TODO: Implement this to handle requests to insert a new row.
//        throw new UnsupportedOperationException("Not yet implemented");
        Long itemId = 0l;
        try {
            itemId = sqLiteDatabase.insertOrThrow("demo_table", null, values);
        } catch (Exception e) {
            Log.e("###", e.getLocalizedMessage());
        }
        Log.e("###", "調(diào)用了out中的insert方法");
        //表名朱监,非空列,值,對于sqlite數(shù)據(jù)庫原叮,添加完成之后會返回一個Long的id
        //uri這個uri就是另外的程序調(diào)用contentprovider的時候傳過來的uri赫编,如果傳回去那么跟調(diào)用程序的uri沒有區(qū)別也沒有意義
        // 所以用ContentUris把uri和itemid整合一下,成為一個新的Uri奋隶,返回回去擂送。
        return ContentUris.withAppendedId(uri, itemId);
    }

注意:這里的 try {}catch((Exception e){} 可以不寫,insertOrThrow可以改成insert达布。另外ContentUris是處理uri的一個類团甲, ContentUris.withAppendedId(uri, itemId)是吧uri追加一個id作為返回值,為了方便調(diào)用者獲取到添加成功的狀態(tài)和id黍聂。

(4)insert()方法的調(diào)用:這里需要新建一個其他的項目,在調(diào)用項目的合適的位置寫一個調(diào)用方法身腻。這里寫了一個textview的點擊監(jiān)聽事件:

 Uri mUri = Uri.parse("content://com.stone.mycontentprovider.outcp");
ContentResolver resolver;
  @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
     
        //獲取ContentResolver對象
        resolver = getContentResolver();
    }

   public void insertTv(View view) {
        ContentValues values = new ContentValues();
        values.put("name", MyUtils.getChineseName());
        values.put("age", MyUtils.getNum(10, 60));
        values.put("gender", MyUtils.getGender());

        Uri reUri = resolver.insert(mUri, values);
        Long reId = ContentUris.parseId(reUri);
        Toast.makeText(MainActivity.this, reId + "", Toast.LENGTH_LONG).show();
    }

注意:這里的uri就是ContentProvider提供者的insert方法返回的我們添加了id的那個uri产还,同樣的我們使用ContentUris這個類的 ContentUris.parseId(reUri);方法拿到添加成功的數(shù)據(jù)的id。

(5)query()查詢方法:

  @Override
    public Cursor query(Uri uri, String[] projection, String selection,
                        String[] selectionArgs, String sortOrder) {
        // TODO: Implement this to handle query requests from clients.
//        throw new UnsupportedOperationException("Not yet implemented");
        Cursor cursor = sqLiteDatabase.query("demo_table", projection, selection, selectionArgs, null, null, sortOrder);
        return cursor;
    }

(6)調(diào)用查詢方法:

SimpleCursorAdapter simpleCursorAdapter;
 ListView mListView;

 public void queryTv(View view) {
// 根據(jù)contentprovider中的查詢方法:Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder)
        //rui,查詢哪一列嘀趟,查詢條件脐区,條件之,排序
        Cursor cursor = resolver.query(mUri, null, null, null, null);
        //這里的listview的adapter用到SimpleCursorAdapter
        simpleCursorAdapter = new SimpleCursorAdapter(this,
                R.layout.layout_adapter_cursor,
                cursor,
                new String[]{"_id", "name", "age", "gender"},
                new int[]{R.id.item_id, R.id.item_name, R.id.item_age, R.id.item_gender},
                CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
        mListView.setAdapter(simpleCursorAdapter);

    }

注意這里直接用的SimpleCursorAdapter其中的參數(shù)分別是:SimpleCursorAdapter(context,layout,cursor,鍵名的字符串數(shù)組她按,對應(yīng)的控件的id牛隅,標志).關(guān)于SimpleCursorAdapter有一篇博客可以看一下

(7)delete():刪除方法

  @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        // Implement this to handle requests to delete one or more rows.
//        throw new UnsupportedOperationException("Not yet implemented");
      int result = sqLiteDatabase.delete("demo_table", selection, selectionArgs);
      return result;
    }

(8)調(diào)用刪除方法:

                    int delResult = resolver.delete(mUri, "_id=?", new String[]{itemId});
                        if (delResult > 0) {
                            Toast.makeText(MainActivity.this, "刪除成功", Toast.LENGTH_LONG).show();
                        } else {
                            Toast.makeText(MainActivity.this, "刪除灰白", Toast.LENGTH_LONG).show();
                        }

(9)修改updata()方法

  @Override
    public int update(Uri uri, ContentValues values, String selection,
                      String[] selectionArgs) {
        // TODO: Implement this to handle requests to update one or more rows.
//        throw new UnsupportedOperationException("Not yet implemented");
        int upReslut = sqLiteDatabase.update("demo_table", values, selection, selectionArgs);
        return upReslut;
    }

(10)調(diào)用修改方法:

 ContentValues upValues = new ContentValues();
      upValues.put("name", MyUtils.getChineseName());
         upValues.put("age", MyUtils.getNum(10, 60));
        upValues.put("gender", MyUtils.getGender());
          int upResult=resolver.update(mUri,upValues,"_id=?",new String[]{itemId});
          if (upResult>0){
               Toast.makeText(MainActivity.this, "修改成功", Toast.LENGTH_LONG).show();
               } else {
              Toast.makeText(MainActivity.this, "修改灰白", Toast.LENGTH_LONG).show();
           }

ok,以上記錄的是設(shè)置ContentProvider的方法酌泰,和相應(yīng)的方法的調(diào)用然后再看一下關(guān)于Uri的解析媒佣。

Uri解析有兩種方法,一種是使用UriMatcher解析陵刹,一種是Uri自帶的解析默伍。

(一)UriMatcher解析:事先制定好匹配規(guī)則,當調(diào)用ContentProvide中的方法時,利用制定好的匹配規(guī)則匹配uri也糊,根據(jù)不同的uri給出不同的處理:以刪除為例在oncreat中制定規(guī)則:

UriMatcher matcher;
 @Override
    public boolean onCreate() {
        // TODO: Implement this to initialize your content provider on startup.
        //闖將數(shù)據(jù)庫
        Log.e("###", "onCreate");
        //匹配規(guī)則:
        //UriMatcher.NO_MATCH:無法匹配
        matcher = new UriMatcher(UriMatcher.NO_MATCH);
        matcher.addURI("com.stone.mycontentprovider.outcp", "democp", 1000);
        matcher.addURI("com.stone.mycontentprovider.outcp", "democp/child", 1001);
        matcher.addURI("com.stone.mycontentprovider.outcp", "democp/#", 1002);//后面是數(shù)字
        matcher.addURI("com.stone.mycontentprovider.outcp", "democp/*", 1003);//任意字符
        //返回true炼蹦,這樣才能會返回數(shù)據(jù)
        return true;
    }

注意:其中的democp可以使任意的字符串,也可以沒有狸剃。
刪除方法:

  @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        // Implement this to handle requests to delete one or more rows.
//        throw new UnsupportedOperationException("Not yet implemented");
        int result = 0;
        int code = matcher.match(uri);
        switch (code) {
            case 1000:
                Log.e("###match","匹配到的路徑是"+uri.toString());
                break;
            case 1001:
                Log.e("###match","匹配到的路徑是"+uri.toString());
                break;
            case 1002:
                Log.d("###match","匹配到路徑為"+uri.toString()+"任意數(shù)字的內(nèi)容");
                break;
            case 1003:
                Log.i("###match","匹配到路徑為"+uri.toString()+"任意字符的內(nèi)容");
                break;
            default:
                Log.e("###match","執(zhí)行刪除數(shù)據(jù)庫內(nèi)容的方法");
                result = sqLiteDatabase.delete("demo_table", selection, selectionArgs);
                break;
        }
        return result;
    }

那么調(diào)用刪除方法:

                 resolver.delete(Uri.parse("content://com.stone.mycontentprovider.outcp/democp"),null,null);
                   resolver.delete(Uri.parse("content://com.stone.mycontentprovider.outcp/democp/child"),null,null);
                        resolver.delete(Uri.parse("content://com.stone.mycontentprovider.outcp/democp/123"),null,null);
                        resolver.delete(Uri.parse("content://com.stone.mycontentprovider.outcp/democp/090"),null,null);
                        resolver.delete(Uri.parse("content://com.stone.mycontentprovider.outcp/democp/89ii"),null,null);
                        resolver.delete(Uri.parse("content://com.stone.mycontentprovider.outcp/democp/ab90"),null,null);
                        resolver.delete(Uri.parse("content://com.stone.mycontentprovider.outcp/123/ab90"),null,null);

運行結(jié)果:

E/###match: 匹配到的路徑是content://com.stone.mycontentprovider.outcp/democp
E/###match: 匹配到的路徑是content://com.stone.mycontentprovider.outcp/democp/child
D/###match: 匹配到路徑為content://com.stone.mycontentprovider.outcp/democp/123任意數(shù)字的內(nèi)容
D/###match: 匹配到路徑為content://com.stone.mycontentprovider.outcp/democp/090任意數(shù)字的內(nèi)容
I/###match: 匹配到路徑為content://com.stone.mycontentprovider.outcp/democp/89ii任意字符的內(nèi)容
I/###match: 匹配到路徑為content://com.stone.mycontentprovider.outcp/democp/ab90任意字符的內(nèi)容
E/###match: 執(zhí)行刪除數(shù)據(jù)庫內(nèi)容的方法

(二)Uri自帶的解析方法:以添加為例:

調(diào)用添加方法:

  Uri othUri=resolver.insert(Uri.parse("content://com.stone.mycontentprovider.outcp/anypath?name="+MyUtils.getChineseName()
        +"&age="+MyUtils.getNum(10, 60)
        +"&gender="+ MyUtils.getGender()),new ContentValues());

注意其中的anypath可以使任意的字符串掐隐,也可以不要。
MyContentProvider中的添加方法:

  @Override
    public Uri insert(Uri uri, ContentValues values) {
        // TODO: Implement this to handle requests to insert a new row.
//        throw new UnsupportedOperationException("Not yet implemented");

        Long itemId = 0l;
        if (values.size()>0){
            try {
                itemId = sqLiteDatabase.insertOrThrow("demo_table", null, values);
            } catch (Exception e) {
                Log.e("###", e.getLocalizedMessage());
            }
        }else {
            String authory=uri.getAuthority();
            Log.e("###authory",authory);
            String path=uri.getPath();
            Log.e("###path",path);
            String query=uri.getQuery();
            Log.e("###query",query);
            String name=uri.getQueryParameter("name");
            Log.e("###name",name);
            String age=uri.getQueryParameter("age");
            Log.e("###age",age);
            String gender=uri.getQueryParameter("gender");
            Log.e("###gender",gender);
            values.put("name", name);
            values.put("age",age);
            values.put("gender",gender);
            itemId = sqLiteDatabase.insertOrThrow("demo_table", null, values);
        }

        Log.e("###", "調(diào)用了out中的insert方法");
        //表名钞馁,非空列虑省,值,對于sqlite數(shù)據(jù)庫,添加完成之后會返回一個Long的id
        //uri這個uri就是另外的程序調(diào)用contentprovider的時候傳過來的uri指攒,如果傳回去那么跟調(diào)用程序的uri沒有區(qū)別也沒有意義
        // 所以用ContentUris把uri和itemid整合一下慷妙,成為一個新的Uri,返回回去允悦。
        return ContentUris.withAppendedId(uri, itemId);
    }

運行結(jié)果:

2020-07-23 20:07:33.190 15996-16123/com.stone.mycontentprovider E/###: 調(diào)用了out中的insert方法
2020-07-23 20:07:33.246 15996-16123/com.stone.mycontentprovider E/###authory: com.stone.mycontentprovider.outcp
2020-07-23 20:07:33.246 15996-16123/com.stone.mycontentprovider E/###path: /anypath
2020-07-23 20:07:33.247 15996-16123/com.stone.mycontentprovider E/###query: name=咸桂&age=45&gender=男
2020-07-23 20:07:33.247 15996-16123/com.stone.mycontentprovider E/###name: 咸桂
2020-07-23 20:07:33.248 15996-16123/com.stone.mycontentprovider E/###age: 45
2020-07-23 20:07:33.248 15996-16123/com.stone.mycontentprovider E/###gender: 男
2020-07-23 20:07:33.256 15996-16123/com.stone.mycontentprovider E/###: 調(diào)用了out中的insert方法

兩種添加方法都執(zhí)行了膝擂,所以打印了兩邊“” 調(diào)用了out中的insert方法“”。

ok關(guān)于解析就簡單記錄這些東西隙弛。下面簡單說一下調(diào)用系統(tǒng)ContentProvider的問題:

(一)讀取短信息:基本分三個步驟:

(1)獲取ContentResolver

 ContentResolver contentResolver = getContentResolver();

(2)查詢短信息

 Uri smsUri = Uri.parse("content://sms/");
 Cursor smsCoursor = contentResolver.query(smsUri, null, null, null, null);

(3)遍歷smsCoursor 架馋,得到每一條的數(shù)據(jù)

//遍歷所有的行
   while (smsCoursor.moveToNext()) {
          //參數(shù)是列索引,遍歷所有的列
          for (int i = 0; i < smsCoursor.getColumnCount(); i++) {
             Log.e("###", smsCoursor.getString(i));//此時獲取到的是每一條的所有內(nèi)容
            String address=cursor.getString(cursor.getColumnIndex("address"));//地址
            String body=cursor.getString(cursor.getColumnIndex("body"));//短信內(nèi)容
            String dateString=cursor.getString(cursor.getColumnIndex("date"));//日期
          }
      }

(4)注意點:

"content://sms/":短信箱
"content://sms/inbox":收件箱
"content://sms/sent":發(fā)件箱
"content://sms/draft":草稿箱

(5)權(quán)限不要忘了動態(tài)申請全闷,manifest也要注冊叉寂。

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

(6)還有我的紅米手機獲取不到短信息,查了資料說是沒有權(quán)限总珠,現(xiàn)在還沒有解決屏鳍,希望各位看官能給個指導(dǎo)意見和方法。華為的可以局服。

(二)讀取聯(lián)系人:通訊錄中的姓名和其他內(nèi)容是由不同的contentprovider提供的钓瞭。也就是說姓名和其他內(nèi)容是不同的表,姓名是主表淫奔,其他內(nèi)容是從表山涡,主表中的主鍵會在從表中作為外鍵使用

(1)權(quán)限:動態(tài)申請

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

(2)讀取數(shù)據(jù)

 ContentResolver resolver;
 resolver = getContentResolver();
//先讀取聯(lián)系人信息
 Cursor cCursor = resolver.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
        while (cCursor.moveToNext()) {
//            ContactsContract.Contacts.DISPLAY_NAME//姓名
//            ContactsContract.Contacts._ID//id
//根據(jù)讀取到的聯(lián)系人信息遍歷Cursor獲取每一個聯(lián)系人的姓名和id
            String name = cCursor.getString(cCursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
            String mId = cCursor.getString(cCursor.getColumnIndex(ContactsContract.Contacts._ID));
            Log.e("###name", name + " ");
            Log.e("###mId", mId + " ");
//根據(jù)id獲取對應(yīng)的聯(lián)系人的其他信息
            String selections = ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=?";//查詢條件
            Cursor phoneCursor = resolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, selections, new String[]{mId}, null);
//變美麗其他信息
            while (phoneCursor.moveToNext()) {
//獲取電話號碼
                String phoneNum = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                name += "  " + phoneNum;
            }
//這個時候的log打印的就是姓名和聯(lián)系電話
            Log.e("###name", name + " ");

        }

(三)添加聯(lián)系人:上面我們知道了聯(lián)系人姓名和電話是在兩個表中,所以寫入聯(lián)系人也需要添加兩次:

(1)權(quán)限:WRITE_CONTACTS唆迁,動態(tài)的你懂的

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

(2)寫入聯(lián)系人

 //1.往一個contentprovider中插入一條空數(shù)據(jù)鸭丛,獲取新生成的id
        ContentValues values = new ContentValues();
        Uri uri = resolver.insert(ContactsContract.RawContacts.CONTENT_URI, values);
        long id = ContentUris.parseId(uri);//獲取到剛剛生成的id
   //2.利用剛剛獲取到的id分別組合姓名和電話號碼往另外一個contentprovider中插入數(shù)據(jù)
        //插入姓名
        values.put(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME,MyUtils.getChineseName());//插入的姓名
        values.put(ContactsContract.Data.RAW_CONTACT_ID,id);//指定和姓名關(guān)聯(lián)的id
        values.put(ContactsContract.Data.MIMETYPE,ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);//設(shè)置該行數(shù)據(jù)的類型
        resolver.insert(ContactsContract.Data.CONTENT_URI,values);//插入操作

        //插入電話
        values.clear();
        values.put(ContactsContract.Data.RAW_CONTACT_ID,id);//指定和電話關(guān)聯(lián)的id
        values.put(ContactsContract.CommonDataKinds.Phone.NUMBER,"13788883333");//插入的電話
        values.put(ContactsContract.CommonDataKinds.Phone.TYPE,ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE);//插入的電話的類型
        values.put(ContactsContract.Data.MIMETYPE,ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);//設(shè)置該行數(shù)據(jù)的類型
        resolver.insert(ContactsContract.Data.CONTENT_URI,values);//插入操作

ok,到此關(guān)于ContentProvider基礎(chǔ)操作已經(jīng)差不多了唐责,其中還有其他的遺漏或者不足的地方鳞溉,希望看官指正。后續(xù)還會不斷的改善妒蔚。祝大家工作愉快穿挨。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末月弛,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子科盛,更是在濱河造成了極大的恐慌帽衙,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件贞绵,死亡現(xiàn)場離奇詭異厉萝,居然都是意外死亡,警方通過查閱死者的電腦和手機榨崩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門谴垫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人母蛛,你說我怎么就攤上這事翩剪。” “怎么了彩郊?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵前弯,是天一觀的道長。 經(jīng)常有香客問我秫逝,道長恕出,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任违帆,我火速辦了婚禮浙巫,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘刷后。我一直安慰自己的畴,他們只是感情好,可當我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布尝胆。 她就那樣靜靜地躺著苗傅,像睡著了一般。 火紅的嫁衣襯著肌膚如雪班巩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天嘶炭,我揣著相機與錄音抱慌,去河邊找鬼。 笑死眨猎,一個胖子當著我的面吹牛抑进,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播睡陪,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼寺渗,長吁一口氣:“原來是場噩夢啊……” “哼匿情!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起信殊,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤炬称,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后涡拘,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體玲躯,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年鳄乏,在試婚紗的時候發(fā)現(xiàn)自己被綠了跷车。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡橱野,死狀恐怖朽缴,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情水援,我是刑警寧澤密强,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站裹唆,受9級特大地震影響誓斥,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜许帐,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一劳坑、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧成畦,春花似錦距芬、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至拄养,卻和暖如春离斩,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背瘪匿。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工跛梗, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人棋弥。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓核偿,卻偏偏與公主長得像,于是被迫代替她去往敵國和親顽染。 傳聞我的和親對象是個殘疾皇子漾岳,可洞房花燭夜當晚...
    茶點故事閱讀 44,927評論 2 355