Android高级应用开发(基础篇) - stage7 - 学习笔记

 

开发问题:大胆假设,小心求证(Sundy)

 

推测的一些存储方式和存储介质

1、XML——SharedPreference

2、Binary File——File

3、关系型数据库——SQLite3

4、网络访问——Network(Socket,Http,Https)

 

 

SharedPreference

 

最基本的操作步骤

1、getSharedPreferences 先得到一个SharedPreference

2、get SharedPrenference.Editor

3、Editor.commit()

 

 

public class Calc extends Activity {
    public static final String PREFS_NAME = "MyPrefsFile";

    @Override
    protected void onCreate(Bundle state){
       super.onCreate(state);
       . . .

       // Restore preferences
       SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
       boolean silent = settings.getBoolean("silentMode", false);
       setSilent(silent);
    }

    @Override
    protected void onStop(){
       super.onStop();

      // We need an Editor object to make preference changes.
      // All objects are from android.context.Context
      SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
      SharedPreferences.Editor editor = settings.edit();
      editor.putBoolean("silentMode", mSilentMode);

      // Commit the edits!
      editor.commit();
    }
}


 

getSharedPreferences方法的:

第一个参数是名字

第二个参数是模式:0, MODE_APPEND,MODE_PRIVATE, MODE_READABLE, MODE_WRITABLE

 

MODE_APPEND 能够在之前的基础上进行数据的追加,追加根据key决定

MODE_PRIVATE, MODE_READABLE, MODE_WRITABLE 与xml的使用权限有关


 

edit()和commit()应当成对出现



获得SharedPreference的对象有三种方法:


1、getSharedPreferences(String name, int mode):这个方法第一个参数需要传入保存数据的xml的名字,可以创建多个

因为Activity继承了ContextWrapper,因此也是通过Activity对象获取,但是属于整个应用程序,可以有多个,

以第一参数的name为文件名保存在系统中


2、getPreferences(int mode):每个Activity只能创建一个,xml以Activity的名字来命名

通过Activity对象获取,获取的是本Activity私有的Preference,保存在系统中的xml形式的文件的名称为这个Activity的名字,

因此一个Activity只能有一个,属于这个Activity


3、PreferenceManager.getDefaultSharedPreference(Context context)

Preference的静态函数,保存PreferenceActivity中的设置,属于整个应用程序,但只有一个,

Android会根据包名和PreferenceAcitivity的布局文件来起一个名字保存




PreferenceActivity

是一个专门用于写settings的系统类,自动持久化数据,继承自ListActivity



可以建一个专门用于PreferenceActivity的layout



<PreferenceScreen
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:key="first_preferencescreen">
    <CheckBoxPreference
            android:key="wifi enabled"
            android:title="WiFi" />
    <PreferenceScreen
            android:key="second_preferencescreen"
            android:title="WiFi settings">
        <CheckBoxPreference
                android:key="prefer wifi"
                android:title="Prefer WiFi" />
        ... other preferences here ...
    </PreferenceScreen>
</PreferenceScreen> 



PreferenceScreen不是一个界面组件,而也是一个控制类,附加到Activity上


使用的时候Activity要继承PreferenceActivity类,绑定界面的时候用addPreferenceFromResource方法即可

还有一个addPreferenceFromIntent方法,可以通过设定Intent-filter调用系统的设置或者自定义的设置


想要打开系统相关的设置,在Settings中查找相关的Action,设置Intent,传入addPreferenceFromIntent中

或者直接在Preference中直接设置intent标签即可




如果想设置某一项的相关属性,我们发现findViewById的方法是行不通的,因为SharedSreen系列标签中不能指定id

但是有一个findPreference方法,传入的是SharedSreen系列标签中的key,返回的是一个Preference的对象

’‘



返回值为true则不再向下传递,系统也就不自动进行持久化的操作了,可以自行处理。





文件存储


内部存储


保存

String FILENAME = "hello_file";
String string = "hello world!";

FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos.write(string.getBytes());
fos.close();


If you want to save a static file in your application at compile time, save the file in your project res/raw/ directory. 

You can open it with openRawResource(), passing the R.raw.<filename> resource ID. 

This method returns an InputStream that you can use to read the file (but you cannot write to the original file).



外部存储


一些权限

<manifest ...>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    ...
</manifest>


根据是否MOUNT或者UNMOUNT返回外部文件是否可读可写

/* Checks if external storage is available for read and write */
public boolean isExternalStorageWritable() {
    String state = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED.equals(state)) {
        return true;
    }
    return false;
}

