Android数据存储

Android数据存储

(本文是在阅读《第一行代码》后对书中的数据存储做的笔记。在此极力推荐郭霖老师的《第一行代码》,通俗易懂,入门必读书籍。)
本文介绍的Android的数据储存主要有三种方式:文件存储、SharedPreferences存储以及数据库存储。

一、文件存储

文件写入数据

Context 类中提供了一个 openFileOutput()方法,这个方法接收两个参数,第一个参数是文件名,在文件创建的时候使用的就是这个名称,注意这里指定的文件名不可以包含路径,因为所有的文件都 是默认存储到/data/data//files/目录下的。第二个参数是文件的操作模式,主要有两种模式可选,MODE_PRIVATEMODE_APPEND。其中MODE_PRIVATE是默认的操作模式,表示当指定同样文件名的时候,所写入的内容将会覆盖原文件中的内容,而MODE_APPEND则表示如果该文 件已存在,就往文件里面追加内容,不存在就创建新文件。其实文件的操作模式本来还有另外两种:MODE_WORLD_READABLEMODE_WORLD_WRITEABLE,这两种模式表示允许其他的应用程序对我们程序中的文件进行读写操作,不过由于这两种模式过于危险,很容易引起 应用的安全性漏洞,已在Android 4.2版本中被废弃。
openFileOutput()方法返回的是一个FileOutputStream对象,得到了这个对象之后就可以使用Java流的方式将数据写入到文件中了。

	public void save() {
		String data = "Data to save";
		FileOutputStream out = null;
		BufferedWriter writer = null;
		try {
			out = openFileOutput("data", Context.MODE_PRIVATE);
			writer = new BufferedWriter(new OutputStreamWriter(out));
			writer.write(data);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (writer != null) {
				writer.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

文件读取数据

Context 类中还提供了一个openFileInput()方法,用于从文件中读取数据。这个方法只接收一个参数,即要读取的文件名,然后系统会自动到/data/data//files/目录下去加载这个文件,并返回一个FileInputStream对象,得到了这个对象之后再通过Java流的方式就可以将数据读取出来了。

	public 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();
	}

二、SharePreferences存储

将数据存储到SharedPreferences中

SharedPreferences是使用键值对的方式来存储数据的,存储的数据为xml格式。Android中主要提供了3种方法用于得到SharedPreferences对象。

  • Context类中的getSharedPreferences()方法

此方法接收两个参数,第一个参数用于指定SharedPreferences文件的名称,如果指定的文件不存在则会创建一个,SharedPreferences文件都是存放在/data/data/<package name>/shared_prefs/目录下的。第二个参数用于指定操作模式,目前只有MODE_PRIVATE这一种模式可选,它是默认的操作模式,和直接传入 0 效果是相同的,表示只有当前的应用程序才可以对这个SharedPreferences文件进行读写。

  • Activity类中的getPreferences()方法

这个方法和Context中的getSharedPreferences()方法很相似,它只接收一个操作模式参数,因为使用这个方
法时会自动将当前活动的类名作为SharedPreferences的文件名。

  • PreferenceManager类中的getDefaultSharedPreferences()方法

这是一个静态方法,它接收一个Context参数,并自动使用当前应用程序的包名作为前缀来命名SharedPreferences文件。得到了SharedPreferences对象之后,就可以开始向SharedPreferences文件中存储数据了,主要可以分为3步实现。

(1) 调用SharedPreferences对象的edit()方法来获取一个SharedPreferences.Editor对象。
(2) 向SharedPreferences.Editor对象中添加数据,比如添加一个布尔型数据就使用putBoolean()方法,添加一个字符串则使用putString()方法,以此类推。
(3) 调用apply()方法将添加的数据提交,从而完成数据存储操作。

	public class MainActivity extends AppCompatActivity {
		@Override
		protected void onCreate(Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);
			setContentView(R.layout.activity_main);
			Button saveData = (Button) findViewById(R.id.save_data);
			saveData.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					SharedPreferences.Editor editor = getSharedPreferences("data",
					MODE_PRIVATE).edit();
					editor.putString("name", "Tom");
					editor.putInt("age", 28);
					editor.putBoolean("married", false);
					editor.apply();
				}
			});
		}
	}

从SharedPreferences中读取数据

