3.菜单+对话框+数据存储+Content provide

一.菜单Menu

1.OptionsMenu  选项菜单  也叫系统菜单,右上角的三点

    (1)高版本的菜单

             Step1: 在menu文件夹中的XMl文件中写菜单布局

                        <item

                         android:id="@+id/action_color"

                         android:orderInCategory="100"控制再Menu中显示的顺序,数值越                                                                                       小,越靠前

                         android:showAsAction="never"控制该菜单项何时显示再ActionBar中

                                           属性:never 永远不现实再ActionBar中

                                                       always  一直显示再Action Bar中

                                                       ifRoom如果有空间,则显示再ActionBar中

                        android:title=“菜单项的文本”/>

                       //<item>元素中可嵌套<menu>元素形成二级菜单

           Step2:在Activity中调用onCreateOptionsMenu方法

                    public boolean onCreateOptionsMenu(Menu menu){

                              //加载菜单布局 

                              getMenuInflater().inflate(R.menu.main,menu);

                              return true;

                    }

            Step3:重写点击菜单回调的方法

                        public boolean onOptionsItemSelected(MenuItem item){

                              switch(item.getItemId()){

                                          .......

                              }

                        }

(2)低版本创建菜单,纯java代码

         在Activity中重写onCreateOptionsMenu方法

public boolean onCreateOptionsMenu(Menu menu){

          menu.add(menu.NONE,1,menu.NONE,"低版本的菜单一");

          SubMenu subMenu = menu.addSubMenu(menu.NONE,2,menu.NONE,"sub 2");

          subMenu.add(menu.NONE,21,1,"sub 2_1");

          subMenu.add(menu.NONE,22,0,"sub 2_2");

           return true;

}

2.ContextMenu  上下文菜单

                            可以为任意View指定上下文菜单,长按View显示上下文菜单,

                            通常用于ListView和GridView中

(1)在menu文件夹下的XML文件中写布局

(2)为View注册上下文菜单

        registerForContextMenu(textView);

(3)重写Activity中的onCreateContextMenu()方法

       /**

      *创建上下文菜单,长按View时调用该方法,每长按一次就会被调用一次

      *ContextMenu menu        需要显示的菜单

       *View view              被长按的view,且经过注册

      *ContextMenuInfo menuInfo所选择界面的额外信息(ListView,GridView,Spinner)

      *                        携带的AdapterView中的position信息

      */

     public void onCreateContextMenu(ContextMenu menu,View view,ContextMenuinfo             menuInfo){

          //加载菜单布局

          getMenuInflater().inflate(R.menu.xxx,menu);

          position = ((AdapterContextMenuInfo)menuInfo).position;

    }

(4)重写onContextItemSelected方法,点击上下文菜单项被回调的方法

public boolean onContextItemSelected(MenuItem item){

          switch(item.getItemId){

                                ........

          }

}

3.弹出式菜单 PopupMenu  API 11 以上,可以为任意一个View创建弹出式菜单

     (1)创建弹出式菜单

          /**

           *this  上下文

           *v    当前弹出式菜单参考显示位置的UI控件

           */

           PopupMenu popupMenu = new PopupMenu(this,v);

(2)加载菜单内容

          getMenuInflater().inflate(R.menu.xxx,popupMenu.getMenu());

(3)为弹出式菜单添加点击事件

      popupMenu.setOnMenuItemClickListener(new OnMenuItemClickListener(){

               public boolean onMenuItemClick(Menuitem item){

                     switch(item.getItemId){

                                   ...........

                     }

              }

       });

(4)显示弹出式菜单

        popuMenu.show();

二、对话框

常用对话框

                        普通对话框      AlertDialog

                        进度条对话框    ProgressDialog

                        日期选择对话框  DatePickerDialog

                        时间选择对话框  TimePickerDialog

                        自定义对话框    setView()

