安卓基礎筆記2之SQLit數據庫

  • 知識點

    1. SQLit數據庫(安卓自帶的)

      • 常見數據庫
      • 創建一個工具類
      • 純sql方式操作數據庫
        • 添加
        • 刪除
        • 更新
        • 查詢
      • 面向對象的方式操作數據庫
        • 添加
        • 刪除
        • 更新
        • 查詢
    2. ListView(安卓核心控件)

  • ListView(理解)
  • ListView入門
  • ListView優化
  • 複雜的ListView

具體細節以及案例
  • ##### 常見數據庫
    • Oracle:大型的數據庫 ,性能最高
    • Mysql:小型數據庫 開源的 免費的
    • DB2:大型數據庫,收費
    • Sqlite:微型,免費,美國軍艦(Android自帶)

  • ###### 創建一個工具類繼承SQLiteOpenHelper
  • 要明白的:

    • -構造方法裏傳的三個參數分別是什麼意思 作用是什麼?

      • 參數1:Context 上下文環境
      • 參數2:name 數據庫文件的名稱(xxx.db)
      • 參數3:factory 遊標工廠,傳入null使用系統默認的遊標(可以理解爲指向數據庫中數據的指針)
      • 參數4:version 數據庫版本,==必須大於1==

        • 作用:給創建的子類對象設置好數據庫名字以及版本號
    • 明白OnCreate()方法什麼時候使用,使用的特點是什麼

      • ==當第一次創建數據庫的時候調用==
      • 特點: 由系統調用,且只會調用一次
  • 思路:

    • 在==onCrate方法==裏創建表
      • 創建表的SQL語句:
      • ==create table 數據表名(_id integer primary key,列名2 數據類型 約束,列名3 數據類型 約束);==
      • SQLite的主鍵會自動自增,不需要加auto_increment
    • 在==onUpgrade==方法內升級數據庫
    • 修改表
      • ==alter table t_user add c_money float==
  • 代碼

@Override
    public void onCreate(SQLiteDatabase db) {
//      創建表結構
        String sql = "create table t_user (_id integer primary key,t_name varchar(20),t_age integer ,t_gender varchar(20))";
        db.execSQL(sql);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        String sql = "alter table t_user add c_money float";
        db.execSQL(sql);
    }

  • ###### 使用SQLiteOpenHelper創建數據庫文件
  • 思路

    • 先寫UI,創建一個按鈕,點擊按鈕觸發創建數據庫事件
    • 創建工具類的對象(有參數的構造)

      • MySQLiteOpenHelper mySQLiteOpenHelper = new MySQLiteOpenHelper(this, DB_NAME, null, VERSION);
    • 通過.getReadableDatabase()或.getWriteableDatabase()來獲取數據庫

      • SQLiteDatabase database = mySQLiteOpenHelper.getWritableDatabase();
    • 調用.close() 釋放資源
// 創建數據庫
    public void create(View view) {
        // 創建工具類的對象
        MySQLiteOpenHelper mySQLiteOpenHelper = new MySQLiteOpenHelper(this,
                DB_NAME, null, VERSION);
        // 通過.getReadableDatabase()來獲取數據庫
        SQLiteDatabase database = mySQLiteOpenHelper.getReadableDatabase();
        // 釋放資源
        database.close();
        Toast.makeText(this, "創建數據庫成功", Toast.LENGTH_SHORT).show();
    }

  • #### 純sql方式操作數據庫
  • 思路

    • 添加,刪除,更新都是調用execSQL(sql,Object[]{})方法,只是sql語句不一樣

      • 先寫UI,創建一個按鈕,點擊按鈕觸發添加數據事件

      • 獲取操作的數據庫

        • ==MySQLiteOpenHelper mySQLiteOpenHelper = new MySQLiteOpenHelper(this, DB_NAME, null, VERSION);==
        • ==SQLiteDatabase database = mySQLiteOpenHelper.getWritableDatabase();==
      • 用一個字符串接收添加數據的sql語句,一般會使用佔位符的格式
      • 調用的是 ==execSQL(sql,Object[]{})== 方法
      • 釋放資源
    • 查詢
      • 先寫UI,創建一個按鈕,點擊按鈕觸發添加數據事件
      • 獲取操作的數據庫(跟添加,刪除,更新一樣)
      • 用一個字符串接收添加數據的sql語句,一般會使用佔位符的格式
      • 調用 ==rewQuery(sql,String[]{})== 方法,返回值是Cursor 結果集
        • 判斷結果集裏是否存在下一個符合條件數據,調用 ==moveToNext()== 方法,用while循環來遍歷出要查詢的數據
        • 如果存在,通過字段索引,獲取字段的內容,調用 ==getXxx()== 方法獲取,索引從0開始
        • ==注意:通過索引獲取時,是根據你查詢的結果爲準==
      • 釋放資源