SharedPreferences对象中提供了一系列的get方法,用于对存储的数据进行读取,每种get方法都对应了SharedPreferences.Editor中的一种put方法,比如读取一个布尔型数据就使用getBoolean()方法,读取一个字符串就使用getString()方法。这些get方法都接收两个参数,第一个参数是,传入存储数据时使用的键就可以得到相应的值了;第二个参数是默认值,即表示当传入的键找不到对应的值时会以什么样的默认值进行返回。

	public class MainActivity extends AppCompatActivity {
		@Override
		protected void onCreate(Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);
			setContentView(R.layout.activity_main);
			...
			Button restoreData = (Button) findViewById(R.id.restore_data);
			restoreData.setOnClickListener(new View.OnClickListener() {
			@Override
				public void onClick(View v) {
					SharedPreferences pref = getSharedPreferences("data", MODE_PRIVATE);
					String name = pref.getString("name", "");
					int age = pref.getInt("age", 0);
					boolean married = pref.getBoolean("married", false);
					Log.d("MainActivity", "name is " + name);
					Log.d("MainActivity", "age is " + age);
					Log.d("MainActivity", "married is " + married);
				}
			});
		}
	}

三、数据库存储

(一)创建数据库

SQLiteOpenHelper 帮助类,这个类可以非常简单地对数据库进行创建和升级。SQLiteOpenHelper是一个抽象类,使用它就需要创建一个帮助类去继承它,SQLiteOpenHelper中有两个抽象方法,分别是onCreate()onUpgrade(),必须在帮助类里面重写这两个方法并在这两个方法中去实现创建、升级数据库的逻辑。

SQLiteOpenHelper中还有两个非常重要的实例方法getReadableDatabase()getWritableDatabase()。这两个方法都可以创建或打开一个现有的数据库(如果数据库已存在则直接打开,否则创建一个新的数据库),并返回一个可对数据库进行读写操作的对象。不同的是,当数据库不可写入的时候(如磁盘空间已满),getReadableDatabase()方法返回的对象将以只读的方式去打开数据库,而getWritableDatabase()方法则将出现异常。

	public class MyDatabaseHelper 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 MyDatabaseHelper(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, "Create succeeded", Toast.LENGTH_SHORT).show();
		}
		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		}
	}

把建表语句定义成了一个字符串常量,然后在onCreate()方法中调用 SQLiteDatabase 的 execSQL() 方法去执行这条建表语句。

	public class MainActivity extends AppCompatActivity {
		private MyDatabaseHelper dbHelper;
		@Override
		protected void onCreate(Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);
			setContentView(R.layout.activity_main);
			dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 1);
			Button createDatabase = (Button) findViewById(R.id.create_database);
			createDatabase.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					dbHelper.getWritableDatabase();
				}
			});
		}
	}

在onUpgrade()方法中执行了两条DROP语句,如果发现数据库中已经存在Book表或Category表了,就将这两张表删除掉,然后再调用onCreate()方法重新创建。这里先将已经存在的表删除掉,因为如果在创建表时发现这张表已经存在了,就会直接报错。

	public class MyDatabaseHelper 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 MyDatabaseHelper(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, "Create succeeded", 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);
		}
	}

还记得SQLiteOpenHelper的构造方法里接收的第四个参数吗?它表示当前数据库的版本号,之前我们传入的是1,现在只要传入一个比1大的数,就可以让onUpgrade()方法得到执行了。修改MainActivity中的代码,如下所示:

	public class MainActivity extends AppCompatActivity {
		private MyDatabaseHelper dbHelper;
		@Override
		protected void onCreate(Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);
			setContentView(R.layout.activity_main);
			dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
			Button createDatabase = (Button) findViewById(R.id.create_database);
			createDatabase.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					dbHelper.getWritableDatabase();
				}
			});
		}
	}

(二)CRUD操作

对数据进行的操作无非有4种,即CRUD。 其中C代表添加(Create),R代表查询(Retrieve),U代表更新(Update),D代表删除(Delete)。每一种操作又各自对应了一 种SQL命令,添加数据时使用insert,查询数据时使用select,更新数据时使用update,删除数据时使用delete

调用SQLiteOpenHelper的getReadableDatabase()或getWritableDatabase()方法可以用于创建和升级数据库,这两个方法会返回一个SQLiteDatabase 对象,借助这个对象就可以对数据进行CRUD操作了。

1、添加数据

