当前位置: 首页 > news >正文

Android——数据存储(二)(二十二)

1. SQLite数据库存储

1.1 知识点

(1)了解SQLite数据库的基本作用;

(2)掌握数据库操作辅助类:SQLiteDatabase的使用;

(3)可以使用命令操作SQLite数据库;

(4)可以完成数据库的CRUD操作;

(5)掌握数据库查询及Cursor接口的使用。

1.2 具体内容

在Android当中,本身提供了一种微型的嵌入式数据库叫做SQLite,同样可以执行SQL语句,对于不熟悉sql和jdbc的小伙伴,还是需要去自学一下。

下面我们首先使用一段代码演示如何取得数据库表操作。

package com.example.sqliteopenhelper;import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;public class MySQLiteOpenHelper extends SQLiteOpenHelper {public static final String DATABASENAME="wancy";//数据库名称public static final int DATABASEVERSION=1;//版本号public static final String TABLENAME = "DH10";//数据库表名public MySQLiteOpenHelper(Context context) {super(context, DATABASENAME, null, DATABASEVERSION);// TODO Auto-generated constructor stub}@Overridepublic void onCreate(SQLiteDatabase db) {String sql = "create table "+TABLENAME+" (id INTEGER PRIMARY KEY,"+"name VARCHAR(50) NOT NULL,"+"birthday DATE NOT NULL)";db.execSQL(sql);}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {String sql = "drop table if exists "+TABLENAME;//当退出的时候删除表db.execSQL(sql);this.onCreate(db);}}

以上要注意一点,在SQLite当中如果想要让某个字段自动增长,那么在创建表的时候使用“INTEGER PRIMARY KEY”声明即可。

那么这样的话一个数据库辅助类已经定义好了,那么我们下面在Activity当中去调用此类的方法。

package com.example.sqliteproject;import com.example.sqliteopenhelper.MySQLiteOpenHelper;import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;public class SQLiteActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_sqlite);MySQLiteOpenHelper helper = new MySQLiteOpenHelper(this);helper.getWritableDatabase();//表示以读写的形式打开数据库}}

现在已经取得了数据库的连接了,如果以上代码没有错误,运行之后就可以在文件列表当中找到数据表.FileExplorer/data/data/数据库辅助类所在的包/database。根据代码,可以发现,如果数据库不存在,那么会自动调用onCreate方法去创建表,如果数据库已经存在了,但是版本号发生了改变,将会调用onUpgrade方法,现将原来的表删除之后,在去创建新的表。

·使用SQLite数据库并完成数据库的更新操作。