// 添加數據
    public void insert(View view) {
        // 獲取操作的數據庫
        MySQLiteOpenHelper mySQLiteOpenHelper = new MySQLiteOpenHelper(this,
                DB_NAME, null, VERSION);
        SQLiteDatabase database = mySQLiteOpenHelper.getWritableDatabase();
        // 用一個字符串接收添加數據的sql語句,一般會使用佔位符的格式
        String sql = "insert into t_user (t_name,t_age,t_gender) values(?,?,?)";
        database.execSQL(sql, new Object[] { "王莉莉" + new Random().nextInt(100),
                new Random().nextInt(108), "" + new Random().nextInt(2) });
        // 釋放資源
        database.close();
        Toast.makeText(this, "1成功", Toast.LENGTH_SHORT).show();

    }

    // 刪除數據
    public void delete(View view) {
        // 獲取操作的數據庫
        MySQLiteOpenHelper mySQLiteOpenHelper = new MySQLiteOpenHelper(this,
                DB_NAME, null, VERSION);
        SQLiteDatabase database = mySQLiteOpenHelper.getWritableDatabase();
        // 用一個字符串接收添加數據的sql語句,一般會使用佔位符的格式
        String sql = "delete t_user where t_age>?";
        database.execSQL(sql, new Object[] { "60" });
        // 釋放資源
        database.close();
        Toast.makeText(this, "2成功", Toast.LENGTH_SHORT).show();
    }

    // 更新數據
    public void update(View view) {
        // 獲取操作的數據庫
        MySQLiteOpenHelper mySQLiteOpenHelper = new MySQLiteOpenHelper(this,
                DB_NAME, null, VERSION);
        SQLiteDatabase database = mySQLiteOpenHelper.getWritableDatabase();
        // 用一個字符串接收添加數據的sql語句,一般會使用佔位符的格式
        String sql = "update t_user set t_name=? where t_age<?";
        database.execSQL(sql, new Object[] { "王麗麗", 20 });
        // 釋放資源
        database.close();
        Toast.makeText(this, "3成功", Toast.LENGTH_SHORT).show();
    }

    // 查詢數據
    public void select(View view) {
        // 獲取操作的數據庫
        MySQLiteOpenHelper mySQLiteOpenHelper = new MySQLiteOpenHelper(this,
                DB_NAME, null, VERSION);
        SQLiteDatabase database = mySQLiteOpenHelper.getWritableDatabase();
        // 用一個字符串接收添加數據的sql語句,一般會使用佔位符的格式
        String sql = "select * from t_user where t_age>?";
        // 調用 rawQuery() 方法進行查詢,第二個參數是string數組,返回的是一個Cursor 結果集
        Cursor cursor = database.rawQuery(sql, new String[] { "50" });
        // 判斷結果集裏是否存在下一個符合條件數據,調用moveToNext()方法,用while循環來遍歷出要查詢的數據
        List<User> list = new ArrayList<User>();
        while (cursor.moveToNext()) {
            // 如果存在,通過字段索引,獲取字段的內容,調用getXxx()方法獲取,索引從0開始
            // 注意:通過索引獲取時,是根據你查詢的結果爲準
            String name = cursor.getString(0);
            int age = cursor.getInt(1);
            String gender = cursor.getString(2);

            User user = new User();
            user.name = name;
            user.age = age;
            user.gender = gender;
            list.add(user);
        }
        Log.w("tag", list.toString());
        textView.setText(list.toString());

        // 釋放資源
        database.close();
        Toast.makeText(this, "5成功", Toast.LENGTH_SHORT).show();

    }

  • #### 面向對象的方式操作數據庫
  • 思路:
    • 添加數據
      • 先寫UI,創建一個按鈕,點擊按鈕觸發添加數據事件
      • 獲取操作的數據庫
      • 調用 ==insert()== 方法
        • 參數1:表名
        • 參數2:一般是null
        • 參數3是一個ContenValues對象,這個類封裝的是一個Map數組
          • 調用put(key,values)方法,添加數據
      • 返回值是插入的行數,==long== 類型的,如果插入爲0,返回-1
    • -