SQLiteDatabase中提供了一个insert()方法,这个方法就是专门用于添加数据的。它接收3个参数:

  • 第一个参数是表名,我们希望向哪张表里添加数据,这里就传入该表的名字。
  • 第二个参数用于在未指定添加数据的情况下给某些可为空的列自动赋值NULL,一般我们用不到这个功能,直接传入null即可。
  • 第三个参数是一个ContentValues 对象,它提供了一系列的put()方法重载,用于向ContentValues中添
    加数据,只需要将表中的每个列名以及相应的待添加数据传入即可。
	public class MainActivity extends AppCompatActivity {
		private MyDatabaseHelper dbHelper;
		@Override
		protected void onCreate(Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);
			setContentView(R.layout.activity_main);
			dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
			...
			Button addData = (Button) findViewById(R.id.add_data);
			addData.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					SQLiteDatabase db = dbHelper.getWritableDatabase();
					ContentValues values = new ContentValues();
					// 开始组装第一条数据
					values.put("name", "The Da Vinci Code");
					values.put("author", "Dan Brown");
					values.put("pages", 454);
					values.put("price", 16.96);
					db.insert("Book", null, values); // 插入第一条数据
					values.clear();
					// 开始组装第二条数据
					values.put("name", "The Lost Symbol");
					values.put("author", "Dan Brown");
					values.put("pages", 510);
					values.put("price", 19.95);
					db.insert("Book", null, values); // 插入第二条数据
				}
			});
		}
	}
2、更新数据

SQLiteDatabase中也提供了一个非常好用的update()方法,用于对数据进行更新,这个方法接收4个参数:

  • 第一个参数和insert()方法一样,也是表名,在这里指定去更新哪张表里的数据。
  • 第二个参数是ContentValues对象,要把更新数据在这里组装进去。
  • 第三、第四个参数用于约束更新某一行或某几行中的数据,不指定的话默认就是更新所有行。
	public class MainActivity extends AppCompatActivity {
		private MyDatabaseHelper dbHelper;
		@Override
		protected void onCreate(Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);
			setContentView(R.layout.activity_main);
			dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
			...
			Button updateData = (Button) findViewById(R.id.update_data);
			updateData.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					SQLiteDatabase db = dbHelper.getWritableDatabase();
					ContentValues values = new ContentValues();
					values.put("price", 10.99);
					db.update("Book", values, "name = ?", new String[] { "The Da Vinci Code" });
				}
			});
		}
	}
3、删除数据

SQLiteDatabase中提供了一个delete()方法,专门用于删除数据,这个方法接收3个参数,

  • 第一个参数仍然是表名,这个已经没什么好说的了,
  • 第二、第三个参数又是用于约束删除某一行或某几行的数据,不指定的话默认就是删除所有行。
	public class MainActivity extends AppCompatActivity {
		private MyDatabaseHelper dbHelper;
		@Override
		protected void onCreate(Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);
			setContentView(R.layout.activity_main);
			dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
			...
			Button deleteButton = (Button) findViewById(R.id.delete_data);
			deleteButton.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					SQLiteDatabase db = dbHelper.getWritableDatabase();
					db.delete("Book", "pages > ?", new String[] { "500" });
				}
			});
		}
	}
4、查询数据

SQLiteDatabase中还提供了一个query()方法用于对数据进行查询。这个方法的参数非常复杂,最短的一个方法重载也需要传入7个参数。

  • 第一个参数是表名,表示我们希望从哪张表中查询数据。
  • 第二个参数用于指定去查询哪几列,如果不指定则默认查询所有列。
  • 第三、第四个参数用于约束查询某一行或某几行的数据,不指定则默认查询所有行的数据。
  • 第五个参数用于指定需要去group by的列,不指定则表示不对查询结果进行group by操作。
  • 第六个参数用于对group by之后的数据进行进一步的过滤,不指定则表示不进行过滤。
  • 第七个参数用于指定查询结果的排序方式,不指定则表示使用默认的排序方式。
query()方法参数对应SQL部分描述
tablefrom table_name指定查询的表名
columnsselect column1, column2指定查询的列名
selectionwhere column = value指定where的约束条件
selectionArgs-为where中的占位符提供具体的值
groupBygroup by column指定需要group by的列
havinghaving column = value对group by后的结果进一步约束
orderByorder by column1, column2指定查询结果的排序方式

