zoukankan      html  css  js  c++  java
  • Android06——Persistence

    持久化(Persistence)


    由于这个东西和mybatis比较像,而且没有太多的内容,写的比较简单。

    简介

    Android系统中主要听过了三种方式用于简单地实现数据持久化功能:文件存储、sharedpreference存储以及数据库存储。

    这一章默认是在模拟器上学习了,华为手机如果没有root的话,是无法进入根目录(/)文件夹下的,也就没办法去/data/app/com.ssozh.filepersistentcetest下查看相关文件了。而华为的内部存储所在的文件夹是/storage/emulated/0/

    文件存储

    文件存储是Android中最基本的数据存储方法,它不对存储的内容进行任何格式化处理,所有数据都是原封不动的保存到文件中。

    存储

    Context类提供了一个openFileOutput()方法,可以用于将数据存储到指定的文件中。

    FileOutputStream openFileOutput(fileName, OPFlag)
    输入参数:
    	fileName是不包括路径的,所有文件都是默认存储到/data/data/<package name>/files/目录下
    	OPFlag:文件的操作模式,主要有MODE_PRIVATE(默认)和MODE_ADDEND两种模式,前者是覆盖,后者是追加。另外还有MODE_WORLD_
    输出参数:
    	FileOutputStream对象,得到这个对象之后就可以使用java流的方式将数据写入文件中了。
    

    假设我们希望关闭app的时候,存储相关数据:

        private EditText edit;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            this.edit = (EditText)findViewById(R.id.edit);
            String inputText = load();
            if (!TextUtils.isEmpty(inputText)) {
                edit.setText(inputText);
                edit.setSelection(inputText.length());
                Toast.makeText(this,"Restoring succeeded",Toast.LENGTH_SHORT).show();
            }
        }
    
    	@Override
        protected void onDestroy() {
            super.onDestroy();
            String inputText = this.edit.getText().toString();
            save(inputText);
        }
    
        private void save(String inputText) {
            FileOutputStream out = null;
            BufferedWriter writer = null;
            try {
                out = openFileOutput("data", Context.MODE_APPEND);
                writer = new BufferedWriter(new OutputStreamWriter(out));
                writer.write(inputText);
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (writer != null){
                    try {
                        writer.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    

    读取

    类似于将数据存储到文件中,Context类中还提供了一个openFileInput()方法,用于文件中读取数据。

    FileInputStream openFileInput(fileName)
    输入参数:
    	fileName是不包括路径的,所有文件都是默认存储到/data/data/<package name>/files/目录下.
    输出参数:
    	FileInputStream对象,得到这个对象之后就可以使用java流的方式将数据读取文件中了。
    

    我们希望再次启动的时候,载入相关数据(注意这个循环会造成文件越存储越大):

        private String load(){
            FileInputStream inputStream = null;
            BufferedReader reader = null;
            StringBuilder content = new StringBuilder();
            try {
                inputStream = openFileInput("data");
                reader  = new BufferedReader(new InputStreamReader(inputStream));
                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();
        }
    

    SharedPreferences存储

    不同于文件的存储方式,sharedpreference是使用键值对的方式来来存储数据的。而且sharedpreferences还支持多种不同的数据存储类型。可以是整型、字符串等等。

    存储

    • 想要使用sharedpreferences存储数据,首先需要获取对象SharedPreferences。主要有两种方法:
      • Context类中的getSharedPreferences()方法:
        • 这个方法和上面的文件存储方法openFileOutput基本一样,包括文件名和写入模式的选择两个参数。
        • 区别在于默认存放在/data/data/<package name>/shared_prefs目录下。
      • Activity类中的getPreferences()方法:
        • 这个方法只接受操作模式这一个参数。因为是用这个方法时会自动将当前activity的类名作为sharedPreferences的文件名。
    • 调用SharedPreferences对象的edit()方法获取一个SharedPreferences.Editor对象。
    • SharedPreferences.Editor对象中添加数据,比如添加boolran型,就使用putBoolean方法。
    • 调用apply()方法将添加的数据提交、从而完成数据存储操作。

    读取

    还是获取SharedPreferences对象,然后调用get方法即可。

    get方法接受两个参数,第一个是key,第二个参数是默认值,即表示当传入的键找不到对应的值时的返回值。

    记住密码

    在上一节的登陆部分,添加一个checkBox控件,增加记住密码功能。

    public class LoginActivity extends BaseActivity {
        private EditText accountEdit;
        private EditText passwordEdit;
        private Button login;
    
        private CheckBox rememberPassword;
        private SharedPreferences pref;
        private SharedPreferences.Editor editor;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_login);
            login = (Button)findViewById(R.id.login);
            rememberPassword =(CheckBox) findViewById(R.id.remember_password);
            pref = PreferenceManager.getDefaultSharedPreferences(this);
            editor = pref.edit();
            accountEdit = (EditText) findViewById(R.id.account_edit);
            passwordEdit = (EditText) findViewById(R.id.password_edit);
            // 读取SharedPreferences
            boolean isRemember = pref.getBoolean("remember_password",false);
            if(isRemember){
                // 将账户和密码都设置到文本框中
                String account = pref.getString("account","");
                String password = pref.getString("password","");
                accountEdit.setText(account);
                passwordEdit.setText(password);
                rememberPassword.setChecked(true);
            }
    
    
            login.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
    
                    if("admin".equals(accountEdit.getText().toString()) && "123456".equals(passwordEdit.getText().toString())){
                        if(rememberPassword.isChecked()){
                            // 存储SharedPreferences
                            editor.putBoolean("remember_password",true);
                            editor.putString("account",accountEdit.getText().toString());
                            editor.putString("password",passwordEdit.getText().toString());
                        }else {
                            // 否则清除数据
                            editor.clear();
                        }
                        editor.apply();
    
                        Intent intent = new Intent(LoginActivity.this, MainActivity.class);
                        startActivity(intent);
                        finish();
                    }else {
                        // TODO:华为键盘会挡住这个toast
                        Toast.makeText(LoginActivity.this,"account or password is invalid",Toast.LENGTH_SHORT).show();
                    }
                }
            });
        }
    }
    

    SQLite数据库存储

    基本操作

    创建、更新数据库

    要想在通过SQLite对数据库进行操作,首先需要创建一个子类继承SQLiteOpenHelper,然后重写他的方法:

    • onCreate:创建数据库
    • onUpgrade:升级数据库
      • 升级数据库的方法:在onUpgrade方法中先把之前的数据库删除,然后重新创建,同时注意在new databaseHelper的时候修改版本号
      • 注意:如果不修改版本号,是不会执行onUpgrade操作的!!!
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            // 后面的1 -> 2表示数据库升级了,比如添加了一个table 之类的行为都叫update
            dbHelper = new MydatabaseHelper(this,"BookStore.db",null,2);
            Button createDb = (Button) findViewById(R.id.create_database);
            createDb.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    dbHelper.getWritableDatabase();
                }
            });
        }
    
        @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);
        }
    

    【adb在F:AndroidSDKplatform-tools目录下,可以先添加path】

    可以考虑通过adb shell进行adb调试,但是由于华为不能root,好像无法访问/data/data下面的app:

    这里可以查看最下方的Android studio自带的database inspection:

    添加数据CRUD

    通过调用SQLiteOpenHelper的getReadableDatabasegetWriteableDatabase方法是可以用于创建和升级数据库的,不仅如此,这两个方法还都会返回一个SQLiteDatabase对象,借助这个对象就可以进行CRUD操作了。

    操作方式基本一致:

    • 通过dbHelper.getWriteableDatabase(),找到数据库db

    • db.insert() , db.query()等方法进行CRUD

    • 其中CU的对象是ContentValues

    • query和delete不太一样

                 @Override
                  public void onClick(View v) {
                      SQLiteDatabase db = dbHelper.getWritableDatabase();
                      ContentValues values = new ContentValues();
                      // 开始组装第一条数据
                      values.put("name", "The Dan Vinci Code");
                      values.put("author","Dan Brown");
                      values.put("pages", 154);
                      values.put("price",16.69);
                      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);
                  }
      
    • 修改:

    • 删除:

      db.delete("Book", "pages > ?" , new String[] {"500"});
      
    • 查询:

                  @Override
                  public void onClick(View v) {
                      SQLiteDatabase db = dbHelper.getWritableDatabase();
                      // 查询db表中的所有数据
                      Cursor cursor = db.query("Book", null, null, null, null, null, null);
                      if(cursor!=null) {
                          while (cursor.moveToNext()){
                              String[] columns = new String[]{"name", "author", "pages", "price"};
                              for(String column : columns){
                                  printOnLog(cursor,column);
                              }
                          }
                      }
                  }
      
                  private void printOnLog(Cursor cursor, String column){
      //                String name = cursor.getString(cursor.getColumnIndex("name"));
                      Object tmp = cursor.getString(cursor.getColumnIndex(column));
                      Log.d(TAG,"book " + column + " is " + tmp.toString());
                  }
      

    直接使用SQL语句操作数据库(有点像mybatis):

    db.execSQL("insert into Book(name, author, pages, price) values(?, ?, ?, ?)", new String[]{"","","",""});
    

    SQLite数据库的最佳实践

    使用事务

  • 相关阅读:
    转:Web Service介绍
    CodeIgniter网页缓存
    CodeIgniter管理你的应用程序
    CodeIgniter自动装载资源
    python feedparser 使用
    HTC文件的使用
    动态执行javascript代码
    jQuery获取文本节点之text()/val()/html() 方法区别
    style,runtimeStyle与currentStyle的定义及用法
    File,FileStream,byte[]3者互相转换总结(转)
  • 原文地址:https://www.cnblogs.com/SsoZhNO-1/p/14092670.html
Copyright © 2011-2022 走看看