Android Studio第八课(SqLite数据库,Room框架,轮播图)


前言

作者介绍:友友们好我是乱披风锤,大二学生党一枚
作者主页:乱披风锤的个人博客主页.跳转到个人简介

我和友友们一样喜欢编辑,天天敲代码🤭,沉迷学习,日渐消瘦。很荣幸能向大家分享我的所学,和大家一起进步,成为合格的卷王。如果文章有错误,欢迎在评论区指正。那么开始今天的学习吧!
那么今天的学习就到这里了。友友们觉得不错的可以给个关注,点赞或者收藏哦!感谢各位友友们的支持。以下的代码希望各位大佬们自行检验哦,毕竟亲手操作让记忆更加深刻。


一、什么是SQLite

SQLite是一个进程内的轻量级嵌入式数据库,它的数据库就是一个文件,实现了自给自足、无服务器、零配置的、事务性的SQL数据库引擎。它是一个零配置的数据库,这就体现出来SQLite与其他数据库的最大的区别:SQLite不需要在系统中配置,直接可以使用。且SQLite不是一个独立的进程,可以按应用程序需求进行静态或动态连接。SQLite可直接访问其存储文件。

1.SQLite数据库实际操作

创建OpenSqlHelper类(用于加载驱动)
在这里插入图片描述

package com.example.hc5;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteTableLockedException;

import androidx.annotation.Nullable;

public class DBOpenHelper extends SQLiteOpenHelper {


    public DBOpenHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }
//创建表
    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
     String sql=   "create table user(id integer primary key autoincrement,username varchar(20),password varchar(20),age integer)";
sqLiteDatabase.execSQL(sql);
    }
//用于更新
    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {

    }
}


多次点击后实现的效果

二、Room框架

概念
搭建Room框架设计到的概念有以下几个:
1、Entity : 对应数据库中的表,可以使用Entity注解将一个类变成数据库中的一张表结构。
2、DAO : 全称Database Access Object,定义了对数据库中数据的读写等操作,DAO中可以使用SQL语句来操作数据库。
3、RoomDatabase : 数据库持有类,用于创建数据库或者连接到数据库。内部包含DAO和Entity。

1.需要做的准备

Entity
Room Database中的Entity表示一张数据表结构,一个Entity实例就是表中的一行,如定义一个Word类的Entity。
重点:
1、一个Entity对象代表数据表中的一行,一个Entity类代表一张数据表。
2、Entity中的成员变量都是数据表中的列。
3、一个Java类定义成Entity只要加上Entity注解就可以了。

@Entity
public class User1 {//实体类->数据库   ->省略创建表
    @PrimaryKey(autoGenerate = true)//代表自增长
    public  int id;
    public  String username;
    public  int age;
    public  String password;

}

建立一个接口UserDao

接口需要写增删改查方法,并在对应的位置标记了注解。

在添加注解的时候爆红,光标点击在对应的爆红的位置按住alt+enter即可选择导入依赖

在DAO(data access object)中,可以使用SQL语句进行对数据库的操作并且将这些语句与Java中方法关联调用,编译器会检查SQL语句并且通过注解生成对应的查询语句,例如@Update。
注意:
1、DAO必现是抽象类或者接口
2、所有的查询语句必须在单独的线程里面执行。

package com.example.hc5;

import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.Query;
import androidx.room.Update;

import java.util.List;

//Dao名字结尾类 一般是操作数据库方法
@Dao
public interface  UserDao{

    @Insert//增
    void inserUser(User1 user1);
@Delete//删
void  deleteUser(User1 user1);
@Update//改
void  update(User1 user1);

    @Query("SELECT * FROM User1")
    List<User1> getallUser() ;
//查
@Query("SELECT * FROM User1 where id= :userId")
List<User1> getallUserByID(int userId);

    @Query("SELECT * FROM User1 where username like  '%'||:username||'%'")
   List<User1> getallUserByName(String username) ;


}


抽象类UserDatabase

package com.example.hc5;
import androidx.room.Database;
import androidx.room.RoomDatabase;
@Database(entities = {User1.class}, version = 1, exportSchema = false)
public abstract class UserDatabase extends RoomDatabase {
    public abstract UserDao getUserDao();
}

2.在主界面进行增删改查

首先布局按钮控件

 <Button
        android:id="@+id/button"
        android:layout_width="109dp"
        android:layout_height="38dp"
        android:layout_marginEnd="240dp"
        android:text="添加数据"
        app:layout_constraintBottom_toBottomOf="@+id/textView"
        app:layout_constraintEnd_toEndOf="parent"
        tools:ignore="MissingConstraints" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="392dp"
        android:text="删除按钮"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.895"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:ignore="MissingConstraints" />

    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="232dp"
        android:text="更新按钮"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.511"
        app:layout_constraintStart_toStartOf="parent"
        tools:ignore="MissingConstraints" />

    <Button
        android:id="@+id/button4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="116dp"
        android:text="查询"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.52"
        app:layout_constraintStart_toStartOf="parent"
        tools:ignore="MissingConstraints" />

