Android_7_數(shù)據(jù)存數(shù)方式

Android_7_數(shù)據(jù)存數(shù)方式

使用SharedPreferences存儲數(shù)據(jù)

  • 獲取SharedPreferences對象

    1. 調(diào)用Context對象的getSharedPreferences()方法

    2. 調(diào)用Activity對象的getPreferences()方

      調(diào)用Context對象的getSharedPreferences()方法獲得的SharedPreferences對象可以被同一應(yīng)用程序下的其他組件共享.
      調(diào)用Activity對象的getPreferences()方法獲得的SharedPreferences對象只能在該Activity中使用.       
      Context.MODE_PRIVATE:為默認操作模式,代表該文件是私有數(shù)據(jù),只能被應(yīng)用本身訪問,在該模式下,寫入的內(nèi)容會覆蓋原文件的內(nèi)容
      Context.MODE_APPEND:模式會檢查文件是否存在,存在就往文件追加內(nèi)容,否則就創(chuàng)建新文件.
      Context.MODE_WORLD_READABLE和Context.MODE_WORLD_WRITEABLE用來控制其他應(yīng)用是否有權(quán)限讀寫該文件.
      MODE_WORLD_READABLE:表示當前文件可以被其他應(yīng)用讀取.
      MODE_WORLD_WRITEABLE:表示當前文件可以被其他應(yīng)用寫入
      
  • SharedPreferences存儲數(shù)據(jù)

    SharedPreferences只支持基本數(shù)據(jù)類型

          public static boolean getBoolean(Context context, String key) {
          if (sp == null) {
          sp = context.getSharedPreferences(name, Context.MODE_PRIVATE);
          }
           return sp.getBoolean(key, false);
          }
    
    封裝過的使用SharedPreferences存儲一個bool值對象,同理可以使用putInt,putString等方法保存其他類型的數(shù)據(jù)

文件存儲數(shù)據(jù)

文件存儲就是通過流的方式,把數(shù)據(jù)寫到文件中,使用Context,Environment獲得路徑

Context常用方法目錄:

方法:getFilesDir 
釋義:返回通過Context.openFileOutput()創(chuàng)建和存儲的文件系統(tǒng)的絕對路徑围小,應(yīng)用程序文件偷拔,這些文件會在程序被卸載的時候全部刪掉愉舔。
 /data/data/package_name/files

方法:getDir
釋義:這是一個可以存放你自己應(yīng)用程序自定義的文件笨使,你可以通過該方法返回的File實例來創(chuàng)建或者訪問這個目錄樱溉,注意該目錄下的文件只有你自己的程序可以訪問眯亦。
getDir("test", Context.MODE_WORLD_WRITEABLE)
/data/data/package_name/app_test

方法:getCacheDir
釋義:返回應(yīng)用程序指定的緩存目錄腰素,這些文件在設(shè)備內(nèi)存不足時會優(yōu)先被刪除掉芦倒,所以存放在這里的文件是沒有任何保障的蛤织,可能會隨時丟掉赴叹。
/data/data/package_name/cache

方法:getExternalFilesDir
釋義:使用這個方法需要寫外部存儲的權(quán)限“”,這個目錄是與應(yīng)用程序相關(guān)的外部文件系統(tǒng)指蚜,這些文件只屬于你的應(yīng)用乞巧,不能被其它人訪問。同樣姚炕,這個目錄下的文件在程序被卸載時也會被一同刪除摊欠。該方法也可以指定返回某一資源類型,這些類型可以是:
 Environment#DIRECTORY_MUSIC 音樂
 Environment#DIRECTORY_PODCASTS 音頻
 Environment#DIRECTORY_RINGTONES 鈴聲
 Environment#DIRECTORY_ALARMS 鬧鈴
 Environment#DIRECTORY_NOTIFICATIONS 通知鈴聲
 Environment#DIRECTORY_PICTURES 圖片
 Environment#DIRECTORY_MOVIES 視頻