public void insert(String name,String birthday){SQLiteDatabase db = super.getWritableDatabase();//取得数据库操作对象String sql = "insert into "+TABLENAME+" (name,birthday) values ('"+name+"',"+birthday+")";db.execSQL(sql);db.close();}public void update(int id,String name,String birthday){SQLiteDatabase db = super.getWritableDatabase();//取得数据库操作对象String sql = "update "+TABLENAME+" set name='"+name+"',birthday="+birthday+" where id="+id;db.execSQL(sql);db.close();}public void delete(int id){SQLiteDatabase db = super.getWritableDatabase();//取得数据库操作对象String sql = "delete from "+TABLENAME+" where id="+id;db.execSQL(sql);db.close();}

以上增删改三个方法写完之后,就可以在Activity当中去进行调用。

package com.example.sqliteproject;import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;import com.example.sqliteopenhelper.MySQLiteOpenHelper;public class SQLiteActivity extends Activity {MySQLiteOpenHelper helper=null;Button insert,update,del = null;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_sqlite);insert=(Button) super.findViewById(R.id.insert);update = (Button) super.findViewById(R.id.update);del = (Button) super.findViewById(R.id.del);helper = new MySQLiteOpenHelper(this);helper.getWritableDatabase();//表示以读写的形式打开数据库insert.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {helper.insert("毛栗子", "1995-01-05");Toast.makeText(SQLiteActivity.this, "新增成功", 0).show();}});update.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {helper.update(1, "大白兔", "1995-01-05");Toast.makeText(SQLiteActivity.this, "修改成功", 0).show();}});del.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {helper.delete(1);Toast.makeText(SQLiteActivity.this, "删除成功", 0).show();}});}}

以上的程序,所有数据都是固定的,这在实际开发当中显然是不科学的,因为我们至少也要使用编辑框进行数据的编辑才是符合实际,而且使用字符串拼凑sql这种形式也是存在问题的,那么我们可以使用占位符的形式来处理这种问题。

public void insert(String name,String birthday){SQLiteDatabase db = super.getWritableDatabase();//取得数据库操作对象java.sql.Date date = null;try {date = new java.sql.Date(new SimpleDateFormat("yyyy-MM-dd").parse(birthday).getTime());} catch (ParseException e) {// TODO Auto-generated catch blocke.printStackTrace();}String sql = "insert into "+TABLENAME+" (name,birthday) values (?,?)";//使用占位符Object args[] = new Object[]{name,birthday};db.execSQL(sql,args);db.close();}

对于以上程序,只是换了另一种操作方法来解决拼凑的问题,功能上没有变化。

对于拼凑sql和使用占位符,可以形成一个共识:

肯定是使用占位符更好一些。

在android当中,还对数据的封装提供了一个ContentValues类。 可以理解为一个Map集合,有key和value,唯一不同的是ContentValues中的key必须是字符串。以后的操作就可以直接通过key取得value。并将value设置到sql语句当中。

public void insert(String name,String birthday){SQLiteDatabase db = super.getWritableDatabase();//取得数据库操作对象ContentValues cv = new ContentValues();cv.put("name", name);cv.put("birthday", birthday);db.insert(TABLENAME, null, cv);//进行新增操作db.close();}public void update(int id,String name,String birthday){SQLiteDatabase db = super.getWritableDatabase();//取得数据库操作对象ContentValues cv = new ContentValues();cv.put("name", name);cv.put("birthday", birthday);String whereClause = " id=?";String whereArgs[]= new String[]{String.valueOf(id)};db.update(TABLENAME, cv, whereClause, whereArgs);//更新操作db.close();}public void delete(int id){SQLiteDatabase db = super.getWritableDatabase();//取得数据库操作对象String whereClause = " id=?";String whereArgs[]= new String[]{String.valueOf(id)};db.delete(TABLENAME, whereClause, whereArgs);//删除操作db.close();}

那么对于使用占位符和ContentValues进行数据库更新操作,两种方式并没有严格的优劣之分,但是对于不会sql的开发人员来说,使用ContentValues更好的。

·数据库查询机Cursor接口

在JDBC中ResultSet接口不呢是的功能就是依靠一个next()方法一动指针向下取数据,是到了JDBC2.0之后才能够向上取数据,但是我们一般也不去用这种向上取的形式。

Cursor接口,出现的比ResultSet晚,所有操作机制有些不同。

package com.example.sqliteproject;import java.util.ArrayList;
import java.util.List;import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;public class DH10Cursor {private static final String TABLENAME="PR10";private SQLiteDatabase db =null;public DH10Cursor(SQLiteDatabase db) {super();this.db = db;}public List<String> find(){List<String> all = new ArrayList<String>();String sql = "select id,name,birthday from "+TABLENAME;Cursor result = this.db.rawQuery(sql, null);//执行查询语句//采用循环的形式去结果集中的数据for(result.moveToFirst();!result.isAfterLast();result.moveToNext()){all.add(result.getInt(0)+"====="+result.getString(1)+"====="+result.getString(2));}result.close();db.close();return all;}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:id="@+id/mylayout"tools:context=".SQLiteActivity" ><Buttonandroid:id="@+id/insert"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="新增"/><Buttonandroid:id="@+id/update"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="修改"/><Buttonandroid:id="@+id/del"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="删除"/><Buttonandroid:id="@+id/query"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="查询"/></LinearLayout>
package com.example.sqliteproject;import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.Toast;import com.example.sqliteopenhelper.MySQLiteOpenHelper;public class SQLiteActivity extends Activity {MySQLiteOpenHelper helper=null;Button insert,update,del,query = null;ListView listView = null;LinearLayout myLayout = null;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_sqlite);helper = new MySQLiteOpenHelper(this);insert=(Button) super.findViewById(R.id.insert);update = (Button) super.findViewById(R.id.update);del = (Button) super.findViewById(R.id.del);query = (Button) super.findViewById(R.id.query);myLayout = (LinearLayout) super.findViewById(R.id.mylayout);query.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {SQLiteActivity.this.listView = new ListView(SQLiteActivity.this);listView.setAdapter(new ArrayAdapter<String>(SQLiteActivity.this, android.R.layout.simple_list_item_1,new DH10Cursor(SQLiteActivity.this.helper.getWritableDatabase()).find()));myLayout.addView(listView);}});insert.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {helper.insert("毛栗子", "1995-01-05");Toast.makeText(SQLiteActivity.this, "新增成功", 0).show();}});update.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {helper.update(1, "大白兔", "1995-01-05");Toast.makeText(SQLiteActivity.this, "修改成功", 0).show();}});del.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {helper.delete(1);Toast.makeText(SQLiteActivity.this, "删除成功", 0).show();}});}}