/* Checks if external storage is available to at least read */
public boolean isExternalStorageReadable() {
    String state = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED.equals(state) ||
        Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
        return true;
    }
    return false;
}










网络存储








最关键学会HttpClient或者HttpRequest类,都是J2SE中的内容


 

 


 

SQLite3

 

SQLite(Http://www.sqlite.org/),是一款轻型的数据库,是遵守ACID的关联式数据库管理系统,

它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,

在嵌入式设备中,可能只需要几百K的内存就够了

它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如Tcl,C#,PHP,Java等,

还有ODBC接口,同样比起MySQL、PostoreSQL这两款开源世界著名的数据库关系系统来讲,它的处理速度比它们都亏

SQLite第一个Alpha版本诞生于2000年5月,至今已经有10个年头,SQLite也迎来了一个版本SQLite3已经发布

 

特征:轻量级、独立性、隔离性、跨平台、多语言接口、安全性

 

 

与其他关系型数据库相比,是否支持:

1、标准SQL语句

2、视图

3、存储过程Process

4、主外键关系(7中)

5、事务

6、等等


 

一般数据库执行操作步骤:

1、建立数据库,建立表结构

2、建立数据库链接DB Connection

3、执行SQL语句

(1)executeSQL——一般执行的是没有返回值的SQL语句

(2)query——一般是给select用的,返回查询结果

4、如果有返回值,建立一个RecordSet或者Cursor,操作结果

5、关闭数据库链接

 

 

Android推荐我们使用继承SQLiteOpenHelper类进行数据库操作,在继承的类中的onCreate方法中可以执行sql语句

 

public class DBOpenHelper extends SQLiteOpenHelper {

    private final String DATABASE_NAME = "androidDBStorageSqlite";
    private final String TABLE_USER_NAME = "users";
    private final String TABLE_CUSTOMER_NAME = "customer";
    public final String COLUMN_USERNAME = "userName";
    public final String COLUMN_USERADDRESS = "userAddress";

    public DBOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        sqLiteDatabase.execSQL("create TABLE " + TABLE_USER_NAME + "(_id INTEGER PRIMARY KEY AUTOINCREMENT, " + COLUMN_USERNAME + " VARCHAR(50) NOT NULL," + COLUMN_USERADDRESS + " VARCHAR(50) NOT NULL)");
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
        if (oldVersion == 1 && newVersion == 2){
            sqLiteDatabase.execSQL("create TABLE " + TABLE_CUSTOMER_NAME + "(_id INTEGER PRIMARY KEY AUTOINCREMENT, " + COLUMN_USERNAME + " VARCHAR(50) NOT NULL," + COLUMN_USERADDRESS + " VARCHAR(50) NOT NULL)");
        }

        else if (oldVersion == 2 && newVersion == 1){
            sqLiteDatabase.execSQL("drop TABLE " + TABLE_CUSTOMER_NAME);
        }
    }


}


 


 

其实SQliteOpenHelper只是一个帮助类,封装了一些数据库操作而已,我们也可以自己实现一个这样的帮助类

SQLiteOpenHelper:A helper class to manage database creation and versio management 用于建立数据库和版本控制的帮助类

还有其他相关的helper类,自己研究

onCreate中参数传入的是SQliteDatabase类的对象,查看api可以知道这个类才是 操作数据库的主要的类

 

 

 

 

 

使用SQLiteOpenHelper

public class DBOpenHelper extends SQLiteOpenHelper {

    private final String DATABASE_NAME = "androidDBStorageSqlite";
    private final String TABLE_NAME = "users";
    public final String COLUMN_USERNAME = "userName";
    public final String COLUMN_USERADDRESS = "userAddress";

    public DBOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        sqLiteDatabase.execSQL("create TABLE " + TABLE_NAME + "(_id INTEGER PRIMARY KEY AUTOINCREMENT, " + COLUMN_USERNAME + " VARCHAR(50) NOT NULL," + COLUMN_USERADDRESS + " VARCHAR(50) NOT NULL)");
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {

    }


}


其实只是创建数据库和版本管理,可以使用getReadableDatabase或者getWritableDatabase返回SQLiteDatabase数据库而已

 

调用

DBOpenHelper dbOpenHelper = new DBOpenHelper(this, TABLE_NAME, null, VERSION);
dbOpenHelper.getWritableDatabase();


得到了返回的SQLiteDatabase对象就可以执行相关的增删改查的操作了

 

 

自定义的一个数据库操作类

public class DBOperation {

    private final String DATABASE_NAME = "androidDBStorageSqlite";
    private final String TABLE_NAME = "users";
    public final String COLUMN_USERNAME = "userName";
    public final String COLUMN_USERADDRESS = "userAddress";