getExternalFilesDir( "/" )
/storage/sdcard0/Android/data/package_name/files
getExternalFilesDir( Environment.DIRECTORY_PICTURES )
/storage/sdcard0/Android/data/package_name/files/Pictures
方法:getExternalCacheDir
使用這個方法需要寫外部存儲的權(quán)限“”柱宦,調(diào)用該方法會返回應(yīng)用程序的外部文件系統(tǒng)(Environment.getExternalStorageDirectory())目錄的絕對路徑些椒,它是用來存放應(yīng)用的緩存文件,它和getCacheDir目錄一樣掸刊,目錄下的文件都會在程序被卸載的時候被清除掉免糕。  
/storage/sdcard0/Android/data/package_name/cache
方法:getDatabasePath
釋義:保存通過Context.openOrCreateDatabase 創(chuàng)建的數(shù)據(jù)庫文件
getDatabasePath("DATABASE_NAME") )
/data/data/package_name/databases/DATABASE_NAME

方法:getPackageCodePath
釋義:返回android 安裝包的完整路徑,這個包是一個zip的壓縮文件,它包括應(yīng)用程序的代碼和assets文件石窑。
/data/app/package_name-2.apk

方法:getPackageResourcePath
釋義:返回android 安裝包的完整路徑牌芋,這個包是一個ZIP的要鎖文件,它包括應(yīng)用程序的私有資源松逊。
/data/app/package_name-2.apk

方法:getObbDir
釋義:返回應(yīng)用程序的OBB文件目錄(如果有的話)躺屁,注意如果該應(yīng)用程序沒有任何OBB文件,這個目錄是不存在的经宏。
/storage/sdcard0/Android/obb/package_name

Environment
Environment類去獲取外部存儲目錄犀暑,在訪問外部存儲之前一定要先判斷外部存儲是否已經(jīng)是可使用(已掛載&可使用)狀態(tài)。并且需要在AndroidManifest.xml文件中添加外部存儲讀和寫的權(quán)限烁兰。
Environment類中提供了幾個靜態(tài)常量用于標識外部存儲的狀態(tài)耐亏,這些狀態(tài)都是String類型
MEDIA_BAD_REMOVAL 在沒有掛載前存儲媒體已經(jīng)被移除。
MEDIA_CHECKING 正在檢查存儲媒體沪斟。
MEDIA_MOUNTED 存儲媒體已經(jīng)掛載广辰,并且掛載點可讀/寫。
MEDIA_MOUNTED_READ_ONLY 存儲媒體已經(jīng)掛載主之,掛載點只讀择吊。
MEDIA_NOFS 存儲媒體是空白或是不支持的文件系統(tǒng)。
MEDIA_REMOVED 存儲媒體被移除杀餐。
MEDIA_SHARED 存儲媒體正在通過USB共享干发。
MEDIA_UNMOUNTABLE 存儲媒體無法掛載朱巨。
MEDIA_UNMOUNTED 存儲媒體沒有掛載史翘。
可以通過靜態(tài)方法getExternalStorageState()來獲取外部存儲的狀態(tài),如果程序需要在外部存儲里面讀寫數(shù)據(jù)冀续,必須要先判斷琼讽。