// 添加數據
    public void insert(View v) {
        // 獲取工具類的對象
        MeSQLiteOpenHelper meSQLiteOpenHelper = new MeSQLiteOpenHelper(this,
                DB_USER, null, VERSION);
        // 通過.getReadableDatabase()創建數據庫
        SQLiteDatabase database = meSQLiteOpenHelper.getReadableDatabase();

        // 調用insert方法,參數3是一個ContenValues對象,這個類封裝的是一個Map數組
        // insert 返回值是插入的行數,long類型的
        ContentValues values = new ContentValues();
        values.put("t_name", "王麗麗" + new Random().nextInt(20));
        values.put("t_age", 20 + new Random().nextInt(10));
        values.put("t_gender", "" + new Random().nextInt(2));
        long len = database.insert("s_user", null, values);
        database.close();

        Toast.makeText(this, "在" + len + "插入了數據", Toast.LENGTH_SHORT).show();
    }
  • 刪除數據
    • 先寫UI,創建一個按鈕,點擊按鈕觸發添加數據事件
    • 獲取操作的數據庫
    • 調用 ==delete()== 方法
      • 參數1:表名
      • 參數2放的是where條件
      • 參數3是參數2裏面?的真實值
    • 返回值是受影響的行數,返回類型 ==int==
    • 釋放資源
    • -
    // 獲取工具類的對象
        MeSQLiteOpenHelper meSQLiteOpenHelper = new MeSQLiteOpenHelper(this,
                DB_USER, null, VERSION);
        // 通過.getReadableDatabase()創建數據庫
        SQLiteDatabase database = meSQLiteOpenHelper.getReadableDatabase();
        // 調用delete()方法,參數2放的是where條件,參數3是參數2裏面?的真實值,返回值是受影響的行數,返回類型int
        int len = database.delete("s_user", "t_age>?", new String[] { "20" });
        database.close();
        Toast.makeText(this, len + "受影響", Toast.LENGTH_SHORT).show();
    }
  • 更新數據
    • 先寫UI,創建一個按鈕,點擊按鈕觸發添加數據事件
    • 獲取操作的數據庫
    • 調用 ==update()== 方法
      • 參數1:表名
      • 參數2是一個ContenValues對象,這個類封裝的是一個Map數組
        • 調用put(key,values)方法,添加數據
      • 參數3放的是where條件
      • 參數4是參數3裏面?的真實值
    • 返回值是受影響的行數,返回類型 ==int==
    • 釋放資源
      -
// 更新
    public void update(View view) {
        // 獲取工具類的對象
        MeSQLiteOpenHelper meSQLiteOpenHelper = new MeSQLiteOpenHelper(this,
                DB_USER, null, VERSION);
        // 通過.getReadableDatabase()創建數據庫
        SQLiteDatabase database = meSQLiteOpenHelper.getReadableDatabase();
        // 調用update()方法,參數2是一個ContenValues對象,這個類封裝的是一個Map數組,參數3放的是where條件,參數4是參數2裏面?的真實值,返回值是受影響的行數,返回類型int
        ContentValues values = new ContentValues();
        values.put("t_money", "1000");
        int len = database.update("s_user", values, "t_age>?",
                new String[] { "19" });
        database.close();

        Toast.makeText(this, len + "受影響", Toast.LENGTH_SHORT).show();
    }
  • 查詢數據
    • 先寫UI,創建一個按鈕,點擊按鈕觸發添加數據事件
    • 獲取操作的數據庫
    • 調用 ==query()== 方法
      • 參數1:表名
      • 參數2:要查詢的字段,放到字符串數組中
      • 參數3放的是where條件
      • 參數4是參數3裏面?的真實值
      • 參數5:null
      • 參數6:null
      • 參數7:排序表達式
    • 返回值返回值是 Cursor 結果集
      • 判斷結果集裏是否存在下一個符合條件數據,調用 ==moveToNext()== 方法,用while循環來遍歷出要查詢的數據
      • 如果存在,通過字段索引,獲取字段的內容,調用 ==getXxx()== 方法獲取,索引從0開始
      • ==注意:通過索引獲取時,是根據你查詢的結果爲準==
    • 釋放資源
    • -
