Android主要提供了3种方式用于实现数据持久化功能,分别是文件存储、SP存储和数据库存储。除了这3种方式,你还可以将数据保存在手机的SD中,不过使用文件、SP或者数据库来保存数据相对简单,更加安全。
文件存储不对存储的内容进行任何的格式化处理,所有的数据原封不动保存在文件当中,因而适合存储简单的文本数据或二进制数据。
如果你想使用文件存储的方式保存一些复杂的文本数据,就需要定义一套自己的格式规范,以便将数据从文件中重新解析出来。
public void save(String inputText) {
FileOutputStream out = null;
BufferedWriter writer = null;
try {
out = openFileOutput("data", Context.MODE_PRIVATE);
writer = new BufferedWriter(new OutputStreamWriter(out));
writer.write(inputText);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (writer != null) {
writer.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.fkq.filepersistencetest.MainActivity">
<EditText
android:id="@+id/edit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:hint="Type someing here" />
</RelativeLayout>
public class MainActivity extends AppCompatActivity {
private EditText editText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = (EditText) findViewById(R.id.edit);
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.e("MainActivity","进来了吗");
String inputText = editText.getText().toString();
save(inputText);
}
public void save(String inputText) {
FileOutputStream out = null;
BufferedWriter writer = null;
try {
out = openFileOutput("data", Context.MODE_PRIVATE);
writer = new BufferedWriter(new OutputStreamWriter(out));
writer.write(inputText);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (writer != null) {
writer.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
说明:页面展示EditText,输入内容后,点击Back键,执行onDestroy方法,方法中获取EditText中的内容,并调用save方法将文本内容保存到文件中。
private String load() {
FileInputStream in = null;
BufferedReader reader = null;
StringBuilder content = new StringBuilder();
try {
in = openFileInput("data");
reader = new BufferedReader(new InputStreamReader(in));
String line = " ";
while ((line = reader.readLine()) != null) {
content.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return content.toString();
}
说明:
1. 首先通过openFileInput方法获取到一个FileInputStream对象。
2. 然后借助FileInputStream对象构建出一个InputStreamReader对象。
3. 接着借助InputStreamReader构建出一个BufferedReader对象。
4. 然后通过BufferedReader进行一行行读取,把文件中所有的文本内容读取并存放在一个StringBuilder对象中。
5. 最后将读取到的内容返回就可以了。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = (EditText) findViewById(R.id.edit);
String inputText = load();
if (!TextUtils.isEmpty(inputText)) {
editText.setText(inputText);
editText.setSelection(inputText.length());
Toast.makeText(this, "还原文本成功", Toast.LENGTH_SHORT).show();
}
}
private String load() {
FileInputStream in = null;
BufferedReader reader = null;
StringBuilder content = new StringBuilder();
try {
in = openFileInput("data");
reader = new BufferedReader(new InputStreamReader(in));
String line = " ";
while ((line = reader.readLine()) != null) {
content.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return content.toString();
}
说明:
1. onCrate方法中调用load方法读取文件中的存储的文本内容。
2. 读取的内容不为null,就将内容填充到EditText里,并调用setSection方法将输入光标移动到文本的末尾位置以便于继续输入,然后弹出一句还原成功的提示。
利用Context类中提供的openFieInput和openFileOutput方法,之后就是利用Java的各种流来进行读写操作。
SP是使用键值对的方式存储数据的,且支持多种不同的数据类型存储。
Context类中的getSharedPreferences方法:
Activity类中的getPreferences方法:
此方法只接收一个操作模式参数,因为使用这个方法会自动将当前活动的类名作为SP的文件名。
PreferenceManager类中的getDefaultSharedPreferences方法
此方法是一个静态方法,它接收一个Context参数,并自动使用当前应用程序的包名作为前缀来命名SP文件。
SharedPreferences.Editor editor = getSharedPreferences("data", MODE_PRIVATE).edit();
editor.putString("name", "Tom");
editor.putInt("age", 28);
editor.putBoolean("married", false);
editor.apply();
SP对象中提供了一系列的get方法,用于对存储的数据进行读取,每种get方法都对应了SharedPreferences.Editor中的一种put方法,比如读取取布尔型数据就用getBoolean方法,读取字符串数据就用getString方法。
这些get方法接收两个参数,第一个参数是键,传入存储数据时使用的键就可以得到响相应的值了;第二个参数是默认值,即表示当传入的键找不到对应的值时会以什么样的默认值进行返回。
SharedPreferences preferences = getSharedPreferences("data",MODE_PRIVATE);
String name = preferences.getString("name","");
int age = preferences.getInt("age",0);
boolean married = preferences.getBoolean("married",false);
创建项目,创建LoginActivity,编辑登录activity_login布局,并修改配置文件如下:
activity_login:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="帐号:"
android:textSize="20dp" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:hint="请输入帐号" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:background="#20000000"></View>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="密码:"
android:textSize="20dp" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:hint="请输入密码" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:background="#20000000"></View>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="30dp"
android:padding="10dp">
<CheckBox
android:id="@+id/cb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="记住密码"
android:textSize="20dp" />
</LinearLayout>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="10dp"
android:text="登录" />
</LinearLayout>
配置文件:
<activity android:name=".MainActivity"></activity>
<activity android:name=".LoginActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
LoginActivity:
public class LoginActivity extends AppCompatActivity implements View.OnClickListener {
@Bind(R.id.et_username)
EditText etUsername;
@Bind(R.id.et_password)
EditText etPassword;
@Bind(R.id.cb_checkbox)
CheckBox cbCheckbox;
@Bind(R.id.bt_login)
Button btLogin;
private SharedPreferences pref;
private SharedPreferences.Editor editor;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
ButterKnife.bind(this);
checkIsRemember();
btLogin.setOnClickListener(this);
}
private void checkIsRemember() {
pref = PreferenceManager.getDefaultSharedPreferences(this);
boolean isRemember = pref.getBoolean("remember_password", false);
if (isRemember) {
//将帐号和密码都设置到文本框中
String account = pref.getString("account", "");
String password = pref.getString("password", "");
etUsername.setText(account);
etPassword.setText(password);
cbCheckbox.setChecked(true);
}
}
@Override
public void onClick(View v) {
String account = etUsername.getText().toString();
String password = etPassword.getText().toString();
//如果帐号是admin,密码是123456,就认为是登录成功
if (account.equals("admin") && password.equals("123456")) {
editor = pref.edit();
if (cbCheckbox.isChecked()) {//检查复选框是否被选中
editor.putBoolean("remember_password", true);
editor.putString("account", account);
editor.putString("password", password);
} else {
editor.clear();
}
editor.apply();
startActivity(new Intent(LoginActivity.this, MainActivity.class));
finish();
} else {
Toast.makeText(this, "帐号或密码错误", Toast.LENGTH_SHORT).show();
}
}
}
说明:
1. 首先在onCreate方法中获取SharedPreferences对象,然后调用它的getBoolean方法获取remember_password这个键对应的值。一开始当然不存在对应的值,所以会使用默认值false,这样什么都不会发生。
2. 接着在登录成功之后,会调用CheckBox的isChecked方法来检查复选框是否被选中,如果被选中,则表示用户想要记住密码,这时将remember_password设置为true,然后把account和password对应的值都存入到SP文件当中并提交。如果没有被选中,就简单地调用一下clear方法,将SP文件中的数据全部清除掉。
3. 当用户选中了记住密码复选框,并成功登录一次后,remember_password键对应的值就是true了,这个时候如果再重新启动登录页面,就会从SP文件中将保存的帐号和密码都读取出来,并填充到文本输入框中,然后把记住密码复选框选中,这样就完成了记住密码的功能了。
4.当然实际的项目中还需要对密码进行加密处理,否则不安全。
SQLite数据库不仅支持标准的SQL语法,还遵循了数据库的ACID事务。
相对文件存储和SP存储,SQLite数据库适合存储大量复杂的关系型数据,比如手机的短信等等。
Android 提供了SQLiteOpenHelper帮助类,借助这个类可以非常简单地对数据库进行创建和升级。
SQLiteOpenHelper是一个抽象类,想使用它,就需要创建一个自己的帮助类去继承它。SQLiteOpenHelper中有两个抽象方法,分别是onCreate和onUpgrade,利用这个两个方法实现创建、升级数据库的逻辑。
SQLiteOpenHelper还有两个非常重要的实例方法:getReadableDatabase和getWriteableDatabase。这两个方法都可以创建或打开一个现有的数据库(如果存在则打开,如果不存在则创建一个新的数据库),并返回一个可对数据库进行读写操作的对象。不同的是,当数据库不可写入的时候(如磁盘空间已满),getReadableDatabase方法返回的对象将以只读的方式去打开数据库,而getWritableDatabase方法则将出现异常。
/**
* Created by FuKaiqiang on 2017/5/9.
*/
public class MyDatabaseOpenHelper extends SQLiteOpenHelper {
public static final String CREATE_BOOK = "create table Book("
+ "id integer primary key autoincrement,"
+ "author text,"
+ "price real,"
+ "pages integer,"
+ "name text)";
private Context mContext;
public MyDatabaseOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
mContext = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK);
Toast.makeText(mContext, "数据库和表BOOK创建成功", Toast.LENGTH_SHORT).show();
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
说明:
1. SQLite数据类型很简单,integer表示整型,real表示浮点型,text表示文本类型,blob表示二进制类型,此外上述建表语句还使用了primary key将id列设为主键,并用autoincrement关键字表示id列是自增长的。
2. 我们把建表语句定义成了一个字符串常量,然后在onCreate方法中又调用了SQLiteDatabase的exexSQL方法去执行这条建表语句,并弹出Toast,保证在数据库创建完成的同时还能成功创建Book表。
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private MyDatabaseOpenHelper databaseOpenHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
databaseOpenHelper = new MyDatabaseOpenHelper(this, "BookStore.db", null, 1);
Button button = (Button) findViewById(R.id.bt_createdb);
button.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt_createdb:
databaseOpenHelper.getWritableDatabase();
break;
}
}
}
说明:
细心的你一定发现,MyDatabaseHelper中还有一个空方法onUpgrade,其实它就是用来进行数据库升级用的。
目前DatabaseTest项目中已经有一张Book表用于存放书的各种详细数据,现在需要再添加一张Category表用于记录图书的分类,这个时候就需要升级数据库。
比如Category表中有id(主键)、分类名和分类代码这个几个列,建表语句就可以写成:
create table Category(
id integer primary key autoincrement,
category_name text,
category_code integer)
public class MyDatabaseOpenHelper extends SQLiteOpenHelper {
public static final String CREATE_BOOK = "create table Book("
+ "id integer primary key autoincrement,"
+ "author text,"
+ "price real,"
+ "pages integer,"
+ "name text)";
public static final String CREATE_CATEGORY = "create table Category("
+ "id integer primary key autoincrement,"
+ "category_name text,"
+ "category_code integer)";
private Context mContext;
public MyDatabaseOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
mContext = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK);
db.execSQL(CREATE_CATEGORY);
Toast.makeText(mContext, "数据库和表BOOK创建成功", Toast.LENGTH_SHORT).show();
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("drop table if exists Book");
db.execSQL("drop table if exists Category");
onCreate(db);
}
}
说明:
MyDatabaseOpenHelper:
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("drop table if exists Book");
db.execSQL("drop table if exists Category");
onCreate(db);
}
MainActivity:
databaseOpenHelper = new MyDatabaseOpenHelper(this, "BookStore.db", null, 2);
说明:
对数据的操作无非4中:CRUD。C:Create增加、R: Retrieve查询、U:Update更新、D:Delete删除。
每一种操作对应一种SQL命令:添加数据用insert、查询数据用select、更新数据使用update、删除数据用delete。
Android提供了辅助方法,不用SQL语句,也能完成CRUD操作。
SQLiteOpenHelper的getWritableDatabase和getReadableDatabase返回一个SQLiteDatabase对象,借助这个对象可以进行CRUD操作。
databaseOpenHelper = new MyDatabaseOpenHelper(this, "BookStore.db", null, 2);
SQLiteDatabase db = databaseOpenHelper.getWritableDatabase();
ContentValues values = new ContentValues();
//开始组装第一条数据
values.put("name","I am fkq");
values.put("author","fkq");
values.put("pages",454);
values.put("price",16.96);
db.insert("Book",null,values); //插入第一条数据
values.clear();
//开始组装第二条数据
values.put("name","I am Tom");
values.put("author","fkq");
values.put("pages",500);
values.put("price",19);
db.insert("Book",null,values);
说明:
SQLiteDatabase db_update = databaseOpenHelper.getWritableDatabase();
ContentValues values_update = new ContentValues();
values_update.put("price", 100);
db_update.update("Book", values_update, "name=?", new String[]{"I am fkq"});
说明:
SQLiteDatabase db_delete = databaseOpenHelper.getWritableDatabase();
db_delete.delete("Book", "price>?", new String[]{"99"});
SQL的全程是Structured Query Language 结构化查询语言,重心是查询!
SQLiteDatabase中提供了query方法对数据库进行查询。
query方法接收7个参数:
第一个参数表名;
第二个参数用于指定查询哪几列,如果不指定默认查询所有列;
第三、第四个参数用于约束查询某一行或某几行的数据,如果不指定则默认查询所有航的数据。
第五个参数用于指定需要去group by的列,不指定则表示不对查询结构进行group by操作。
第六个参数用于对group by 之后的数据进行进一步的过滤,不指定则表示不进行过滤。
第七个参数用于指定查询结果的排序方式,不指定则表示使用默认的排序方式。
SQLiteDatabase db_query = databaseOpenHelper.getWritableDatabase();
Cursor cursor = db_query.query("Book", null, null, null, null, null, null);
if (cursor.moveToFirst()) {
do {
//遍历Cursor对象,取出数据并打印
String name = cursor.getString(cursor.getColumnIndex("name"));
String author = cursor.getString(cursor.getColumnIndex("author"));
int pages = cursor.getInt(cursor.getColumnIndex("pages"));
double price = cursor.getDouble(cursor.getColumnIndex("price"));
Log.d("MainActivity", "book name is" + name);
Log.d("MainActivity", "book author is" + author);
Log.d("MainActivity", "book pages is" + pages);
Log.d("MainActivity", "book price is" + price);
} while (cursor.moveToNext());
}
cursor.close();
说明:查询“Book”表中的数据,返回一个游标Cursor;让游标移动到第一行,根据各列的名字取出对应的值,并打印出来。
db.execSQL("insert into Book(name,author,pages,price) values(?,?,?,?)",
new String[]{"I am baby", "I am body", "456", "16.90"});
db_update.update("Book", values_update, "name=?", new String[]{"I am fkq"});
db_delete.execSQL("delete from Book where pages>?", new String[]{"500"});
db_query.rawQuery("select * from Book", null);
LitePal是一款开源的Android数据库框架,它采用了对象关系映射(ORM)的模式,并将我们平时开发最常用到的一些数据库功能进行了封装,不用编写一行SQL语句就可以完成各种建表和增删改查的操作。
LitePal采取的是对象关系映射(ORM)的模式,那什么是对象关系映射呢?简单点说:我们的编程语言是面向对象语言,而使用的数据库是关系型数据库,那么将面向对象的语言和面向对象的数据库之间建立一种映射关系,这就是对象关系映射。
compile 'org.litepal.android:core:1.3.2'
<?xml version="1.0" encoding="utf-8"?>
<litepal>
<dbname value="BookStore"></dbname>
<version value="1"></version>
<list>
</list>
</litepal>
android:name="org.litepal.LitePalApplication"
说明:只有配置了application才能让LitePal所有功能正常工作。
public class Book {
private int id;
private String author;
private double price;
private int pages;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public int getPages() {
return pages;
}
public void setPages(int pages) {
this.pages = pages;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
说明:一个典型的javabean类,类名代表的是表名,字段对应表中的每一个列,这就是对象关系映射最直观的体验。
<list>
<mapping class="com.fkq.litepaltest.Book"></mapping>
</list>
说明:使用mapping配置映射模型类,注意一定要使用完整的类名。不管有多少模型类需要映射,都使用相同方式配置在list标签下。
Connector.getDatabase();
说明:创建数据库最简单的操作。
LitePal升级数据库不会像SQLiteOpenHelper升级数据库需要先把之前的drop掉,然后再重新创建。
LitePal升级数据库非常简单,只需要改你想改的任何内容,然后将版本号加1就行了。
向Book表添加一个press(出版社)列;向数据库添加一张Category表:
Book表添加:
private String press;
public String getPress() {
return press;
}
public void setPress(String press) {
this.press = press;
}
创建Category表
public class Category {
private int id;
private String categoryName;
private int categoryCode;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCategoryName() {
return categoryName;
}
public void setCategoryName(String categoryName) {
this.categoryName = categoryName;
}
public int getCategoryCode() {
return categoryCode;
}
public void setCategoryCode(int categoryCode) {
this.categoryCode = categoryCode;
}
}
版本号加1,添加新的模型类:
<?xml version="1.0" encoding="utf-8"?>
<litepal>
<dbname value="BookStore"></dbname>
<version value="2"></version>
<list>
<mapping class="com.fkq.litepaltest.Book"></mapping>
<mapping class="com.fkq.litepaltest.Category"></mapping>
</list>
</litepal>
Book类:
public class Book extends DataSupport {}
MainActivity:
Book b = new Book();
b.setName("Tom is a book!");
b.setAuthor("fkq");
b.setPages(500);
b.setPrice(10);
b.setPress("unknown");
b.save();
对于LitePal来说,对象是否已存储就是根据调用model.isSaved方法的结果来判断的,返回true就表示已存储,返回false就表示未存储。
只有两种情况下返回true:一种情况是已经调用过model.save方法添加数据,一种情况是model对象是通过LitePal提供的查询API查出来的,由于是从数据库查出来的,所以会被认为是已存储的对象。
更新数据的第一种方式:
Book b = new Book();
b.setName("Tom is a book!");
b.setAuthor("fkq");
b.setPages(500);
b.setPrice(10);
b.setPress("unknown");
b.save();
b.setPrice(20);
b.save();
说明:只能针对save过的对象进行操作,性太大。
Book b_update = new Book();
b_update.setPrice(14.95);
b_update.setPress("Green");
b_update.updateAll("name = ? and athor = ?","Tom is a book!","fkq");
说明:set指定的是要更新的内容;updateAll是更新的条件,不指定就代表对说有的数据生效。需要注意的是当我们想更新数据为默认值的时候,要用下面方法设置:
Book b_update = new Book();
b_update.setToDefault("pages");
b_update.updateAll();
已经存储的对象调用delete方法即可,下面介绍另一种:
DataSupport.deleteAll(Book.class, "price<?", "50");
4.6.1.查询表中所有数据:
List<Book> books = DataSupport.findAll(Book.class);
for (Book book : books) {
Log.e("MainActivity", "book name is" + book.getName());
Log.e("MainActivity", "book author is" + book.getAuthor());
Log.e("MainActivity", "book pages is" + book.getPages());
Log.e("MainActivity", "book price is" + book.getPrice());
Log.e("MainActivity", "book press is" + book.getPress());
}
4.6.2.查询表中第一条数据:
Book firstbook = DataSupport.findFirst(Book.class);
4.6.3.查询表中最后一条数据:
Book lastbook = DataSupport.findLast(Book.class);
4.6.4.select方法用于指定查询哪几列的数据,对应了SQL当中的select关键字。比如只查name和author这两列的数据:
List<Book> books = DataSupport.select("name","author").find(Book.class);
4.6.5.where方法用于指定查询的约束条件,对应了SQL当中的where关键字。比如只查页数大于400的数据:
List<Book> books_where = DataSupport.where("pages>?", "400").find(Book.class);
4.6.6.order方法用于指定结果的排序方式,对应了SQL当中的order by 关键字。比如将查询结果按照书价从高到低排序:
List<Book> books_order = DataSupport.order("price desc").find(Book.class);
说明:desc:降序;asc或者不写表示升序。
4.6.7.limit方法用于指定查询结果的数量,比如只查询表中的前3条数据:
List<Book> books_limit = DataSupport.limit(3).find(Book.class);
4.6.8.offset方法用于指定查询结果的偏移量,比如查询表中的第2条、第3条、第4条数据:
List<Book> books_offset = DataSupport.limit(3).offset(1).find(Book.class);
说明:由于limit(3)查询到的是前3条数据,再加上offset(1)进行一个位置的偏移,就能实现查询第2条、第3条、第4条数据的功能。
4.6.9.对以上5个方法进行任意的连缀组合:
List<Book> books = DataSupport.select("name", "author", "pages")
.where("pages>?", "400")
.order("pages")
.limit(10)
.offset(10)
.find(Book.class);
4.6.10.上述API满足不了的时候,支持SQL查询,利用findBySQL方法:
Cursor c = DataSupport.findBySQL("select * from Book where pages > ? and price < ?","400","20");
因篇幅问题不能全部显示,请点此查看更多更全内容