SQLite數(shù)據(jù)庫存儲數(shù)據(jù)

  • SQLite是一款開源的、嵌入式關(guān)系型數(shù)據(jù)庫,沒有獨立運行的進程洪唐,與所服務(wù)的應(yīng)用程序在應(yīng)用程序 進程空間內(nèi)共生共存钻蹬。它的代碼與應(yīng)用程序代碼也是在一起的,或者說嵌入其中凭需,作為托管它的程序 的一部分问欠。因此不存在數(shù)據(jù)庫的客戶端和服務(wù)器,使用SQLite一般只需要帶上它的一個動態(tài)庫粒蜈,就可 以享受它的全部功能顺献。

  • SQLite支持的數(shù)據(jù)類型

        SQLite采用動態(tài)數(shù)據(jù)存儲類型,會根據(jù)存入的值自動進行判斷枯怖。SQLite支持以下5種數(shù)據(jù)類型:
      
       ∽⒄(1)NULL:空值
      
        (2)INTEGER:帶符號的整型
      
        (3)REAL:浮點型
      
       ≈坠臁(4)TEXT:字符串文本
      
       ∈倜帷(5)BLOB:二進制對象
    
  • 創(chuàng)建SQLite數(shù)據(jù)庫

    創(chuàng)建類繼承自SQLiteOpenHelper,并復(fù)寫其onCreate(),onUpgrade(),onDeleteDB()方法,其中onCreate()方法會在創(chuàng)建數(shù)據(jù)庫后調(diào)用,在這里使用sql語句建表,在onUpgrade()方法中,是數(shù)據(jù)庫升級時對比版本對表或數(shù)據(jù)進行修改,onDeleteDb()是數(shù)據(jù)庫被刪除時回調(diào)的方法

          public class AndroidSQLiteOpenHelper extends SQLiteOpenHelper {  
        
          // 數(shù)據(jù)庫名稱  
          public static final String DBNAME = "android.db";  
          // 數(shù)據(jù)庫版本  
          public static final int VERSION = 2;  
          // 建表語句,大小寫不敏感  
          private static final String CREATETABLE = "create table "  
                  + Person.TABLENAME  
                  + "(id string, name string, gender int, age int)";  
        
          public AndroidSQLiteOpenHelper(Context context) {  
              super(context, DBNAME, null, VERSION);  
          }  
        
          // 創(chuàng)建表  
          @Override  
          public void onCreate(SQLiteDatabase db) {  
              db.execSQL(CREATETABLE);  
          }  
        
          // 更新表  
          @Override  
          public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {  
              this.deleteDB(db);  
              this.onCreate(db);  
          }  
        
          // 刪除表  
          private void deleteDB(SQLiteDatabase db) {  
              db.execSQL("drop table if exists " + Person.TABLENAME);  
          }  
      }  
    
  • 使用SQLite中的數(shù)據(jù)

    實例化上一步中定義的SQLiteOpenHelper子類對象,調(diào)用getWritableDatabase()方法可以獲得SQLiteDataBase對象,使用SQLiteDataBase對象就可以直接對數(shù)據(jù)庫進行操作了

      public DatabaseManager(Context context) {  
          dbHelper = new AndroidSQLiteOpenHelper(context);  
      }  
    
      // 插入記錄  
      public int insert(Person person) {  
          Log.e("SQLite", "----insert----");  
          SQLiteDatabase db = dbHelper.getWritableDatabase();  
          db.beginTransaction();  
          try {  
              db.execSQL("insert into " + Person.TABLENAME  
                       + " values(?, ?, ?, ?)", new Object[] { person.id,  
                      person.name, person.gender, person.age });  
              db.setTransactionSuccessful();  
          } catch (Exception e) {  
              return 0;  
          } finally {  
              db.endTransaction();  
          }  
          db.close();  
          return 1;  
      }  
    
      // 刪除記錄  
      public int delete(Person person) {  
          Log.e("SQLite", "----delete----");  
          SQLiteDatabase db = dbHelper.getWritableDatabase();  
          db.beginTransaction();  
          try {  
              db.execSQL("delete from " + Person.TABLENAME + " where id = ?",  
                      new Object[] { person.id });  
              db.setTransactionSuccessful();  
          } catch (Exception e) {  
              return 0;  
          } finally {  
              db.endTransaction();  
          }  
          db.close();  
          return 1;  
      }  
    
      // 更新記錄  
      public int update(Person person) {  
          Log.e("SQLite", "----update----");  
          SQLiteDatabase db = dbHelper.getWritableDatabase();  
          db.beginTransaction();  
          try {  
              db.execSQL("update " + Person.TABLENAME  
                          + " set name=?, gender=?, age=? where id=?", new Object[] {  
                      person.name, person.gender, person.age, person.id });  
              db.setTransactionSuccessful();  
          } catch (Exception e) {  
              return 0;  
          } finally {  
              db.endTransaction();  
          }  
          db.close();  
          return 1;  
      }  
    
      // 查詢記錄  
      public ArrayList<Person> query(String id) {  
          Log.e("SQLite", "----query----");  
          SQLiteDatabase db = dbHelper.getReadableDatabase();  
          Cursor cursor;  
          Person person;  
          ArrayList<Person> list = new ArrayList<Person>();  
          // 若fileId為null或""則查詢所有記錄  
          if (id == null || id.equals("")) {  
              cursor = db.rawQuery("select * from " + Person.TABLENAME, null);  
          } else {  
              cursor = db.rawQuery("select * from " + Person.TABLENAME  
                          + " where id=?", new String[] { id });  
          }  
          while (cursor.moveToNext()) {  
              person = new Person();  
              person.id = cursor.getString(cursor.getColumnIndex("id"));  
              person.name = cursor.getString(cursor.getColumnIndex("name"));  
              person.gender = cursor.getString(cursor.getColumnIndex("gender"));  
              person.age = cursor.getInt(cursor.getColumnIndex("age"));  
              Log.e("SQLite", person.toString());  
              list.add(person);  
          }  
          cursor.close();  
          db.close();  
          if (list.size() == 0) {  
              Log.e("SQLite", "****表中無數(shù)據(jù)****");  
          }  
          return list;  
          }
      }
    