列表对话框(在AlertDialog的基础上设置某些属性而得)

                         普通列表对话框

                          builder.setItems(数组,new Dialoginterface.OnClickListener{})

                          单选列表对话框

                          builder.setSingleChoiceItems(数组,new                                                                                                                          Dialoginterface.OnclickListener{})

                          多选列表对话框

                          builder.setMultiChoiceItems(数组,new                                                                                                                                OnMultiChoiceClickListener{})

                          适配器列表对话框

                           builder.setAdapter(数组,new Dailoginterface.OnclickListener{})

对话框的通用属性

              setIcon(R.drawable.ic_launcher)  设置对话框的标题头像

              setTitle("")                    设置标题

              setMessage("")                  设置内容文字

              setCancelable(ture/false)        设置点击空表出对话框是否消失

三、Android的存储

一.共享参数存储 (SharedPreferences)

(1)SharedPreferences的介绍

SharedPreferences是Android系统提供的一个通用的数据持久化框架,用于存储和读取key-value类型的原始基本数据类型对,目前支持String、int、long、float、boolean等基本类型的存储,对于自定义的对象数据类型,无法使用SharedPreferences来存储。

SharedPreferences主要用于存储系统的配置信息。例如上次登录的用户名,上次最后设置的配置信息(如:是否打开音效、是否使用振动,小游戏的玩家积分等)。

当再次启动程序后依然保持原有设置。SharedPreferences用键值对方式存储,方便写入和读取。

SharedPreferences是Context上下文中的一个接口,Context提供了一个getSharedPreferences(name,mode)方法用于拿到SharedPreferences对象

SharedPreferences里又有一个Editor接口,SharedPreferences对象中提供了一个edit()方法用于拿到Editor对象

(2)SharedPreferences的特点

      存放轻量级数据

     本质存储形式是xml格式

     通常用于存储简单的数据信息,如记住账号,配置信息等

     应用程序卸载后,文件也会被删除

(3)SharedPreferences存储的数据类型

    可以存放boolean,int,string,long,float,

    但不能存放对象.

(4)getSharedpreferences(name,mode)方法的介绍

        该方法返回SharedPreferences对象,

         该方法有两个参数:

                            第一个:String name  文件名

                            第二个:int mode    一些权限  Context中提供了一些常量

                                                    Context.MODE_PRIVATE : 只有本应用可以访问

                                                    Context.MODE_WORLD_READABLE :其他应用可读

                                                   Context.MODE_WORLD_WRITEABLE : 其他应用可写

                                                   这些权限可以用+号来连接

(5)SharedPreferences常用方法        

      sharedPreferences.edit();获取Editor对象        

      sharedPreferences.getXXX(key,默认值);                

      如:sharedPreferences.getString(key,默认值);        

      sharedPreferences.getStringSet(key,默认set); 返回set       

       sharedpreferences.getAll()  返回Map<String,?>

       sharedPreferences.contains(key) 判断是否存在某键

       editor.putXXX(key,默认值)

       editor.putStringSet(key,默认Set)

       editor.remove(key);  移除某键值对

       editor.clear();  清楚所有数据.

       editor.commit();  提交,如果不提交则写不到文件中去

(6)SharedPreferences使用步骤

       ①通过context对象得到sharedpreferences对象

            Sharedpreferences sharedpreferences =                                                                                               context.getSharedPreferences("name",Context.MODE_PRIVATE);

       ②拿个Editor对象,并put数据

              Editor editor = sharedpreferences.editor();

              editor.putString(key,默认值);

                     ........

               editor.commit();数据成功存入

③通过sharedpreferences对象拿值

               sharedpreferences.getString(key,默认值);

                           ........

二.File存储