public void select(View view) {
        // 獲取工具類的對象
        MeSQLiteOpenHelper meSQLiteOpenHelper = new MeSQLiteOpenHelper(this,
                DB_USER, null, VERSION);
        // 通過.getReadableDatabase()創建數據庫
        SQLiteDatabase database = meSQLiteOpenHelper.getReadableDatabase();
        // 調用了query()方法 參數2:要查詢的字段,放到字符串數組中
        //  參數3:就是where表達式
        //  參數4:用於替換參數3中?號的真實的值,String[]數組中形式
        // 參數5:null
        // 參數6:null
        //  參數7:排序表達式
        // 返回類型是一個Cursor對象,結果集

        Cursor cursor = database.query("s_user", new String[] { "*" },
                "t_age>?", new String[] { "20" }, null, null, "t_age");
        List<User> list = new ArrayList<User>();
        while (cursor.moveToNext()) {
            String name = cursor.getString(1);
            int age = cursor.getInt(2);
            String gender = cursor.getString(3);
            User user = new User();
            user.name = name;
            user.age = age;
            user.gender = gender;
            list.add(user);
        }
        database.close();
        Toast.makeText(this, list.toString(), Toast.LENGTH_SHORT).show();
    }

  • ##### 數據庫升級
  • 思路:
    • 更新數據庫:
      • ==注意,只能升版本,不能降版本==
    • 先寫UI,創建一個按鈕,點擊按鈕觸發添加數據事件
    • 獲取操作的數據庫
    • 設置版本號,必須大於上一個版本號
    • 釋放資源
// 更新數據庫
    public void shengji(View view) {
        // 更新數據庫:注意,只能升版本,不能降版本
        // 獲取工具類的對象
        MeSQLiteOpenHelper meSQLiteOpenHelper = new MeSQLiteOpenHelper(this,
                DB_USER, null, VERSION);
        // 通過.getReadableDatabase()創建數據庫
        SQLiteDatabase database = meSQLiteOpenHelper.getReadableDatabase();
        database.close();
        Toast.makeText(this, "升級成功", Toast.LENGTH_SHORT).show();
    }
  • ###### 數據庫事物(模擬轉賬)
  • 對事物的理解:
  • 同時執行的多個數據庫操作,要麼同時成功,要麼同時失敗,不能出現一個成功一個失敗的情況,==事物就是爲了確保安全性的==
  • 思路:
    • 先寫UI,創建一個按鈕,點擊按鈕觸發添加數據事件
    • 獲取操作的數據庫
    • 開啓事物,調用了 ==beginTransaction()== ;方法
    • 提交事物, ==setTransactionSuccessful()==
    • 關閉事務, ==endTransaction()==

- 釋放資源

