安卓基础笔记2之SQLit数据库

本文详细介绍SQLite数据库的基础操作,包括创建、读写、升级等,并深入探讨Android中ListView控件的使用方法,涵盖基本使用、优化及复杂场景的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 知识点

    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时,感觉吃力很多,新单词有些多,容易记混使用方法

经过这些天的学习,明白了就业班和基础班的区别,相比之下在基础班节奏还是慢的,明白了不能拿在基础班的态度,对待就业班,努力的去改善自己的学习方法和节奏,也慢慢的去适应就业班,跟着节奏一点一点的往前跟,希望自己不要掉队,加油!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值