MainActivity 下的增删改查操作实现代码

 findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                User1 user1 = new User1();
                user1.username = "test1234";
                user1.password = "123456";
                user1.age = 20;

                userDao.inserUser(user1);
            }
        });
        findViewById(R.id.button3).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                User1 user1 = new User1();
                user1.username = "test1234";
                user1.password = "123456";
                user1.age = 20;
                user1.id = 2;
                userDao.update(user1);
            }
        });
        findViewById(R.id.button4).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                List<User1> user1List = userDao.getallUserByName("test");
                for (User1 user1 : user1List) {
                    Log.i("User1", "name" + user1.username + "password=" + user1.password + "id=" + user1.id);
                }
            }
        });
        findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                User1 user1 = new User1();
                user1.id = 1;
                user1.username = "test1234";
                user1.password = "123456";
                user1.age = 20;
                //对象操作  省略sql语句->映射到数据库对于数据的操作
                userDao.deleteUser(user1);

三、实现轮播图

1.导入依赖

首先我们要在build.gradle下导入所需要的依赖,我会把代码发在下面,我们直接拿来用就可以了.依赖包如下:

   implementation 'io.github.youth5201314:banner:2.2.2'
   implementation 'com.github.bumptech.glide:glide:4.13.0'
   annotationProcessor 'com.github.bumptech.glide:compiler:4.13.0'

2.主页面修改布局界面,加入以下布局

<com.youth.banner.Banner
   android:id="@+id/banner"
   android:layout_width="match_parent"
   android:layout_height="200dp"
   app:layout_constraintEnd_toEndOf="parent"
   app:layout_constraintTop_toTopOf="parent"
   app:layout_constraintStart_toStartOf="parent"
   />

3.主页面java文件添加图片

public class MainActivity extends AppCompatActivity {
   //声明控件
   UserDatabase userDatabase;
   UserDao userDao;
   Banner banner;
   List<String> bannerList = new ArrayList<>();

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);

       banner = findViewById(R.id.banner);
       //添加图片
       bannerList.add("https://s.cn.bing.net/th?id=OIP-C.rHuc8SKa0wLVwCqqA27uIwHaEt&w=313&h=199&c=8&rs=1&qlt=90&o=6&dpr=1.25&pid=3.1&rm=2");
       bannerList.add("https://s.cn.bing.net/th?id=OIP-C.io4VXXysHbv5SM257I-isQHaEo&w=316&h=197&c=8&rs=1&qlt=90&o=6&dpr=1.25&pid=3.1&rm=2");
       bannerList.add("https://s.cn.bing.net/th?id=OIP-C.Zxtf2X2EddV-g7hKyBhilAHaQB&w=161&h=350&c=8&rs=1&qlt=90&o=6&dpr=1.25&pid=3.1&rm=2");
       banner.setAdapter(new BannerImageAdapter<String>(bannerList) {
           @Override
           public void onBindView(BannerImageHolder holder, String data, int position, int size) {
               Glide.with(holder.imageView)
                       .load(data).into(holder.imageView);
           }

       });
       banner.setIndicator(new CircleIndicator(this));
       banner.setIndicatorRadius(50);


下面是我实现的轮播图效果,图片都是从网上找到,小伙伴们也可以替换自己喜欢的图片实现效果