调用query()方法后会返回一个Cursor 对象,查询到的所有数据都将从这个对象中取出。

	public class MainActivity extends AppCompatActivity {
		private MyDatabaseHelper dbHelper;
		@Override
		protected void onCreate(Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);
			setContentView(R.layout.activity_main);
			dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
			...
			Button queryButton = (Button) findViewById(R.id.query_data);
			queryButton.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					SQLiteDatabase db = dbHelper.getWritableDatabase();
					// 查询Book表中所有的数据
					Cursor cursor = db.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();
				}
			});
		}
	}
5、使用SQL操作数据库

除了查询数据的时候调用的是SQLiteDatabase的rawQuery()方法,其他的操作都是调用的execSQL()方法。

  • 添加数据的方法如下:
	db.execSQL("insert into Book (name, author, pages, price) values(?, ?, ?, ?)", 
					new String[] { "The Da Vinci Code", "Dan Brown", "454", "16.96" });
	db.execSQL("insert into Book (name, author, pages, price) values(?, ?, ?, ?)", 
					new String[] { "The Lost Symbol", "Dan Brown", "510", "19.95" });
  • 更新数据的方法如下:
	db.execSQL("update Book set price = ? where name = ?", new String[] { "10.99", "The Da Vinci Code" });
  • 删除数据的方法如下:
	db.execSQL("delete from Book where pages > ?", new String[] { "500" });
  • 查询数据的方法如下:
	db.rawQuery("select * from Book", null);

四、使用LitePal操作数据库

LitePal是一款开源的Android数据库框架,它采用了对象关系映射**(ORM)**的模式

1、配置LitePal

要使用LitePal的第一步,就是编辑app/build.gradle文件,在dependencies闭包中添加如下内容:

	dependencies {
		compile fileTree(dir: 'libs', include: ['*.jar'])
		compile 'com.android.support:appcompat-v7:23.2.0'
		testCompile 'junit:junit:4.12'
		compile 'org.litepal.android:core:1.4.1'
	}

配置litepal.xml文件。右击app/src/main目录→New→Directory,创建一个assets目录,然后在assets目录下再新建一个litepal.xml文件,接着编辑 litepal.xml文件中的内容,

	<?xml version="1.0" encoding="utf-8"?>
	<litepal>
		<dbname value="BookStore" ></dbname>
		<version value="1" ></version>
		<list></list>
	</litepal>

标签用于指定数据库名,标签用于指定数据库版本号,标签用于指定所有的映射模型.。

还需要在AndroidManifest.xml中再配置一下LitePalApplication。

	<manifest xmlns:android="http://schemas.android.com/apk/res/android"
		package="com.example.litepaltest">
		<application
			android:name="org.litepal.LitePalApplication"
			android:allowBackup="true"
			android:icon="@mipmap/ic_launcher"
			android:label="@string/app_name"
			android:supportsRtl="true"
			android:theme="@style/AppTheme">
			...
		</application>
	</manifest>

将项目的application配置为org.litepal.LitePalApplication,这样才能让LitePal的所有功能都可以正常工作。

2、创建和升级数据库

使用LitePal可以用面向对象的思维来实现和SQLiteOpenHelper同样的功能了,定义一个Book类,

	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;
		}
	}

生成getter和setter方法的快捷方式是,先将类中的字段定义好,然后按下Alt + Insert键(Mac系统是command +
N),在弹出菜单中选择Getter and Setter,接着使用Shift键将所有字段都选中,最后点击OK。

将Book类添加到映射模型列表当中,修改litepal.xml中的代码

	<litepal>
		<dbname value="BookStore" ></dbname>
		<version value="1" ></version>
		<list>
		<mapping class="com.example.litepaltest.Book"></mapping>
		</list>
	</litepal>

在MainActivity中进行数据操作。

	public class MainActivity extends AppCompatActivity {
		@Override
		protected void onCreate(Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);
			setContentView(R.layout.activity_main);
			Button createDatabase = (Button) findViewById(R.id.create_database);
			createDatabase.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					//LitePal.getDatabase()方法就是一次最简单的创建数据库的操作
					LitePal.getDatabase();
				}
			});
		}
	}

使用LitePal来升级数据库非常非常简单,只需要改想改的任何内容,然后将版本号加1就行了。

3、使用LitePal添加数据

创建出模型类的实例,再将所有要存储的数据设置好,最后调用一下** save() **方法就可以了。