// 開啓事物
    public void change(View view) {
        // 獲取工具類的對象
        MeSQLiteOpenHelper meSQLiteOpenHelper = new MeSQLiteOpenHelper(this,
                DB_USER, null, VERSION);
        // 通過.getReadableDatabase()創建數據庫
        SQLiteDatabase database = meSQLiteOpenHelper.getReadableDatabase();
        // 更新表中數據,進行模擬轉賬操作!

        // 開啓事物,之後的代碼都是在臨時內存中執行的,並未真正的寫入到數據庫文件中
        database.beginTransaction();

        String sql = "update s_user set t_money = t_money-500 where t_name=?";
        database.execSQL(sql, new Object[] { "jjjj" });

        String sql2 = "update s_user set t_money = t_money+500 where t_name=?";
        database.execSQL(sql2, new Object[] { "王麗麗" });
        // 提交事物,事物只有提交了纔會寫到數據庫中
        database.setTransactionSuccessful();
        // 使用完後關閉事務功能
        database.endTransaction();
        database.close();

        Toast.makeText(this, "轉賬成功", Toast.LENGTH_SHORT).show();
    }

  • ###### ListView(理解)
    • 對ListView的理解:
      • ListView是一個可以放很多條目的控件,可以滑動,可以顯示一個數據集,如果數據超出屏幕可以上下滑動
      • ==注意,ListView的寬高必須設置爲match_parent,不能使用wrap_content。只有加了id才能在佈局中看到示例頁面==
      • 使用ListView一般都會使用適配器Adapter,在適配器一般會用Adapter的子類BaseAdapter
        • ==getCount()==:ListView一共有多少個條目
        • ==getView()==:設置每一個條目數據,==最後一定要返回對象==
          • ==注意:界面上顯示多少個條目該方法就調用多少次,之後滾出來一個條目就調用一次==。
          • ==public View getView(int position, View convertView, ViewGroup parent)==
          • 有三個參數
          • 參數一:int position,放的是索引,跟集合的索引是一樣的
          • 參數二:View convertView 一個可以複用的view控件
          • 參數三:一般是null
        • getItem():返回每個條目的對象
        • getItemId():返回當前條目位置。

- 如果是操作是一個TextView,可以用 ==ArrayAdapter== ,這個類底層就已經實現好了,只需要用就行

  • ###### ListView入門
  • 思路:

    • 在main xml中創建一個ListViewko 控件
    • 在MainActivity寫業務邏輯
      • 創建一個成員集合,來存放數據
      • 初始化ListView
      • 設置快速滑動 調用 .setsetFastScrollEnabled(true);
      • 設置適配器調用setAdapter()
      • 參數傳的一個Adapter一個子類BaseAdapter對象,
      • 創建一個類去繼承BaseAdapter,重寫BaseAdapter的方法
        • 在getCount()方法裏獲取總共的條目
        • 在getView裏創建一個textView(可以直接new一個)
        • 定義一個字符串根據索引獲取集合裏的內容
        • 調用 .setText()給TextView賦值
  • ListView優化
  • 爲了防止內存溢出

- 在getView()方法裏複用convertView

     view view=null;
     if(convertView==null){
     view = View.inflate(MainActivity.this, R.layout.listview_my, null);//創建view時,調用inflate()方法,獲取id時是獲取view存在的xml中的xml名字:R.layout.listview_my
     }else {
        view = convertView;
    }

- ###### 複雜的ListView
- 思路:
- 先在main xml 創建一個ListView 控件
- 自己定義一個 xml 放的是存在ListView裏面的佈局
- 在MainActivity裏面寫業務邏輯
- 創建一個成員集合,來存放數據
- 初始化ListView
- 設置快速滑動 調用 ==.setsetFastScrollEnabled(true);==
- 設置適配器調用==setAdapter()==
- 參數傳的一個Adapter一個子類BaseAdapter對象,
- 創建一個類去繼承==BaseAdapter==,重寫BaseAdapter的方法
- 在 ==getCount()== 方法裏獲取總共的條目
- 要用ListView優化->>>(上一個優化代碼)
- 在getView裏創建一個View
- 獲取view資源

            ```
            ImageView imageView = (ImageView) view.findViewById(R.id.image);
            TextView name = (TextView) view.findViewById(R.id.name);
            TextView ageTextView = (TextView) view.findViewById(R.id.age);
            TextView genderTextView = (TextView) view.findViewById(R.id.gender);
            ```
        - **注意:獲取View資源一定要調用==View的findViewById==(R.id.image)**  
        - 調用  ==.setText()== 給TextView賦值  

            ```
            name.setText(user.name);  
            ageTextView.setText(user.age+"");  
            genderTextView.setText(user.gender);
            ```
        - 給條目添加圖片