<think>好的,我现在需要解决用户在Vue中组件未正确更新的问题,尤其是在点击“复制”按钮后弹窗内容没有及时显示,而是延迟加载的情况。用户提到希望通过修改key值或其他方法强制重渲染子组件。让我先理清楚可能的原因和解决方案。 首先,根据用户提供的引用内容,特别是引用[1]中的例子,他们之前通过设置key为时间戳来强制子组件刷新。这似乎是一个有效的方法,因为Vue的响应式系统在key改变时会重新创建组件实例。不过用户现在遇到了类似的问题,可能需要同样的方法,但需要确认是否正确应用。 然后,引用[2]提到Vue的异步更新队列,可能导致状态变化不会立即触发DOM更新。如果在同一个事件循环中多次修改状态,Vue可能只会处理最后一次的变更。这可能意味着用户在点击“复制”按钮后,某些状态没有被及时更新,导致弹窗内容没有正确显示。 接下来,我需要考虑可能的解决方案。除了修改key值之外,还有其他方法可以强制组件重新渲染,比如使用this.$forceUpdate()或者改变组件的某个prop。但修改key值通常是推荐的方法,因为它更直接地触发组件的销毁和重新创建,确保状态完全重置。 用户的问题具体是在点击“复制”按钮时弹窗内容没有正确显示。可能的情况是,弹窗组件依赖于某些数据,而这些数据在按钮点击后没有及时触发更新。例如,可能在打开弹窗时,数据还未被正确赋值,或者由于Vue的异步更新机制,DOM没有及时渲染。 我需要检查用户可能的代码结构。假设弹窗组件是一个子组件,当点击“复制”按钮时,父组件会修改某些数据,然后显示弹窗。如果弹窗的内容依赖于这些数据,但数据的变化没有被及时检测到,或者弹窗组件没有重新渲染,就会导致内容显示不正确。 根据引用[1]中的例子,用户之前通过给子组件设置:key="timer",并在打开弹窗时更新timer的值,从而强制子组件重新渲染。同样的方法可能适用于当前的问题。即在点击“复制”按钮时,更新key的值,确保子组件每次打开时都重新创建,而不是复用之前的实例。 另外,需要注意在关闭弹窗时,是否正确地重置了相关的数据和key的值。例如,在弹窗关闭事件中,将timer置为null或新的时间戳,以确保下次打开时key值不同,触发重新渲染。 还有可能涉及到Vue的响应式数据更新问题。如果用户的数据结构较为复杂,或者使用了嵌套对象,Vue可能无法检测到数据的变化。这时候可能需要使用Vue.set或this.$set来确保属性的响应式更新。 此外,引用[3]中提到的主进程和渲染进程之间的通信机制,可能不直接相关,但如果用户的应用涉及Electron或其他类似框架,可能需要考虑跨进程通信对状态更新的影响,不过用户当前的问题集中在Vue组件本身,暂时可以排除这方面的因素。 总结可能的解决步骤: 1. 在弹窗子组件上使用:key属性,并将其绑定到一个响应式的变量(如timer)。 2. 在点击“复制”按钮时,更新timer的值,通常使用时间戳,确保每次点击时key值不同。 3. 在弹窗关闭时,重置timer或其他相关状态,确保下次打开时能再次触发更新。 4. 检查数据更新的时机,确保在打开弹窗前数据已经正确赋值,可能需要使用this.$nextTick来确保DOM更新。 需要验证用户是否正确地应用了这些步骤。例如,是否在点击按钮时更新了key的值,是否在关闭时重置,是否有其他因素导致数据未及时更新。 另外,如果用户的数据更新存在异步操作,比如从API获取数据,可能需要确保在数据加载完成后再打开弹窗,或者使用v-if指令控制弹窗的显示,结合key的变化来强制重渲染。 最后,还要考虑是否有其他优化手段,比如使用计算属性或侦听器来响应数据变化,但关键点还是通过修改key来强制组件重新渲染,确保内容正确显示。</think>在Vue中强制子组件重渲染的解决方案如下: ### 一、通过修改key值强制重渲染 1. **绑定动态key属性** 在弹窗子组件上绑定`:key`属性,值为响应式变量: ```vue <codemirror-editor ref="editor" :key="componentKey" v-model="content" ></codemirror-editor> ``` 2. **点击操作时更新key值** 在"复制"按钮事件中修改key值触发重建: ```javascript handleCopy() { this.componentKey = new Date().getTime(); // 时间戳更新key this.showModal = true; // 显示弹窗 } ``` 3. **关闭弹窗时重置状态** 弹窗关闭时清空关键数据: ```javascript closeModal() { this.componentKey = null; // 可选重置操作 this.content = ''; this.showModal = false; } ``` ### 二、其他辅助优化方法 1. **使用$nextTick确保DOM更新** 在异步操作后强制更新: ```javascript this.$nextTick(() => { this.componentKey = new Date().getTime(); }); ``` 2. **通过v-if控制生命周期** 结合`v-if`与`key`双重保障: ```vue <codemirror-editor v-if="showModal" :key="componentKey" ></codemirror-editor> ``` 3. **使用Vue.set处理深层次对象** 当数据层级较深时: ```javascript Vue.set(this.dataObj, 'nestedProp', newValue); ``` ### 三、原理说明 Vue通过虚拟DOM的diff算法判断组件是否需要更新。当`key`值改变时,会销毁旧组件实例并创建新实例,达到强制重渲染的目的[^1]。这种方法比`$forceUpdate()`更彻底,后者仅触发重新渲染但不重置组件状态[^2]。
评论 30
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

进击攻城狮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值