需要注意一下Cursor的下标是从0开始的有别于ResultSet

·模糊查询

     ·使用sql语句完成模糊查询

public List<String> find(){List<String> all = new ArrayList<String>();String sql = "select id,name,birthday from "+TABLENAME+" where name like ?";String args[] = new String[]{"%栗%"};Cursor result = this.db.rawQuery(sql, args);//执行查询语句//采用循环的形式去结果集中的数据for(result.moveToFirst();!result.isAfterLast();result.moveToNext()){all.add(result.getInt(0)+"====="+result.getString(1)+"====="+result.getString(2));}result.close();db.close();return all;}

        ·使用query方法完成

public List<String> find(){List<String> all = new ArrayList<String>();//String sql = "select id,name,birthday from "+TABLENAME+" where name like ?";String selection = "name like ?";String args[] = new String[]{"%栗%"};String columns[] = new String[]{"id","name","birthday"};Cursor result = this.db.query(TABLENAME, columns, selection, args, null, null, null);//执行查询语句//采用循环的形式去结果集中的数据for(result.moveToFirst();!result.isAfterLast();result.moveToNext()){all.add(result.getInt(0)+"====="+result.getString(1)+"====="+result.getString(2));}result.close();db.close();return all;}

既然模糊查询已经能够完成了,那么还有一种功能可以往下去实现,那就是数据的分页。如果想要实现数据的部分显示,这个语句和Mysql中的查询方式是非常相似,使用limit完成。下面我们进行一些简单的分页操作。

public List<String> find(){int currentPage = 1;//当前页码int lineSize = 5;//每页显示的数据量List<String> all = new ArrayList<String>();String sql = "select id,name,birthday from "+TABLENAME+" limit ?,?";String args[] = new String[]{String.valueOf((currentPage-1)*lineSize),String.valueOf(currentPage*lineSize)};Cursor result = this.db.rawQuery(sql, args);//采用循环的形式去结果集中的数据for(result.moveToFirst();!result.isAfterLast();result.moveToNext()){all.add(result.getInt(0)+"====="+result.getString(1)+"====="+result.getString(2));}result.close();db.close();return all;}

·使用ListView来实现滑动分页

  Android中有这样一个操作,只需要手指进行上下滑动,屏幕自动滚动,到达最后一条数据的时候,提示:请稍等,数据正在加载......。这个操作需要使用SimpleAdapter来完成,因为在这个适配器中有下面这样一个方法。

pulibc void notifyDataSetChanged()

表示如果在SimpleAdapter中的填充数据集合list内容一旦发生变化,就会立刻通知ListView进行及时新数据加载,当数据加载底部的时候,需要提示一个信息,而这个信息可以通过ListView组件里的方法去添加

public void addFooterView(View v)

现在还剩下一个问题,需要去监听滚动事件,需要使用如下接口:

首先顶一个ListView的布局模板。

<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/mylayout"android:layout_width="match_parent"android:layout_height="match_parent" ><TableRow ><TextView android:id="@+id/id"android:layout_width="50px"android:layout_height="wrap_content"android:textSize="30px"/><TextView android:id="@+id/name"android:layout_width="120px"android:layout_height="wrap_content"android:textSize="30px"/><TextView android:id="@+id/birthday"android:layout_width="130px"android:layout_height="wrap_content"android:textSize="30px"/></TableRow></TableLayout>

现在我们需进行查询操作,需要返回一共有多少笔数据,修改一下查询的类

package com.example.sqliteproject;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;public class DH10Cursor {private static final String TABLENAME="DH10";private SQLiteDatabase db =null;public DH10Cursor(SQLiteDatabase db) {super();this.db = db;}public List<Map<String,Object>> find(int currentPage,int lineSize){List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();String sql = "select id,name,birthday from "+TABLENAME+" limit ?,?";String args[] = new String[]{String.valueOf((currentPage-1)*lineSize),String.valueOf(currentPage*lineSize)};Cursor result = this.db.rawQuery(sql, args);for(result.moveToFirst();!result.isAfterLast();result.moveToNext()){Map<String,Object> map = new HashMap<String,Object>();map.put("id", result.getInt(0));map.put("name", result.getString(1));map.put("birthday", result.getString(2));list.add(map);}return list;}public int getCount(){int count = 0;String sql = "select count(id) from "+TABLENAME;Cursor result  = this.db.rawQuery(sql, null);for(result.moveToFirst();!result.isAfterLast();result.moveToNext()){count = result.getInt(0);//取得数据的总笔数}return count;}
}

下面写一下主布局文件,这个比较简单,直接放一个线性布局管理器就可以了。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/mainlayout"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ></LinearLayout>

现在只剩下Activity

package com.example.sqliteproject;import java.util.List;
import java.util.Map;import android.app.Activity;
import android.os.Bundle;
import android.view.Gravity;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;import com.example.sqliteopenhelper.MySQLiteOpenHelper;public class SQLiteActivity extends Activity {MySQLiteOpenHelper helper=null;ListView listView = null;LinearLayout mainLayout = null;int currentPage = 1;int lineSize = 5;int count = 0;int pageSize = 1;//总页数int lastItem = 0;//保存最后一个记录点SimpleAdapter adapter = null;TextView tv = null;//底部信息LinearLayout loadLayout = null;//底部提示框布局List<Map<String,Object>> list = null;LayoutParams lp= new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);  super.setContentView(R.layout.listview_main);this.mainLayout=(LinearLayout) super.findViewById(R.id.mainlayout);this.loadLayout=new LinearLayout(this);this.tv = new TextView(this);tv.setText("数据加载中,请稍后。。。");tv.setGravity(Gravity.CENTER);tv.setTextSize(30);loadLayout.addView(this.tv,this.lp);loadLayout.setGravity(Gravity.CENTER);this.showAllData();}private void showAllData(){this.helper = new MySQLiteOpenHelper(this);this.listView = new ListView(this);DH10Cursor cursor = new DH10Cursor(this.helper.getWritableDatabase());//获得一个查询操作对象this.count = cursor.getCount();//取得总数据笔数this.list = cursor.find(currentPage, lineSize);this.adapter = new SimpleAdapter(this, list, R.layout.listview_item_layout, new String[]{"id","name","birthday"},new int[]{R.id.id,R.id.name,R.id.birthday});//实例化适配器对象SQLiteActivity.this.listView.addFooterView(SQLiteActivity.this.loadLayout);this.listView.setAdapter(adapter);this.listView.setOnScrollListener(new OnScrollListener() {@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {if(SQLiteActivity.this.lastItem==SQLiteActivity.this.adapter.getCount()//表示当前记录已经在最底部&&SQLiteActivity.this.currentPage<SQLiteActivity.this.pageSize//当前页要小于总页数&&scrollState==OnScrollListener.SCROLL_STATE_IDLE//屏幕不再滚动){SQLiteActivity.this.currentPage++;SQLiteActivity.this.listView.setSelection(SQLiteActivity.this.lastItem);//设置显示位置SQLiteActivity.this.listView.addFooterView(SQLiteActivity.this.loadLayout);SQLiteActivity.this.appendData();}}@Overridepublic void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {SQLiteActivity.this.lastItem = firstVisibleItem+visibleItemCount-1;}});mainLayout.addView(this.listView);if(this.count%this.lineSize==0){this.pageSize = this.count/this.lineSize;}else{this.pageSize = this.count/this.lineSize+1;}}private void appendData(){//更新数据方法DH10Cursor cursor = new DH10Cursor(this.helper.getWritableDatabase());List<Map<String,Object>> newData = cursor.find(currentPage, lineSize);this.list.addAll(newData);this.adapter.notifyDataSetChanged();//适配器重新加载集合数据}
}

以上就是整个实现下滑屏幕实现分页加载数据的程序。

事务的处理是针对数据库而已,以后的开发当中,只要针对增删改,都需要用事务进行处理。

public void insert(String name,String birthday){SQLiteDatabase db = super.getWritableDatabase();//取得数据库操作对象db.beginTransaction();//开启事务try{ContentValues cv = new ContentValues();cv.put("name", name);cv.put("birthday", birthday);db.insert(TABLENAME, null, cv);//进行新增操作db.setTransactionSuccessful();//正确执行,否则回滚}catch(Exception e){db.endTransaction();//事务关闭db.close();}}

1.3 小结

(1)SQLite数据库是一个专门用于嵌入式设备的数据库;

(2)SQLite支持SQL语句的操作;

(3)可以使用SQLiteOpenHelper类完成数据库的操作;

(4)所有的查询数据使用Cursor进行接收;

相关文章:

Android——数据存储(二)(二十二)

1. SQLite数据库存储 1.1 知识点 &#xff08;1&#xff09;了解SQLite数据库的基本作用&#xff1b; &#xff08;2&#xff09;掌握数据库操作辅助类&#xff1a;SQLiteDatabase的使用&#xff1b; &#xff08;3&#xff09;可以使用命令操作SQLite数据库&#xff1b; …...

appium环境搭建

一.appium环境搭建 1.python3 python3的下载安装这里就不多做介绍了&#xff0c;当然你也可以选择自己喜欢的语音&#xff0c;比如java… 2.jdk 1&#xff09;下载地址 官网(需登录账号)&#xff1a; https://www.oracle.com/java/technologies/downloads/ 百度网盘&…...

十五、Webpack打包图片-js-Vue、Label命令、resolve模块解析

一、webpack打包图片 &#xff08;1&#xff09;加载图片案例准备 为了演示我们项目中可以加载图片&#xff0c;我们需要在项目中使用图片&#xff0c;比较常见的使用图片的方式是两种&#xff1a; img元素&#xff0c;设置src属性&#xff1b;其他元素&#xff08;比如div&…...

ARM指令集--数据处理指令

数据处理指令&#xff1a;数学运算&#xff0c;逻辑运算 立即数 立即数的本质 就是包含在指令当中的数&#xff0c;属于指令的一部分 立即数的优点&#xff1a;取指的时候就可以将其读取到CPU&#xff0c;不用单独去内存读取&#xff0c;速度快 立即数的缺点&#xff1a;不…...

Excel embed into a webpage

无法编辑嵌入式 Excel 网页版 工作簿&#xff0c;但具有适当权限的人员可能能够在 Excel 中打开嵌入的工作簿&#xff0c;他们可以在其中编辑数据。 通过制作一个浏览器&#xff0c;打开并编辑它 https://onedrive.live.com/embed? resid5FC97855340825A9%21135& aut…...

uniapp点击事件在小程序中无法传参

这个问题很是神奇&#xff0c;第一次遇到。在h5中&#xff0c;点击事件可以正常传参&#xff0c;打包小程序后确失效了。 修改&#xff1a;for循环中的key&#xff0c;使用 index就好了...

ssprompt:一个LLM Prompt分发管理工具

阅读顺序 &#x1f31f;前言&#x1f514;ssprompt介绍命令介绍Metafile介绍版本依赖规则 &#x1f30a; PromptHubGitHub Token &#x1f680; Quick Install系统依赖pip安装Linux, macOS, Windows (WSL)Windows (Powershell) &#x1f6a9; Roadmap&#x1f30f; 项目交流讨论…...

修复 ChatGPT 发生错误的问题

目录 ChatGPT 发生错误&#xff1f;请参阅如何修复连接错误&#xff01; 修复 ChatGPT 发生错误的问题 基本故障排除技巧 检查 ChatGPT 的服务器状态 检查 API 限制 检查输入格式 清除浏览数据 香港DSE是什么&#xff1f; 台湾指考是什么&#xff1f; 王湘浩 生平 …...

《热题100》字符串、双指针、贪心算法篇

思路&#xff1a;对于输入的的字符串&#xff0c;只有三种可能&#xff0c;ipv4,ipv6,和neither ipv4:四位&#xff0c;十进制&#xff0c;无前导0&#xff0c;小于256 ipv6:八位&#xff0c;十六进制&#xff0c;无多余0&#xff08;00情况不允许&#xff09;&#xff0c;不…...

大数据组件Sqoop-安装与验证

&#x1f947;&#x1f947;【大数据学习记录篇】-持续更新中~&#x1f947;&#x1f947; 个人主页&#xff1a;beixi 本文章收录于专栏&#xff08;点击传送&#xff09;&#xff1a;【大数据学习】 &#x1f493;&#x1f493;持续更新中&#xff0c;感谢各位前辈朋友们支持…...

运算符重载(个人学习笔记黑马学习)

1、加号运算符重载 #include <iostream> using namespace std; #include <string>//加号运算符重载 class Person { public://1、成员函数重载号//Person operator(Person& p) {// Person temp;// temp.m_A this->m_A p.m_A;// temp.m_B this->m_B p…...

2023.9.6 Redis 的基本介绍

目录 Redis 的介绍 Redis 用作缓存和存储 session 信息 Redis 用作数据库 消息队列 消息队列是什么&#xff1f; Redis 用作消息队列 Redis 的介绍 特点&#xff1a; 内存中存储数据&#xff1a;奠定了 Redis 进行访问和存储时的快可编程性&#xff1a;支持使用 Lua 编写脚…...

2023-09-08力扣每日一题

链接&#xff1a; 2651. 计算列车到站时间 题意&#xff1a; 不看日期只看时间 解&#xff1a; &#xff1f; 实际代码&#xff1a; 还看&#xff01;你怎么肥四&#xff1f;int findDelayedArrivalTime(int arrivalTime, int delayedTime) {return (arrivalTimedelayed…...

adb-linux 调试桥

这里写自定义目录标题 摘要&#xff1a;一、简介二、adb使用参考连接 摘要&#xff1a; adb 可替代网络、串口等调试手段&#xff0c;可以方便的进行文件传输、终端登录等 一、简介 ADB的全称为Android Debug Bridge&#xff0c;即调试桥&#xff0c;方便调试设备或调试开发…...

入门人工智能 —— 使用 Python 进行文件读写,并完成日志记录功能(4)

入门人工智能 —— 使用 Python 进行文件读写&#xff08;4&#xff09; 入门人工智能 —— 使用 Python 进行文件读写打开文件读取文件内容读取整个文件逐行读取文件内容读取所有行并存储为列表 写入文件内容关闭文件 日志记录功能核心代码&#xff1a;完整代码&#xff1a;运…...

使用Caffeine实现帖子的缓存来优化网站的运行速度

导入依赖 <!-- https://mvnrepository.com/artifact/com.github.ben-manes.caffeine/caffeine --><dependency><groupId>com.github.ben-manes.caffeine</groupId><artifactId>caffeine</artifactId><version>3.1.7</version>…...

Webpack5 搭建Vue项目(进阶版)

Webpack5 搭建Vue项目&#xff08;进阶版&#xff09; 提示&#xff1a;中间隔了好长时间&#xff0c;我胡汉三又回来继续更新了&#xff01;&#xff01;&#xff01;&#x1f602;&#x1f602;&#x1f602; 文章目录 Webpack5 搭建Vue项目&#xff08;进阶版&#xff09;前…...

论文阅读:Distortion-Free Wide-Angle Portraits on Camera Phones

论文阅读&#xff1a;Distortion-Free Wide-Angle Portraits on Camera Phones 今天介绍一篇谷歌 2019 年的论文&#xff0c;是关于广角畸变校正的。 Abstract 广角摄影&#xff0c;可以带来不一样的摄影体验&#xff0c;因为广角的 FOV 更大&#xff0c;所以能将更多的内容…...

力扣每日一题---207. 课程表

Problem: 207. 课程表 文章目录 解题方法复杂度Code 解题方法 y总的 Topsort 模板题 复杂度 时间复杂度: 添加时间复杂度, 示例&#xff1a; O ( n ) O(n) O(n) 空间复杂度: 添加空间复杂度, 示例&#xff1a; O ( n ) O(n) O(n) Code class Solution {int res 0; public…...

在Kubernetes环境中有关Nginx Ingress与API Gateway的连接问题

文章目录 小结问题解决参考 小结 在Kubernetes环境中是通过Nginx Ingress来从外部访问Kubernetes内部的环境&#xff0c;并用API Gateway来分发请求&#xff0c;碰到了 502 Bad gateway.的问题&#xff0c;并尝试解决。 问题 从外部通过Nginx Ingress访问Kubernetes内部的环…...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法

树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作&#xff0c;无需更改相机配置。但是&#xff0c;一…...

(十)学生端搭建

本次旨在将之前的已完成的部分功能进行拼装到学生端&#xff0c;同时完善学生端的构建。本次工作主要包括&#xff1a; 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)

服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

页面渲染流程与性能优化

页面渲染流程与性能优化详解&#xff08;完整版&#xff09; 一、现代浏览器渲染流程&#xff08;详细说明&#xff09; 1. 构建DOM树 浏览器接收到HTML文档后&#xff0c;会逐步解析并构建DOM&#xff08;Document Object Model&#xff09;树。具体过程如下&#xff1a; (…...

Mac下Android Studio扫描根目录卡死问题记录

环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中&#xff0c;提示一个依赖外部头文件的cpp源文件需要同步&#xff0c;点…...

重启Eureka集群中的节点,对已经注册的服务有什么影响

先看答案&#xff0c;如果正确地操作&#xff0c;重启Eureka集群中的节点&#xff0c;对已经注册的服务影响非常小&#xff0c;甚至可以做到无感知。 但如果操作不当&#xff0c;可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

LeetCode - 199. 二叉树的右视图

题目 199. 二叉树的右视图 - 力扣&#xff08;LeetCode&#xff09; 思路 右视图是指从树的右侧看&#xff0c;对于每一层&#xff0c;只能看到该层最右边的节点。实现思路是&#xff1a; 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...

代码规范和架构【立芯理论一】(2025.06.08)

1、代码规范的目标 代码简洁精炼、美观&#xff0c;可持续性好高效率高复用&#xff0c;可移植性好高内聚&#xff0c;低耦合没有冗余规范性&#xff0c;代码有规可循&#xff0c;可以看出自己当时的思考过程特殊排版&#xff0c;特殊语法&#xff0c;特殊指令&#xff0c;必须…...

FFmpeg:Windows系统小白安装及其使用

一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】&#xff0c;注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录&#xff08;即exe所在文件夹&#xff09;加入系统变量…...