模型类都是没有继承结构的,因为LitePal进行表管理操作时不需要模型类有任何的继承结构。但是进行CRUD操作时就必须要继承自LitePalSupport 类 (DataSupport 类已被弃用) 才行,因此修改Book类中的代码,如下所示:

	public class Book extends LitePalSupport {
		...
	}

向Book表中添加数据

	public class MainActivity extends AppCompatActivity {
		@Override
		protected void onCreate(Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);
			setContentView(R.layout.activity_main);
			...
			Button addData = (Button) findViewById(R.id.add_data);
			addData.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					Book book = new Book();
					book.setName("The Da Vinci Code");
					book.setAuthor("Dan Brown");
					book.setPages(454);
					book.setPrice(16.96);
					book.setPress("Unknow");
					book.save();
				}
			});
		}
	}
4、使用LitePal更新数据

对象是否已存储就是根据调用model.isSaved()方法的结果来判断的,返回true就表示已存储,返回false就表示未存储。

实际上只有在两种情况下model.isSaved()方法才会返回true,一种情况是已经调用过model.save()方法去添加数据了,此时model会被认为是已存储的对象。另一种情况是model对象是通过LitePal提供的查询API查出来的,由于是从数据库中查到的对象,因此也会被认为是已存储的对象。

	public class MainActivity extends AppCompatActivity {
		@Override
		protected void onCreate(Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);
			setContentView(R.layout.activity_main);
			...
			Button updateData = (Button) findViewById(R.id.update_data);
			updateData.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					Book book = new Book();
					book.setName("The Lost Symbol");
					book.setAuthor("Dan Brown");
					book.setPages(510);
					book.setPrice(19.95);
					book.setPress("Unknow");
					book.save();
					book.setPrice(10.99);
					book.save();
				}
			});
		}
	}

另外一种更加灵巧的更新方式

	public class MainActivity extends AppCompatActivity {
		@Override
		protected void onCreate(Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);
			setContentView(R.layout.activity_main);
			...
			Button updateData = (Button) findViewById(R.id.update_data);
			updateData.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					Book book = new Book();
					book.setPrice(14.95);
					book.setPress("Anchor");
					book.updateAll("name = ? and author = ?", "The Lost Symbol", "Dan
					Brown");
				}
			});
		}
	}

updateAll()方法中可以指定一个条件约束,和SQLiteDatabase中update()方法的where参数部分有点类似,但更加简洁,如果不指定条件语句的话,就表示更新所有数据。

在Java中任何一种数据类型的字段都会有默认值,例如int类型的默认值是0,boolean类型的默认值是false,String类型的默认值是null。那么当new出一个Book对象时,其实所有字段都已经被初识化成默认值了,比如说pages字段的值就是0。因此,如果想把数据库表中的pages列更新成0,直接调用book.setPages(0)是不可以的,因为即使不调用这行代码,pages字段本身也是0,LitePal此时是不会对这个列进行更新的。对于所有想要将为数据更新成默认值的操作,LitePal统一提供了一个setToDefault()方法,然后传入相应的列名就可以实现了。

	Book book = new Book();
	book.setToDefault("pages");
	book.updateAll();
5、使用LitePal删除数据

直接调用已存储对象的delete()方法就可以了,这种方式比较简单就不进行代码演示了,下面直接来看另外一种删除数据的方式。

	public class MainActivity extends AppCompatActivity {
		@Override
		protected void onCreate(Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);
			setContentView(R.layout.activity_main);
			...
			Button deleteButton = (Button) findViewById(R.id.delete_data);
			deleteButton.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					LitePalSupport.deleteAll(Book.class, "price < ?", "15");
				}
			});
		}
	}

这里调用了LitePalSupport.deleteAll()方法来删除数据,其中deleteAll()方法的第一个参数用于指定删除哪张表中的数据,Book.class就意味着删除Book表中的数据,第二第三的参数用于指定约束条件。

6、使用LitePal查询数据
	List<Book> books = LitePalSupport.findAll(Book.class);

LitePalSupport.findAll()方法的返回值是一个Book类型的List集合,也就是说,不用像之前那样再
通过Cursor对象一行行去取值了,LitePal已经自动帮我们完成了赋值操作。

	public class MainActivity extends AppCompatActivity {
		@Override
		protected void onCreate(Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);
			setContentView(R.layout.activity_main);
			...
			Button queryButton = (Button) findViewById(R.id.query_data);
			queryButton.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					List<Book> books = LitePalSupport.findAll(Book.class);
					for (Book book: books) {
						Log.d("MainActivity", "book name is " + book.getName());
						Log.d("MainActivity", "book author is " + book.getAuthor());
						Log.d("MainActivity", "book pages is " + book.getPages());
						Log.d("MainActivity", "book price is " + book.getPrice());
						Log.d("MainActivity", "book press is " + book.getPress());
					}
				}
			});
		}
	}

