怎么设计门户网站,不动产登记门户网站建设方案,php网站开发具体的参考文献,微信二维码制作小程序持久化技术简介
在你打开完成了一份PPT之后关闭程序#xff0c;再次打开肯定是希望之前的内容还存在在电脑上#xff0c;一打开PPT#xff0c;之前的内容就自动出现了。数据持久化就是将那些内存中的瞬时数据保存到存储设备中#xff0c;保证即使在手机或电脑关机的情况下…持久化技术简介
在你打开完成了一份PPT之后关闭程序再次打开肯定是希望之前的内容还存在在电脑上一打开PPT之前的内容就自动出现了。数据持久化就是将那些内存中的瞬时数据保存到存储设备中保证即使在手机或电脑关机的情况下这些数据仍然不会丢失。保存在内存中的数据是处于瞬时状态的而保存在存储设备中的数据是处于持久状态的持久化技术则提供了一种机制可以让数据在瞬时状态和持久化状态之间进行转换。
Android系统主要提供了3种方式用于简单地实现数据持久化功能
文件存储SharedPreferences存储数据库存储
文件存储
文件存储是Android中最基本的一种数据存储方式它不对存储的内容进行任何的格式化处理所有的数据都是原封不动地保存到文件当中因而它比较适合用于存储一些简单的文本数据或者二进制数据。
将数据存储到文件中
Context类中提供了一个openFileOutput()方法可以用于将数据存储到指定的文件当中。
第一个参数为文件名在文件创建的时候使用的就是这个名称这里的文件名不可以包含路径因为所有的文件都是默认存储到/data/data//files/目录下第二个参数是文件的操作模式主要有两种模式可以选MODE_PRIVATE和MODE_APPEND 二者的相同点当文件不存在时都会创建一个新文件来写入数据 MODE_PRIVATE是默认的操作模式会截断文件即删除文件中的现有内容并从文件开头开始写入新数据 MODE_APPEND新写入的数据会被追加到文件的末尾而不是覆盖现有内容 openFileOutput()方法返回的是一个FileOutputStream对象得到了这个对象就可以使用Java流的方式将数据写到文件中了。我们先创建一个活动设置一个EditText用来使用户输入信息在我们关闭程序的时候将数据进行存储代码如下
public class MainActivity extends AppCompatActivity {private EditText editText;Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);EdgeToEdge.enable(this);setContentView(R.layout.activity_main);ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) - {Insets systemBars insets.getInsets(WindowInsetsCompat.Type.systemBars());v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);return insets;});editText (EditText) findViewById(R.id.edit);}}Overrideprotected void onDestroy() {super.onDestroy();String input editText.getText().toString();save(input);}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();}}}
}从文件中读取数据
Context类中还提供一个openFileInput()方法用于从文件里面读取数据它只接收一个参数即要读取的文件名然后系统会自动到目录下去加载这个文件并返回一个FileInputStream对象得到这个对象之后再通过Java流的方式将数据读取出来。
读取文件代码如下
public String lode () {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) {throw new RuntimeException(e);}}}return content.toString();
}首先通过openFileInput()方法获取到一个FileInputStream对象然后借助它又构建一个InputStreamReader对象接着再使用InputStreamReader构建成一个BufferedReader对象这样就可以一行行地读取把文件地内容都读取出来。学习了读取文件的代码就对活动进行修改使你第一次输入的数据在退出程序之后再次进入程序数据依然保留。修改代码如下
先将上面读取文件的代码加入活动当中再在onCreate()方法里面补充
String input lode();
editText (EditText) findViewById(R.id.edit);
if (!TextUtils.isEmpty(input)) {editText.setText(input);editText.setSelection(input.length());Toast.makeText(this,Restoring succeeded, Toast.LENGTH_SHORT).show();
}在Android开发中setSelection方法用于设置文本输入框如EditText中光标的位置。当你调用editText.setSelection(input.length());时你实际上是将光标移动到了文本的末尾。 现在运行程序第一次运行没有输入任何的数据因此打开程序的输入框是空白的当我们输入一段文字再次打开 SharedPreferences存储
SharedPreferences是使用键值对的方式进行数据存储的因此我们可以根据数据所对应的键将数据取出来。
将数据存储到SharedPreferences中
要想使用SharedPreferences来存储数据首先需要获取到SharedPreferences对象Android提供了三种方式用于得到SharedPreferences对象 Context类中的getSharedPreferences()方法 此方法接收两个参数第一个参数用于指定SharedPreferences文件的名称如果指定的文件不存在则会创建一个SharedPreferences文件都是放在/data/data//shared_prefs/目录下的。第二个参数用于指定操作模式目前只有MODE_PRIVATE这一种模式可选它是默认的操作模式和直接传入0是效果相同的表示只有当前的程序才可以对这个SharedPreferences文件进行读写 Activity类中的getPreferences()方法 这个方法和上面的方法很类似但它只接收一个操作模式参数因为这个方法会自动获取当前活动的类名作为SharedPreferences的文件名 PreferenceManage类中的getDefaultSharedPreferences()方法 这是一个静态方法只接收一个Context参数并自动使用当前应用程序的包名作为前缀名来命名SharedPreferences文件。
接下来就进行数据的存储
调用SharedPreferences对象的edit()方法来获取一个SharedPreferences.Editor对象向SharedPreferences.Editor对象中添加数据例如添加String类型就使用putString()方法调用apply()方法将添加的数据提交从而完成数据存储操作
接下来就根据实例来体验一下吧新建一个项目在主活动上面设置一个按钮用来触发存储数据为按钮注册点击事件
public class MainActivity extends AppCompatActivity {Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);EdgeToEdge.enable(this);setContentView(R.layout.activity_main);ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) - {Insets systemBars insets.getInsets(WindowInsetsCompat.Type.systemBars());v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);return insets;});Button buttonsava (Button) findViewById(R.id.savaData);buttonsava.setOnClickListener(new View.OnClickListener() {Overridepublic 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中读取数据
上面提到了put方法将数据存储进去相对应的有get方法从中读取数据。这些get方法都接收两个参数第一个参数是键传入存储数据时使用的键就可以得到相应的值了第二个参数是默认值即表示当前的键找不到对应的值时会以什么样的默认值进行返回。
仍然在上面进行修改添加一个按钮用来触发读取数据的事件并未按钮注册点击事件
Button buttonget (Button) findViewById(R.id.getData);
buttonget.setOnClickListener(new View.OnClickListener() {Overridepublic void onClick(View v) {SharedPreferences preferences getSharedPreferences(data, MODE_PRIVATE);String name preferences.getString(name, );int age preferences.getInt(age, 0);boolean marr preferences.getBoolean(married, false);Log.d(MainActivity, name is name);Log.d(MainActivity, age is age);Log.d(MainActivity, married is marr);}
});按下get data按钮就可以得到信息了
案例
接下来就通过一个案例让大家体会数据存储吧。我们有时在登录的时候经常遇到一个选项是否记住密码当我们按下这个按钮在下一次登录的时候就会自动的为我们输入数据此时我们只需要按下登录按钮即可。想要了解的话可以看上一篇广播的博客在结尾我们实现了一个强制下线的功能现在就对这个小项目加上记住密码功能。因此在登录界面我们需要使使用者自由选择是否让程序记住密码
LinearLayoutandroid:layout_widthmatch_parentandroid:layout_heightwrap_contentandroid:orientationhorizontalCheckBoxandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:idid/remember_pass/TextViewandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:textSize18spandroid:textremember password/
/LinearLayout修改登录界面的代码
private SharedPreferences preferences;
private SharedPreferences.Editor editor;
private CheckBox checkBox;先根据前面的读取数据在onCreate()方法里面修改
preferences PreferenceManager.getDefaultSharedPreferences(this);
checkBox (CheckBox) findViewById(R.id.remember_pass);
boolean isremember preferences.getBoolean(remember_password, false);
if (isremember) {String account preferences.getString(account, );String password preferences.getString(password, );accountEdit.setText(account);passwordEdit.setText(password);checkBox.setChecked(true);
}先获取上一次存储的数据是否允许记得如果是就将上一次的数据读取出来显示在文本框接下来就是登录的点击按钮会根据我们此次是否选择记住密码而进行不同的操作
login.setOnClickListener(new View.OnClickListener() {Overridepublic void onClick(View v) {String account accountEdit.getText().toString();String password passwordEdit.getText().toString();if (account.equals(admin) password.equals(123456)) {editor preferences.edit();if (checkBox.isChecked()) {editor.putBoolean(remember_password, true);editor.putString(account, account);editor.putString(password, password);} else {editor.clear();}editor.apply();Intent intent new Intent(LoginActivity.this, MainActivity.class);startActivity(intent);finish();} else {Toast.makeText(LoginActivity.this,account or password is invalid, Toast.LENGTH_SHORT).show();}}
});在我们的账户与密码正确的时候会根据我们对于记住密码的选择进行数据存储的更新。
此时运行程序当我们选择记住密码时到了活动界面按下按钮强制下线之后密码与账号已经输好了只需要按下登录按钮即可。
SQLite数据库存储
Android系统内置了数据库——SQLite。SQLite是一款轻量级的关系型数据库它的运算速度非常快占用资源很少通常只需要几百KB的内存就足够了因而特别适合在移动设备上使用。SQLite不及支持标准的SQL语法还遵循数据库的ACID事务。前面介绍的方法都只适用一些简单的数据存储当存储量大的时候上面的方法就很难实现了。接下来就看看Android的SQLite数据库是如何使用的吧
创建数据库
Android为了让我们能够更加方便地管理数据库,专门提供了一个 SQLiteOpenHelper帮助类借助这个类就可以非常简单地对数据库进行创建和升级。下面我就对 SQLiteOpenHelper的基本用法进行介绍。
SQLiteOpenHelper是一个抽象类这意味着如果我们想要使用它的话就需要创建一个自己的帮助类去继承它。SQLiteOpenHelper中有两个抽象方法分别是onCreate()和 onUpgrade()我们必须在自己的帮助类里面重写这两个方法然后分别在这两个方法中去实现创建、升级数据库的逻辑。
SQLiteOpenHelper中还有两个非常重要的实例方法:getReadableDatabase()和 getwritableDatabase()。这两个方法都可以创建或打开一个现有的数据库如果数据库已存在则直接打开否则创建一个新的数据库)并返回一个可对数据库进行读写操作的对象。不同的是,当数据库不可写入的时候如磁盘空间已满),getReadableDatabase()方法返回的对象将以只读的方式去打开数据库,而getwritableDatabase()方法则将出现异常。
SQLiteOpenHelper中有两个构造方法可供重写一般使用参数少一点的那个构造方法即可。这个构造方法中接收4个参数
第一个参数是 Context这个没什么好说的必须要有它才能对数据库进行操作。 Cursor是一个从android.database.Cursor类继承而来的接口用于访问SQLite数据库的内容。 第二个参数是数据库名创建数据库时使用的就是这里指定的名称。第三个参数允许我们在查询数据的时候返回一个自定义的Cursor一般都是传入null。第四个参数表示当前数据库的版本号可用于对数据库进行升级操作。
构建出 SQLiteOpenHelper的实例之后再调用它的getReadableDatabase()或 getwritableDatabase()方法就能够创建数据库了数据库文件会存放在/data/data//databases/目录下。此时重写的oncreate()方法也会得到执行,所以通常会在这里去处理一些创建表的逻辑。 SQL知识的补充 一个数据库通常会包含一个或多个表每个表由一个名字标识例如价格、id。表包含带有数据的记录例 IDnameage1Tom232Jack153Aila41 包含三条记录每个记录对应一个人 创建表 create table 表名称 ( 列名称1 数据类型 列名称2 数据类型 … ); 它的数据类型很简单integer表示整型real表示浮点型text表示文本类型blob表示二进制类型 接下来就实践一下 新建MyDatabaseHelper继承于SQLiteOpenHelper
public class MyDatabaseHelper extends SQLiteOpenHelper {public static final String CREATE_BOOK create table book ( id integer primary key autoincrement, author text, price reeal, 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;}Overridepublic void onCreate(SQLiteDatabase db) {db.execSQL(CREATE_BOOK);Toast.makeText(mcontext, succeeded succeeded, Toast.LENGTH_SHORT).show();}Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}
}我们先使用SQL语句创建了一个名为book的表
在表中创建id的时候我们使用primary key该字段是表的主键。主键是一个或多个字段的组合用于唯一标识表中的每条记录。在数据库中主键的值必须唯一不能为null除非特别指定我们还加入了autoincrement这是一个特定于某些数据库系统如SQLite的属性表示每当表中插入一条新记录时该字段的值会自动递增。这通常用于生成一个唯一的序列号使得每条记录都有一个唯一的标识符。在SQLite中autoincrement属性仅适用于整型integer字段。
构造出MyDatabaseHelper传入4个参数
context应用程序的上下文用于获取数据库文件的路径name数据库文件的名称factory游标工厂用于创建游标对象。游标Cursor是一个重要的概念它允许应用程序从数据库中检索和操作数据。游标工厂Cursor Factory是一个接口用于创建游标对象version数据库的版本号
重写了MyDatabaseHelper的onCreate()方法这样在我们创建这个数据库的时候就会跟着执行onCreate()方法从而同时完成表的创建。onUpgrade()方法这是SQLiteOpenHelper的另一个重写方法当数据库需要升级时调用
这样数据库的创建代码就完成了接下来我们就在活动当中加上一个按钮使按下按钮数据库就自动进行创建
public class MainActivity extends AppCompatActivity {//按钮用来触发数据库的创建private Button buttonCreateData;//新建数据库MyDatabaseHelper dphelper;Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);EdgeToEdge.enable(this);setContentView(R.layout.activity_main);ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) - {Insets systemBars insets.getInsets(WindowInsetsCompat.Type.systemBars());v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);return insets;});//创建了一个MyDatabaseHelper对象dphelper new MyDatabaseHelper(this, BookStore.db, null, 1);//为按钮注册点击事件buttonCreateData (Button) findViewById(R.id.create_database);buttonCreateData.setOnClickListener(new View.OnClickListener() {Overridepublic void onClick(View v) {dphelper.getWritableDatabase();}});}
}我们先创建了一个MyDatabaseHelper对象当你第一次点击按钮此时程序当中并没有这个数据库因此会调用MyDatabaseHelper里的onCreate()方法进行创建此时就会弹出Toast提示。当我们再次按的时候由于已经创建过了就会不会再执行了也就没有了Toast消息提示。
升级数据库
在上面数据库类里面就有一个空的方法onUpgrade()我们只简单提了一下是在数据库升级时调用接下来就重点学习吧。可是很重要的
我们在其中加入一个表用于书的分类我们再在onCreate()方法里面加上将这个表创建的语句
public static final String CREATE_CATEGORY create table category ( id integer primary key autoincrement, category_name text, category_code integer);public void onCreate(SQLiteDatabase db) {db.execSQL(CREATE_BOOK);db.execSQL(CREATE_CATEGORY);Toast.makeText(mcontext, succeeded succeeded, Toast.LENGTH_SHORT).show();
}此时运行程序并没有Toast语句弹出即没有执行onCreate()方法这是因为数据库已经在之前建好了之后无论怎样都不会执行因此我们就要用到onUpgrade()方法对这个方法进行修改
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);
}这两个语句为当在数据库当中发现存在这两张表的时候就将表删除之后再执行onCreate()方法接下来就是让这个方法在创建的时候执行上面提到构造的时候传入个参数还记得吗最后一个就是版本号此时我们能将版本号改为2再次运行程序此时就弹出了添加成功的信息。
添加数据
SQLiteDatabse 中提供了一个insert()方法这个方法就是专门用于添加数据的
第一个参数是表名我们希望向哪张表里添加数据这里就传入该表的名字第二个参数用于在未指定添加数据的情况下给某些可为空的列自动赋值NULL一般我们用不到这个功能直接传入null即可第三个参数是一个ContentValues对象它提供了一系列的put()方法重载用于向ContentValues中添加数据只需要将表中的每个列名以及相应的待添加数据传入即可。
Button buttonadd (Button) findViewById(R.id.add_data);
buttonadd.setOnClickListener(new View.OnClickListener() {Overridepublic void onClick(View v) {SQLiteDatabase db dphelper.getWritableDatabase();ContentValues values new ContentValues();values.put(name, Tombook);values.put(author, Tom);values.put(price, 23.23);values.put(pages, 56);db.insert(book, null, values);values.clear();values.put(name, Ailabook);values.put(author, Aila);values.put(price, 56.23);values.put(pages, 99);db.insert(book, null, values);Toast.makeText(MainActivity.this, hhhh, Toast.LENGTH_SHORT).show();}
});更新数据
SQLite-Database中也提供了一个非常好用的 update()方法用于对数据进行更新
第一个参数和insert()方法一样也是表名在这里指定去更新哪张表里的数据第二个参数是ContentValues对象要把更新数据在这里组装进去第三、第四个参数用于约束更新某一行或某几行中的数据不指定的话默认就是更新所有行
Button buttonupdata (Button) findViewById(R.id.updata_data);
buttonupdata.setOnClickListener(new View.OnClickListener() {Overridepublic void onClick(View v) {SQLiteDatabase db dphelper.getWritableDatabase();ContentValues values new ContentValues();values.put(price, 12.12);db.update(book, values, name ?,new String[] {Tombook});}
});第三个参数对应的是SQL语句的 where部分表示更新所有name等于?的行而?是一个占位符,可以通过第四个参数提供的一个字符串数组为第三个参数中的每个占位符指定相应的内容。因此上述代码想表达的意图是将名字是Tombook的这本书的价格改成10.99。
删除数据
SQLite-Database中也提供了一个非常好用的 delete()方法用于对数据进行删除
第一个参数仍然为表名第二三个参数用于约束更新某一行或某几行中的数据不指定的话默认就是删除所有行
Button buttondelete (Button) findViewById(R.id.dalete_data);
buttondelete.setOnClickListener(new View.OnClickListener() {Overridepublic void onClick(View v) {SQLiteDatabase db dphelper.getWritableDatabase();db.delete(book, pages ?, new String[] {500});}
});查询数据
SQLite-Database中专门提供了一个非常好用的 query()方法用于对数据进行查找需要传入七个参数
表名即我们希望从哪张表中查询数据用于指定查询那几列不指定则默认查所有列第三四个参数用于约束查询某一行或者某几行的数据不指定则默认查询所有行的数据用于指定需要去group by的列不指定则表示不对查询结果进行group by的操作即进行分组用于对进行group by之后的数据进行进一步的过滤不指定则表示不进行过滤用于指定查询结果的排序方式不指定则表示默认的排序方式 Button buttonquery (Button) findViewById(R.id.query_data);
buttonquery.setOnClickListener(new View.OnClickListener() {Overridepublic void onClick(View v) {SQLiteDatabase db dphelper.getWritableDatabase();Cursor cursor db.query(book, null, null, null, null, null, null);if (cursor.moveToFirst()) {while (cursor.moveToNext()){SuppressLint(Range) String name cursor.getString(cursor.getColumnIndex(name));SuppressLint(Range) int pages cursor.getInt(cursor.getColumnIndex(pages));SuppressLint(Range) double price cursor.getDouble(cursor.getColumnIndex(price)); }}cursor.close();}
});文章到这里就结束了