    private Context mContext;
    private SQLiteDatabase mSqLiteDatabase;

    public DBOperation(Context context){
        mContext = context;
    }

    /**
     * 建立及打开数据库
     */
    public void openOrCreateDatabase()
    {
        // 建立链接
        mSqLiteDatabase = mContext.openOrCreateDatabase(DATABASE_NAME, mContext.MODE_PRIVATE, null);
        //SQLiteDatabase也有相关方法 mSqLiteDatabase = SQLiteDatabase.openOrCreateDatabase();

        // 建立表
        String firstTableName = mSqLiteDatabase.findEditTable(TABLE_NAME);
        if (firstTableName == null || firstTableName.equals("")){
            mSqLiteDatabase.execSQL("create TABLE " + TABLE_NAME + "(_id INTEGER PRIMARY KEY AUTOINCREMENT, " + COLUMN_USERNAME + " VARCHAR(50) NOT NULL," + COLUMN_USERADDRESS + " VARCHAR(50) NOT NULL)");
        } else{
            Log.i("error", "table exist");
        }
    }

    /**
     * 关闭数据库
     */
    public void closeDatabase(){
        // 关闭数据库链接
        mSqLiteDatabase.close();
        mSqLiteDatabase = null;
    }

    /**
     * 下面可以封装各种增删改查的方法
     */

    /**
     * 插入用户
     * @param user 用户实例
     * @return
     */
    public long insertUser(User user)
    {
        if (mSqLiteDatabase != null && user != null)
        {
            // 插入一条记录
            ContentValues contentValues = new ContentValues();
            contentValues.put(COLUMN_USERNAME, user.getUserName());
            contentValues.put(COLUMN_USERADDRESS, user.getUserAddress());
            // insert(java.lang.String table, java.lang.String nullColumnHack, android.content.ContentValues values)
            return mSqLiteDatabase.insert(TABLE_NAME, "", contentValues);
        }
        return -1;
    }

    public Cursor selectAll(String selection, String[] selectionArgs, String groupBy, String having, String orderBy)
    {
        if (mSqLiteDatabase != null)
        {
            return mSqLiteDatabase.query(TABLE_NAME, new String[]{"_id", COLUMN_USERNAME, COLUMN_USERADDRESS},
                    selection, selectionArgs, groupBy, having, orderBy);
        }
        return null;
    }
}


 

 

执行一些语句时,可以使用通配符

 

 

在adb shell中可以操作数据库

 

使用sqlite3 + 数据库名称即可进入数据库操作模式

 

系统命令都是以.开头的


 

 

 

 

还可以在google查询sqlite tool,使用例如Sqlite Developer,或者sqlitestudio的视图工具

 

 

 

总结:

1、SQLite是一个全面而又完整支持sql语句的文件型数据库

2、SQLite支持事务,视图,索引,触发器,主外键约束

3、默认的必须给每张表的主键名字为_id

4、SqliteDatabase可以用封装的insert,update,delete,query方法,也可以用execSql,rawSql等原生方法

 

 

 

 

Cursor的相关方法

 

 

 

思考:

SQLite3数据库引擎在哪儿?

 

如何在Android源码中找到类似于SQLite3的这种开源的源码

1、一般来讲,集成源代码比只调用.so文件更好

2、下载SQLite3的源码

3、通过SQLite3源码中的文件名到Android源码中找寻

这是一种思路

 

SQLite3的源文件只有四个

 

 

 

 

所以可以找到SQLite3数据库的引擎

 

在源码external的sqlite目录下

 

而external目录下还有许多其他的引擎

 

 

 

思考:

SQLite3链接方式实际是什么?

 

一定会调用到native方法,而且有相关驱动

 

封装好的驱动

之前的版本在libcore文件夹下

 

现在放到了external下javasqlite目录下

 

 

 

 

可以通过SQLite Studio等工具生成表,创建表,建立主外键链接,创建视图,创建触发器等

将数据库导出为.sql文件,可以选择直导出数据库结构,也可以同时导出数据库数据

将这些sql语句放入到程序交由SQLiteDatabase或SQLiteOpenHelper处理即可

 

 

 

 

 

事务:

要么都执行,要么都不执行

mSqliteDatabase.beginTransaction():开始事务

mSqliteDatabase.setTransactionSuccessful():事务成功

mSqliteDatabase.endTransaction():结束事务

在这两个方法之间放入执行事务的语句即可

一般把事务放在try - catch语句中,endTransaction放在finally语句中

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值