查询Book表中的第一条数据就可以这样写:

	Book firstBook = LitePalSupport.findFirst(Book.class);

查询Book表中的最后一条数据就可以这样写:

	Book lastBook = LitePalSupport.findLast(Book.class);

还可以通过连缀查询来定制更多的查询功能。

  • select() 方法用于指定查询哪几列的数据,对应了SQL当中的select关键字。比如只查name和author这两列的数据,就可以这样写:
	List<Book> books = LitePalSupport.select("name", "author").find(Book.class);
  • where() 方法用于指定查询的约束条件,对应了SQL当中的where关键字。比如只查页数大于400的数据,就可以这样写:
	List<Book> books = LitePalSupport.where("pages > ?", "400").find(Book.class);
  • order() 方法用于指定结果的排序方式,对应了SQL当中的order by关键字。比如将查询结果按照书价从高到低排序,就可以这样写:
	List<Book> books = LitePalSupport.order("price desc").find(Book.class);

其中 desc 表示降序排列, asc 或者不写表示升序排列。

  • limit() 方法用于指定查询结果的数量,比如只查表中的前3条数据,就可以这样写:
	List<Book> books = LitePalSupport.limit(3).find(Book.class);
  • offset() 方法用于指定查询结果的偏移量,比如查询表中的第2条、第3条、第4条数据,就可以这样写:
	List<Book> books = LitePalSupport.limit(3).offset(1).find(Book.class);

这5个方法进行任意的连缀组合,可以完成一个比较复杂的查询操作:

	List<Book> books = LitePalSupport.select("name", "author", "pages")
									.where("pages > ?", "400")
									.order("pages")
									.limit(10)
									.offset(10)
									.find(Book.class);

itePal仍然支持使用原生的SQL来进行查询:

	Cursor c = LitePalSupport.findBySQL("select * from Book where pages > ? and price < ?", "400", "20");

调用 LitePalSupport.findBySQL() 方法来进行原生查询,其中第一个参数用于指定SQL语句,后面的参数用于指定占位符的值。注意 findBySQL() 方法返回的是一个 Cursor 对象,

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android数据存储是一种将数据存储在设备上的技术,以便应用程序可以使用它们,无论它们是否在运行。这使得应用程序可以使用一些简单且安全的存储方法,而无需直接与设备存储硬件进行交互。Android提供了几种不同的数据存储选项,包括: 1. **Shared Preferences**:这是最基本的数据存储方式,它允许应用程序存储和检索键值对数据。这对于小型数据存储需求非常有用,因为它们是本地存储并且对其他应用程序不可见。 2. **Files**:应用程序可以使用文件系统来存储和检索数据。这可以包括文本文件、图像、音频和视频文件等。文件系统存储数据可以在应用程序关闭后保持持久性。 3. **SQLite**:SQLite是一个轻量级的关系型数据库,它可以在设备上作为嵌入式数据库使用。SQLite提供了对数据结构化查询支持,因此更适合存储大量数据。 4. **Content Providers**:Content Providers允许应用程序之间共享数据。它们使得跨应用程序访问和共享数据成为可能,这对于构建大型应用程序的跨应用程序功能非常有用。 5. **外部存储(如SD卡)**:Android允许应用程序访问设备的外部存储(如SD卡)。这可以用于存储文件或大型数据集,但需要注意的是,访问外部存储可能需要额外的权限。 在选择适当的存储选项需要考虑数据的类型、大小、持久性和安全性。例如,如果数据需要在应用程序运行可用,Shared Preferences可能是一个合适的选择。然而,如果需要存储大量结构数据或大型文件,那么SQLite或外部存储可能更适合。 此外,对于敏感数据(如用户密码或个人信息),建议使用加密来保护这些数据。在Android中,可以使用AES或其他加密算法来实现这一点。 最后,记住在处理存储数据遵循最佳实践,例如使用适当的错误处理和日志记录,以确保数据的安全性和完整性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值