網(wǎng)絡(luò)存儲數(shù)據(jù)

所謂網(wǎng)絡(luò)存儲就是把數(shù)據(jù)存儲到服務(wù)器上,這個過程需要使用網(wǎng)絡(luò)請求 

使用ContentProvider存儲數(shù)據(jù)

  • ContentProvider作為Android四大組件之一,一般自己很少定義ContentProvider,現(xiàn)多用在訪問系統(tǒng)提供的數(shù)據(jù)上,ContentProvider可以實現(xiàn)在應(yīng)用程序之間共享數(shù)據(jù).

      1椒袍、ContentProvider使用表的形式來組織數(shù)據(jù),無論數(shù)據(jù)的來源是什么驼唱,ContentProvider都會認為是一種表,然后把數(shù)據(jù)組織成表格
      2驹暑、ContentProvider提供的方法
      query:查詢
      insert:插入
      update:更新
      delete:刪除
      getType:得到數(shù)據(jù)類型
      onCreate:創(chuàng)建數(shù)據(jù)時調(diào)用的回調(diào)函數(shù)
    
  • 使用步驟

    1曙蒸、 定義一個CONTENT_URI常量(里面的字符串必須是唯一)

        Public static final Uri CONTENT_URI = Uri.parse("content://com.MyContentprovider");
        如果有子表,URI為:
        Public static final Uri CONTENT_URI = Uri.parse("content://com.MyContentProvider/users");
    

    2岗钩、 定義一個類纽窟,繼承ContentProvider

        Public class MyContentProvider extends ContentProvider
    

    3、實現(xiàn)ContentProvider的所有方法(query兼吓、insert臂港、update、delete视搏、getType审孽、onCreate)

        public class MyContentProvider extends ContentProvider {
         //訪問表的所有列
         public static final int INCOMING_USER_COLLECTION = 1;
         //訪問單獨的列
         public static final int INCOMING_USER_SINGLE = 2;
         //操作URI的類
         public static final UriMatcher uriMatcher;
         //為UriMatcher添加自定義的URI
         static{
         uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
         uriMatcher.addURI(MyContentProviderMetaData.AUTHORITIES,"/user",
         INCOMING_USER_COLLECTION);
         uriMatcher.addURI(MyContentProviderMetaData.AUTHORITIES,"/user/#",
         INCOMING_USER_SINGLE);
        
         }
         private DatabaseHelp dh;
         //為數(shù)據(jù)庫表字段起別名
         public static HashMap userProjectionMap;
         static
         {
         userProjectionMap = new HashMap();
         userProjectionMap.put(UserTableMetaData._ID,UserTableMetaData._ID);
         userProjectionMap.put(UserTableMetaData.USER_NAME, UserTableMetaData.USER_NAME);
         }
         /**
         * 刪除表數(shù)據(jù)
         */
         @Override
         public int delete(Uri uri, String selection, String[] selectionArgs) {
         System.out.println("delete");
         //得到一個可寫的數(shù)據(jù)庫
         SQLiteDatabase db = dh.getWritableDatabase();
         //執(zhí)行刪除,得到刪除的行數(shù)
         int count = db.delete(UserTableMetaData.TABLE_NAME, selection, selectionArgs);
         return count;
         }
         /**
         * 數(shù)據(jù)庫訪問類型
         */
         @Override
         public String getType(Uri uri) {
         System.out.println("getType");
         //根據(jù)用戶請求浑娜,得到數(shù)據(jù)類型
         switch (uriMatcher.match(uri)) {
         case INCOMING_USER_COLLECTION:
         return MyContentProviderMetaData.UserTableMetaData.CONTENT_TYPE;
         case INCOMING_USER_SINGLE:
         return MyContentProviderMetaData.UserTableMetaData.CONTENT_TYPE_ITEM;
         default:
         throw new IllegalArgumentException("UnKnown URI"+uri);
         }
         }
         /**
         * 插入數(shù)據(jù)
         */
         @Override
         public Uri insert(Uri uri, ContentValues values) {
         //得到一個可寫的數(shù)據(jù)庫
         SQLiteDatabase db = dh.getWritableDatabase();
         //向指定的表插入數(shù)據(jù)佑力,得到返回的Id
         long rowId = db.insert(UserTableMetaData.TABLE_NAME, null, values);
         if(rowId > 0){//判斷插入是否執(zhí)行成功
         //如果添加成功,利用新添加的Id和
         Uri insertedUserUri = ContentUris.withAppendedId(UserTableMetaData.CONTENT_URI, rowId);
         //通知監(jiān)聽器筋遭,數(shù)據(jù)已經(jīng)改變
         getContext().getContentResolver().notifyChange(insertedUserUri, null);
         return insertedUserUri;
         }
         return uri;
         }
         /**
         * 創(chuàng)建ContentProvider時調(diào)用的回調(diào)函數(shù)
         */
         @Override
         public boolean onCreate() {
         System.out.println("onCreate");
         //得到數(shù)據(jù)庫幫助類
         dh = new DatabaseHelp(getContext(),MyContentProviderMetaData.DATABASE_NAME);
         return false;
         }
         /**
         * 查詢數(shù)據(jù)庫
         */
         @Override
         public Cursor query(Uri uri, String[] projection, String selection,
         String[] selectionArgs, String sortOrder) {
         //創(chuàng)建一個執(zhí)行查詢的Sqlite
         SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
         //判斷用戶請求打颤,查詢所有還是單個
         switch(uriMatcher.match(uri)){
         case INCOMING_USER_COLLECTION:
         //設(shè)置要查詢的表名
         qb.setTables(UserTableMetaData.TABLE_NAME);
         //設(shè)置表字段的別名
         qb.setProjectionMap(userProjectionMap);
         break;
         case INCOMING_USER_SINGLE:
         qb.setTables(UserTableMetaData.TABLE_NAME);
         qb.setProjectionMap(userProjectionMap);
         //追加條件,getPathSegments()得到用戶請求的Uri地址截取的數(shù)組,get(1)得到去掉地址中/以后的第二個元素
         qb.appendWhere(UserTableMetaData._ID + "=" + uri.getPathSegments().get(1));
         break;
         }
         //設(shè)置排序
         String orderBy;
         if(TextUtils.isEmpty(sortOrder)){
         orderBy = UserTableMetaData.DEFAULT_SORT_ORDER;
         }
         else{
         orderBy = sortOrder;
         }
         //得到一個可讀的數(shù)據(jù)庫
         SQLiteDatabase db = dh.getReadableDatabase();
         //執(zhí)行查詢漓滔,把輸入傳入
         Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy);
         //設(shè)置監(jiān)聽
         c.setNotificationUri(getContext().getContentResolver(), uri);
         return c;
        
         }
         /**
         * 更新數(shù)據(jù)庫
         */
         @Override
         public int update(Uri uri, ContentValues values, String selection,
         String[] selectionArgs) {
         System.out.println("update");
         //得到一個可寫的數(shù)據(jù)庫
         SQLiteDatabase db = dh.getWritableDatabase();
         //執(zhí)行更新語句编饺,得到更新的條數(shù)
         int count = db.update(UserTableMetaData.TABLE_NAME, values, selection, selectionArgs);
         return count;
         }
        
        }
    

    4、在AndroidMinifest.xml中進行聲明

    <provider   
          android:name=".cp.MyContentProvider"  
          android:authorities="com.cp.MyContentProvider"  
          android:exported="true" >  
    </provider>  
  • 這樣一個ContentProvider就定義完成了,可以在另一個程序使用ContentResolver進行在應(yīng)該間互相使用數(shù)據(jù)了
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末响驴,一起剝皮案震驚了整個濱河市透且,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌豁鲤,老刑警劉巖秽誊,帶你破解...
    沈念sama閱讀 219,110評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異琳骡,居然都是意外死亡锅论,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評論 3 395
  • 文/潘曉璐 我一進店門日熬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來棍厌,“玉大人肾胯,你說我怎么就攤上這事≡派矗” “怎么了敬肚?”我有些...
    開封第一講書人閱讀 165,474評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長束析。 經(jīng)常有香客問我艳馒,道長,這世上最難降的妖魔是什么员寇? 我笑而不...
    開封第一講書人閱讀 58,881評論 1 295
  • 正文 為了忘掉前任弄慰,我火速辦了婚禮,結(jié)果婚禮上蝶锋,老公的妹妹穿的比我還像新娘陆爽。我一直安慰自己,他們只是感情好扳缕,可當我...
    茶點故事閱讀 67,902評論 6 392
  • 文/花漫 我一把揭開白布慌闭。 她就那樣靜靜地躺著,像睡著了一般躯舔。 火紅的嫁衣襯著肌膚如雪驴剔。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,698評論 1 305
  • 那天粥庄,我揣著相機與錄音丧失,去河邊找鬼。 笑死惜互,一個胖子當著我的面吹牛布讹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播载佳,決...
    沈念sama閱讀 40,418評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼炒事,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蔫慧?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,332評論 0 276
  • 序言:老撾萬榮一對情侶失蹤权薯,失蹤者是張志新(化名)和其女友劉穎姑躲,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體盟蚣,經(jīng)...
    沈念sama閱讀 45,796評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡黍析,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,968評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了屎开。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片阐枣。...
    茶點故事閱讀 40,110評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蔼两,到底是詐尸還是另有隱情甩鳄,我是刑警寧澤,帶...
    沈念sama閱讀 35,792評論 5 346
  • 正文 年R本政府宣布额划,位于F島的核電站妙啃,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏俊戳。R本人自食惡果不足惜揖赴,卻給世界環(huán)境...
    茶點故事閱讀 41,455評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望抑胎。 院中可真熱鬧燥滑,春花似錦、人聲如沸阿逃。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽盆昙。三九已至羽历,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間淡喜,已是汗流浹背秕磷。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留炼团,地道東北人澎嚣。 一個月前我還...
    沈念sama閱讀 48,348評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像瘟芝,于是被迫代替她去往敵國和親易桃。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,047評論 2 355

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