(1)内部存储  Internal Storage

          <1>特点: 文件只能被本应用访问,其他应用不能访问

                            当应用程勋卸载后,程序在内部存储的文件也会被删除

         <2>路径:

                           data/data/应用程序包名/files/***.**

          <3>核心方法:

               context提供了openInputStream(name); 根据指定文件名打开输入流

                      openOutputStream(name,mode); 根据文件名打开输入流,无则创建.

                                                                                 mode同SharedPreferences一样

                      String[] fileList()    获取所有文件名称

                       File    getFileDir()  获取文件的绝对路径

                       boolean  deleteFile(name)删除某个文件 

(2)外部存储  external storage(扩展卡 SD卡)

       <1>特点:SD卡公共目录  SD卡的私有目录

             公共目录下的文件可以被应用程序共享,私有目录中的文件只能当前应用程序使用.当程序卸载后,公共目录中的文件不被清理,私有目录中的文件会被清理

       <2>权限:

<!--写SD卡的权限-->

<user-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

<!--读SD卡的权限-->

<users-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

<3>SD卡的根目录

File file = Environment.getExternalStorageDirectory();

打印结果为:/mnt/sdcard

<4>SD卡公共目录

Environment.getExternalStoragePublicDirectory(String type)

                   参数type:

                         DIRECTORY_ALARMS //警报的铃声

                         DIRECTORY_DCIM //相机拍摄的图片和视频保存的位置

                         DIRECTORY_DOWNLOADS //下载文件保存的位置

                         DIRECTORY_MOVIES //电影保存的位置, 比如 通过google play下载                          的电影

                         DIRECTORY_MUSIC //音乐保存的位置

                         DIRECTORY_NOTIFICATIONS //通知音保存的位置

                         DIRECTORY_PICTURES //下载的图片保存的位置

                         DIRECTORY_PODCASTS //用于保存podcast(博客)的音频文件

                         DIRECTORY_RINGTONES //保存铃声的位置

        打印结果为:/mnt/sdcard/alarms

<5>SD卡的私有目录

    context.context.getExternalFilesDir(null)  SD卡的私有目录的根目录

    打印结果为:/mnt/sdcard/Android/data/包名/files

    context.getExternalFilesDir(String type)  SD卡的私有目录中的指定目录

    context.getExternalCacheDir()    SD卡的私有目录的缓存目录

     打印结果为:/mnt/sdcard/Android/data/包名/cache

<6>获取SD卡的状态

         Environment.getExternalStorageState()

<7>读写SD卡的步骤

①判断SD卡的状态

        Environment.getExternalStorageState()

②获取sdcard的路径

         Environment.getExternalStorageDirectory()

③添加读写SD卡的权限

④执行IO操作

<8>利用StatFs获取磁盘空间信息

          StatFs 一个模拟linux的df命令的一个类,获得SD卡和手机内存的使用情况

          StatFs的常用方法: 以block为单位.

                     getAvailableBlocks()    返回int,可用数据块个数

                     getFreeBlocks()          返回int,可用数据块个数,与上一个方法一样

                     getBlockCount()          返回int,总数据块数

                     getBlockSize()          返回int,大小,以字节为单位,每个数据块的大小

                     restate(String path)    执行一个由该对引用的文件系统

           SDK>=18时

                      statFs.getFreeBytes()    直接返回磁盘的剩余空间

            SDK<18时

                       statFs.getFreeBlocks()*statFs.getBlockSize() 计算剩余空间


三.SQLite数据库存储

    (1)特点

            轻量级  绿色  零配置  跨平台 嵌入式

            在程序的内部,可以在任何位置通过数据库的名称访问数据库,不可跨应用访问

            路径:data/data/应用程序包名/database/**.db

(2)SQLite知识,同java笔记

(3)Android操作SQlite数据库的核心类

      <1>SQLiteDatabase的使用

             SQLiteDatabase用于管理和操作数据库

             context对象中提供了一个返回SQLiteDatabase对象的方法

             context.openOrCreateDatabase(name,mode,CursorFactory);

                参数:

                        name  :  数据库名称

                        mode  :  模式: SQliteDatabase.OPEN_READWRITER  读写模式

                                                 SQLiteDatabase.OPEN_READONLY    只读模式

                                                 SQLiteDatabase.CREATE_IF_NECESSARY 如果数据                                                  库不存在,则创建

                         CursorFactory:  通常为空

SQLiteDatabase中执行SQL语句的方法: (常用)

               void execSQL(String sql)  执行SQL语句

              void execSQl(String sql,Object[] bindArgs) 执行SQL语句(可以有占位符)

              Cursor rawQuery(String sql,String[]  selectionArgs) 执行查询语句(可以有占位符)

SQLiteDatabase封装好的操作数据库的方法 (不常用)

               insert()  插入数据到指定的表中

                update()  更改表中指定的数据

               delete()  删除表中指定的数据

               query()   查询表中指定的内容

<2>SQLiteOperHelper  维护了一个数据库及维护了一个SQLiteDatabase对象

                                         用于数据的创建.更新.和打开数据库连接

   用法:

            ①定义一个类,继承SQLiteOpenHelper

                并重写父类的两个方法,这两个方式是系统调用的不用手动调用

                onCreate(SQLiterDatabase  db)  第一次创建数据库时调用, 只会被调用一次

                onUpgrade(SQLiterDatabase  db,int oldVersion, int newVersion)  数据库的版本号发生变化后,执行此方法(可能会被执行多次)

②必须提供一个构造方法

public MySQLiteOpenHelper(Context context) {

              super(context, name, CursorFactory, version);

}

参数:

          context:    上下文对象

          name:      数据库名字

          CursorFactory:通常为null,就是用系统的CursorFactory

          version:    版本号

SqLiteOpenHelper对象中的方法

               mySQLiteOpenHelper.getReadableDatabase();只读方式打开数据库连接

               mySQLiteOpenHelper.getWritableDatabase();以读写方式打开数据库连接

<3>Cursor

           作用类似于JDBC中resultSet, 把查询的结果封装到Cursor对象中.

            cursor就像是一个结果级上的游标, 可以向上或向下移动

             默认游标位置在数据的上方

cursor对象的常用方法:

coursor.getCount()  得到游标中的数据数量

          coursor.moveToNext() 游标移动到下一条数据, 并且判断下一条数据是否存在

           coursor.moveToPrevious() 游标移动到上一条数据, 并且判断上一条数据是否存在

          coursor.moveToFirst() 游标移动到第一条数据, 并且判断第一条数据是否存在

          coursor.moveToLast()  游标移动到最后一条数据, 并且判断最后一条数据是否存在

         coursor.moveToPosition(int position) 游标移动到某一条数据, 并且判断某一条数据是否存在

         coursor.move(int offset)  游标向上或者向下移动指定的行数, 正数代表向上,负数代表向下, 并且判断数据是否存在

         cursor.getColumnIndex(columnName)  根据列名拿个下标2016/7/6

         cursor.getColumnName(columnIndex)  根据下标拿个列名

         cursor.getColumnNames()  得到所有列名组成的数组

         cursor.getPosition()      得到行标

四.Content Provider  内容提供者(Android四大组件之一)

(1)Content Provider的介绍,作用以及特点

         为了达到不同应用程序之间的数据共享,Android提供了ContentProvider.

         例如我们需要操作系统里的媒体库、通讯录等,这时我们就可能通过                           ContentProvider来满足我们的需求了

<1>ContentProvider为存储和获取数据提供了统一的接口。ContentProvide对数据进行封装,不用关心数据存储的细节。使用表的形式来组织数据。

<2>使用ContentProvider可以在不同的应用程序之间共享数据。

<3>Android为常见的一些数据提供了默认的ContentProvider(包括音频、视频、图片和通讯录等)。

总的来说使用ContentProvider对外共享数据的好处是统一了数据的访问方式。

(2)ContentProvider类的介绍

             ContentProvider是一个抽象类,要想创建ContentProvider必须自定义一个类继承ContentProvider并实现其中的抽象方法:

          public boolean onCreate():该方法在ContentProvider创建后就会被调用,                                                                  Android开机后,ContentProvider在其它应用第一                                                            次访问它时才会被创建。

         public Cursor query(Uri uri, String[] projection, String selection, String[]                                                   selectionArgs, String sortOrder):该方法用于供外部应用从                                                                                                       ContentProvider中获取数据。

         public Uri insert(Uri uri, ContentValues values):该方法用于供外部应用往                                                                                                        ContentProvider添加数据。

        public int update(Uri uri, ContentValues values, String selection, String[]                                                                           selectionArgs):该方法用于供外部应用更新                                                                                                  ContentProvider中的数据。

       public int delete(Uri uri, String selection, String[] selectionArgs):该方法用于供                                                                                外部应用从ContentProvider删除数据。

      public String getType(Uri uri):该方法用于返回当前Url所代表数据的MIME类型。

                                                            如果操作的数据属于集合类型,那么MIME类型字                                                             符串应该以vnd.android.cursor.dir/开头,

                                                    如果要操作的数据属于非集合类型数据,那么                                                                 MIME类型字符串应该以vnd.android.cursor.item/开头,

创建自己的ContentProvider步骤:

①封装CONTENT_URI(必须是唯一的字符串,常用Contentprovider完全限定名)

    和数据库表的列名,必须为其定义一个叫_id的列,它用来表示每条记录的唯一性。

public class MyUsers {

          public static final String AUTHORITY  = “com.wissen.MyContentProvider”;

          // BaseColumn类中已经包含了 _id字段和_COUNT字段

          public static final class User implements BaseColumns {

                      public static final Uri CONTENT_URI  =                                                                                         Uri.parse(”content://com.wissen.MyContentProvider”);

                            // 表数据列

                         public static final String  USER_NAME  = “USER_NAME”;

         }

}

②定义自己的MyContentProvider类继承ContentProvider,实现其中的抽象方法

 ③实现SQLiteOpenHelper对数据库的操作,一共②使用. 

④在AndroidManifest.xml中配置ContentProvider

<provider android:name="MyContentProvider"

    android:authorities="包名.类名“/>

(3)ContentReslover类的介绍

     <1>ContentReslover的作用和特点

            当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver 类来完成,ContentReslover是一个抽象类,不能new出其实例,Context提供了getContentResLover()方法

<2>ContentReslover的常用方法

      ContentResolver 类提供了与ContentProvider类相同签名的四个方法:

      public Uri insert(Uri uri, ContentValues values):该方法用于往ContentProvider添加数据。

        public int delete(Uri uri, String selection, String[] selectionArgs):该方法用于从ContentProvider删除数据。

        public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs):该方法用于更新ContentProvider中的数据。

        public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder):该方法用于从ContentProvider中获取数据。

           参数:uri  同上解释

                     projection  要返回的列名组成的数组

                     selecttion  条件字符串,包含占位符

                     selectionArgs  上面占位符要显示的内容组成的数组

                     sortOrder    排列顺序

这些方法的第一个参数为Uri,代表要操作的ContentProvider和对其中的什么数据进行操作,其实和contentprovider里面的方法是一样的.他们所对应的数据,最终是会被传到我们在之前程序里面定义的那个contentprovider类的方法,假设给定的是:Uri.parse("content://com.bing.providers.personprovider/person/10"),那么将会对主机名为com.bing.providers.personprovider的ContentProvider进行操作,操作的数据为person表中id为10的记录。

<3>ContentReslover的使用步骤

①获取ContentReslover对象

        ContentResolver resolver =  getContentResolver();

②指定URI

        Uri uri = Uri.parse("content://com.bing.provider.personprovider/person");

③调用contentReslover的方法指定操作

     //添加一条记录

     ContentValues values = new ContentValues();

     values.put("name", "bingxin");

     values.put("age", 25);

     resolver.insert(uri, values);

     //获取person表中所有记录

    Cursor cursor = resolver.query(uri, null, null, null, "personid desc");

    while(cursor.moveToNext()){

    Log.i("ContentTest", "personid="+ cursor.getInt(0)+ ",name="+ cursor.getString(1));

}

    //把id为1的记录的name字段值更改新为zhangsan

   ContentValues updateValues = new ContentValues();

   updateValues.put("name", "zhangsan");

  Uri updateIdUri = ContentUris.withAppendedId(uri, 2);

  resolver.update(updateIdUri, updateValues, null, null);

  //删除id为2的记录

  Uri deleteIdUri = ContentUris.withAppendedId(uri, 2);

  resolver.delete(deleteIdUri, null, null);

<4>系统提供的ContentProvider已经封装好的URI

(4)URI的介绍

     URI叫做统一资源标识符,代表要操作的数据,这样你就可以找到对应的       ContentProvider以及想要的数据.(URI也可以说是一种类似SQL的查询语句)

URI的格式:

         content://com.example.transportationprovider/trains/122

         该URI可以根据反斜杠来划分为四部分

         content://  :  协议部分类似于http://,不可改变

         com.example.transportationprovider  :  该部分是URI的授权部分,是唯一标识,用来定位ContentProvider.一般定义为Contentprovider的完全限定名,注册时需要用到

         trains/122  :  内部路径部分, trains指向一个集合,一般用表名来表示,"122"为_id.单条数据的标识,如果没有"122"则返回一个数据集,有"122"则返回一条数据

(5)UriMatcher类的介绍

       因为Uri代表了要操作的数据,所以我们经常需要解析Uri,并从Uri中获取数据。Android系统提供了两个用于操作Uri的工具类,分别为UriMatcher和ContentUris 。掌握它们的使用,会便于我们的开发工作。

UriMatcher类用于匹配Uri,它的用法如下:

首先第一步把你需要匹配Uri路径全部给注册上,如下:

//常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码

UriMatcher  sMatcher = new UriMatcher(UriMatcher.NO_MATCH);

//如果match()方法匹配content://com.bing.procvide.personprovider/person路径,返回匹配码为1

sMatcher.addURI("com.bing.procvide.personprovider", "person", 1);//添加需要匹配uri,如果匹配就会返回匹配码

//如果match()方法匹配content://com.bing.provider.personprovider/person/230路径,返回匹配码为2

sMatcher.addURI("com.bing.provider.personprovider", "person/#", 2);//#号为通配符

switch(sMatcher.match(Uri.parse("content://com.ljq.provider.personprovider/person/10"))) {

          case 1

                    break;

         case 2

                    break;

         default://不匹配

                   break;

(6)ContentUris类的介绍

       ContentUris类用于操作Uri路径后面的ID部分,它有两个比较实用的方法:

                   withAppendedId(uri, id)用于为路径加上ID部分:

                   parseId(uri)方法用于从路径中获取ID部分:

(7)监听ContentProvider中数据的变化

如果ContentProvider的访问者需要知道ContentProvider中的数据发生变化,

则需要有两个步骤

①ContentProvider需要在数据发生变化时调用getContentResolver().notifyChange(uri, null)来通知注册在此URI上的访问者

例:

public class PersonContentProvider extends ContentProvider {

            public Uri insert(Uri uri, ContentValues values) {

                         db.insert("person", "personid", values);

                         getContext().getContentResolver().notifyChange(uri, null);

            }

}

②ContentProvider的访问者必须使用ContentObserver对数据(数据采用uri描述)进行监听,当监听到数据变化通知时,系统就会调用ContentObserver的onChange()方法:

contentProvider对象调用registerContentObserver(uri, notifyForDescendents, observer);注册监听

参数说明: URI  要监听数据的URI

                notifyForDescendents  true/false

                observer  ContentObserver实例,其中实现了onChange方法

例:

getContentResolver().registerContentObserver(Uri.parse("content://com.ljq.providers.personprovider/person"),

                true, new PersonObserver(new Handler()));

public class PersonObserver extends ContentObserver{

            public PersonObserver(Handler handler) {

                              super(handler);

           }

           public void onChange(boolean selfChange) {

                           //此处可以进行相应的业务处理

          }

}

(8)操作Android系统短息信息

(9)操作Android系统通话记录

(10)操作Android系统联系信息

(11)操作Android图片信息

(12)操作Android音频信息

(13)操作Android视频信息

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容