- 具體代碼

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 初始化listview
        listView = (ListView) findViewById(R.id.contects);

        for (int i = 0; i < 100; i++) {
            User user = new User();
            user.name = "khk"+i;
            user.age = i;
            user.gender = "女"+i;
            alist.add(user);
        }
//      設置滑動加速器
        listView.setFastScrollEnabled(true);
//      添加適配器
        listView.setAdapter(new BaseAdapter() {

            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
//              獲取view對象
                View view =null;
                if (convertView==null) {
                    view = View.inflate(MainActivity.this, R.layout.listview_my, null);
                }else {
                    view = convertView;
                }
//              根據索引獲取數據
                User user = alist.get(position);
//              獲取view資源
                ImageView imageView = (ImageView) view.findViewById(R.id.image);
                TextView name = (TextView) view.findViewById(R.id.name);
                TextView ageTextView = (TextView) view.findViewById(R.id.age);
                TextView genderTextView = (TextView) view.findViewById(R.id.gender);

                name.setText(user.name);
                ageTextView.setText(user.age+"");
                genderTextView.setText(user.gender);

//              給條目添加圖片
                switch (position%10) {
                case 0:
                    imageView.setImageResource(R.drawable.iv0);
                    break;
                case 1:
                    imageView.setImageResource(R.drawable.iv1);
                    break;
                case 2:
                    imageView.setImageResource(R.drawable.iv2);
                    break;
                case 3:
                    imageView.setImageResource(R.drawable.iv3);
                    break;
                case 4:
                    imageView.setImageResource(R.drawable.iv4);
                    break;
                case 5:
                    imageView.setImageResource(R.drawable.iv5);
                    break;
                case 6:
                    imageView.setImageResource(R.drawable.iv6);
                    break;
                case 7:
                    imageView.setImageResource(R.drawable.iv7);
                    break;
                case 8:
                    imageView.setImageResource(R.drawable.iv8);
                    break;
                case 9:
                    imageView.setImageResource(R.drawable.iv9);
                    break;

                default:
                    break;
                }
                return view;
            }


            @Override
            public int getCount() {
//              獲取條目的個數
                return alist.size();
            }
            @Override
            public long getItemId(int position) {

                return 0;
            }

            @Override
            public Object getItem(int position) {

                return null;
            }
        });

    }
- 計時器:
  • 步驟:

    1. 在LinearLayout定義一個button和一個ListView控件
      • 先分配button的空間,把ListView的高度設置match…
      • 也可以設置權重
    2. 獲取ListView和button
    3. 點擊按鈕獲取當前時間

      • 調用SimpleDataFormat裏面format()方法

        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String timeString = format.format(new Date());
        timeList.add(timeString);
    4. 定義一個集合接收時間字符串

    5. Adapter裏有一個方法:notifyDataSetChange() ==讓arraylistview(ListView)更新一下數據,重新調用Adapter的getCount和getview();==
    6. //list集合有一個add(adaption,String)讓添加的數據加載第一條list.add(0,要添加的數據);
    7. 讓ListView滾動到最後一個條目
      • 方法一.
        • 平滑 調用 ==smoothScrollToPosition(一般是放的最後一個條目的索引)== 方法
      • 方法二.
      • 不平滑 讓ListView定位定位到哪個條目 調用 ==setSelection()==;

感受和問題

今天主要學了SQLite 和ListView控件 數據庫存儲數據的兩種方式,出現了大量的新方法,雖然操作數據時很多都是相似的,但是大部分都是需要記得東西,感覺一下子接受這些東西有些吃力,可能手速還是跟不上,練習的時間總感覺不夠用.
在練習的時候總會因爲一些粗心犯了一些很低級的錯誤,在使用這些方法時容易記混裏面參數的意思,在學習ListView時,感覺吃力很多,新單詞有些多,容易記混使用方法

經過這些天的學習,明白了就業班和基礎班的區別,相比之下在基礎班節奏還是慢的,明白了不能拿在基礎班的態度,對待就業班,努力的去改善自己的學習方法和節奏,也慢慢的去適應就業班,跟着節奏一點一點的往前跟,希望自己不要掉隊,加油!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章