sqlite简介

本人最近在写一个小的安卓项目,开发app过程中用到了安卓自带的sqlite。本文主要对sqlite图片操作进行介绍,其他存入文本之类的操作和普通数据库一样,众所周知,sqlite是一款轻型的数据库,以下先简单介绍一下sqlite,为后续做铺垫,有了解的大佬可以跳过此部分:

SQLite是一种轻量级、嵌入式的关系型数据库管理系统,它以库的形式提供了一组编程接口,可以在各种操作系统上运行,如Windows、Linux、Mac OS等,被广泛应用于移动设备和嵌入式系统中。SQLite的数据存储在单个文件中,不需要专门的服务器进程或后台进程,它支持绝大多数的SQL语法,可以处理大部分中小型应用程序的数据存储和管理需要。

SQLite的优点主要有以下几个:

简单易用:SQLite非常易于安装和使用,只需要引入单个库文件,便可以开始使用它提供的API进行开发。

小巧灵活:由于SQLite的设计目标定位为轻量级的数据库管理系统,因此它的库文件非常小巧,适合在嵌入式设备和移动终端中使用。

零配置:SQLite不需要任何专门的配置或安装过程,用户只需要将其API引入到程序中即可使用,大大简化了部署和维护的工作。

兼容性强:SQLite支持大部分标准的SQL语法,同时可以通过插件或扩展使用自定义的函数和AGGREGATE聚合函数。

SQLite的缺点也是比较明显的:

不适合大规模数据存储:由于SQLite的数据存储在单个文件中,因此不适合处理大规模数据存储的需求,处理大量数据的查询和更新操作性能可能较差。

难以扩展:SQLite的特性和限制都固定在库文件中,因此很难对其进行重构或扩展,无法满足高度定制化需求。

总的来说,SQLite是一种非常轻量级的数据库管理系统,在小型应用开发及移动端开发中十分适合,但在处理大规模数据存储及高并发操作的应用场景下效果不佳。

插入图片

进入正题,在使用sqlite的过程中,我遇到了插入图片失败的问题,查了不少资料,才知道sqlite不能直接存入.jpg还有.png之类的文件,需要以二进制的形式存储在sqlite中,这也是为什么上面说的sqlite不适合大规模数据存储,是一个轻量级数据库。我用下面代码来进一步说明

要用到的方法以及部分名词说明:

Bitmap是Android系统中的图像处理的最重要类之一。用它可以获取图像文件信息,进行图像剪切、旋转、缩放等操作,并可以指定格式保存图像文件。

BitmapFactory.decodeResource(?,?)这个带两个参数的方法:第一个参数是包含你要加载的位图资源文件的对象(一般写成 getResources()就ok了);第二个时你需要加载的位图资源的Id。

位图介绍:位图(Bitmap)格式其实并不能说是一种很常见的格式(从我们日常的使用频率上来讲,远不如 .jpg .png .gif 等),因为其数据没有经过压缩,或最多只采用行程长度编码(RLE,run-length encoding)来进行轻度的无损数据压缩

这是一个写好的调用语句和方法,insertdb()是写好的方法,可以稍加修改后放入你的Activity页面或fragment页面,调用语句如图。

//你的图片在andriod studio中是存在R.drawble中的,并且是int型的
//存入数据库的id是自己定义数据库时设计好的,可以参考我的数据库代码 insertdb( R.drawable.你的图片名,存入数据库的id); //s指你的图片资源,int型,即R.drawable.你的图片名
private void insertdb(int s,int id){ //把你的图片资源转化成位图
Bitmap bitmap = BitmapFactory.decodeResource(this.getResources(), s); //Mysql是自己写的数据库类,需要自己编写,下面两句话是实例化一个sqlite数据库对象
Mysql mySqlLite = new Mysql(this);
SQLiteDatabase database = mySqlLite.getReadableDatabase(); //设置一个size大小,用来压缩图片文件
int size = bitmap.getWidth() * bitmap.getHeight() * 4; //ByteArrayOutputStream(字节数组输出流)对byte类型数据进行写入的类,属于内存操作流
ByteArrayOutputStream baos= new ByteArrayOutputStream(size); //压缩位图bitmap
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos); //定义一个byte类型的数组bytedata存储位图字节流转化成的byte数组
byte[] bytedata = baos.toByteArray(); //sql语句是根据自己需求写的,不要照抄
database.execSQL("update 你的表名 set image=? where _id=?",new Object[] {bytedata,id});
}
//MySQL.java
package 你的包名; import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper; public class Mysql extends SQLiteOpenHelper { private static final String DB_NAME="INFORM.db";
private static final int DB_VERSION=1; public Mysql(Context context){
super(context,DB_NAME,null,DB_VERSION);
} @Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(
"CREATE TABLE INFORMATION(" +
"_id INTEGER PRIMARY KEY AUTOINCREMENT,"
+"NAME TEXT,"
+"TITLE TEXT,"
+"image blob,"
+"TEXTS TEXT);"
); insertTest(db, "程序员", "程序员.exe无响应","祝你有美好的一天");
insertTest(db, "程序员", "已停止运行","下辈子再也不用sqlite了"); @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } public void insertTest(SQLiteDatabase db,String name,String title,String texts){
ContentValues value=new ContentValues();
value.put("NAME",name);
value.put("TITLE",title);
value.put("TEXTS",texts);
db.insert("INFORMTION",null,value);
}
}

读取图片

已经往数据库插入图片了,现在可以读取图片了,这里我用的是游标

package 你的包名;

import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import com.example.garden.database.Mydb; public class SearchResult extends AppCompatActivity implements AdapterView.OnItemClickListener { //定义游标
private Cursor cursor;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search_result); Intent rit = getIntent();
String text = rit.getStringExtra("key"); ListView listview=findViewById(R.id.listview); //帮助器和管理器两个老朋友了,实例化数据库对象
SQLiteOpenHelper helper=new Mydb(this);
SQLiteDatabase db=helper.getWritableDatabase(); //游标读取数据库
cursor=db.rawQuery("select * from KNOW where name like '%"+text+"%'",null);
cursor.moveToFirst(); //数据库的简单游标适配器,简单来说就是往模板填充内容的一个桥梁
SimpleCursorAdapter mAdapter=new SimpleCursorAdapter(this,R.layout.item_list,
cursor,new String[]{"NAME","image","TITLE"},new int[]{R.id.iv1,R.id.iv2,R.id.iv3},0);//自己的xml组件名R.id.iv1,R.id.iv2,R.id.iv3与数据库字段名"NAME","image","TITLE"对应,更多用法自己查 //仅仅是上面的简单游标适配器是不能读取图片的,重点来了,此处用到了ViewBinder
SimpleCursorAdapter.ViewBinder binder=new SimpleCursorAdapter.ViewBinder() {
@Override
public boolean setViewValue(View view, Cursor cursor, int columnIndex) { //判断是否是ImageView,这个判断非常关键,详细可以按ctr去查找ViewBinder,就去文档看,不要找其他资料,如果想真的搞懂一定要看!
if (view instanceof ImageView) {
ImageView imageView = (ImageView) view; imageView.setImageBitmap(readImageFromDb(cursor.getString(cursor.getColumnIndex("_id"))));//为imageView配置id所对应的图片
return true;
}
return false;
}
}; //配置ViewBinder
mAdapter.setViewBinder(binder);
//配置适配器
listview.setAdapter(mAdapter);
//点击监听器
listview.setOnItemClickListener(this); } //
@SuppressLint("Range")
private Bitmap readImage(String id) { //至于为什么又要实例化,是因为sqlite不能同时使用,术语不专业,总之要重新实例化,不然会报错
Mysql mySqlLite2 = new Mysql(this);
SQLiteDatabase database2 = mySqlLite2.getReadableDatabase(); Bitmap image= null;
byte[] bytes;
Cursor cursor = database2.rawQuery( "SELECT * FROM INFORMATION WHERE _id = ?", new String[]{id});
if (cursor.moveToFirst()) {
if ((bytes = cursor.getBlob(cursor.getColumnIndex("image"))) != null) {
image= BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
}
}
cursor.close();
return image;
} //listview的点击事件
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//此处写点击事件,我用来传值以及跳转页面
Intent it=new Intent(this, Show.class);
it.putExtra("ID",(int)id-1);
startActivity(it);
finish();
}
}

可能会出现的问题

此处重点!我遇到的大问题目前只有一个,就是行过大导致无法读取数据库,原因是我放入的图片太大了,大概1MB左右的样子,我其他的图片大小一般是200KB到500KB左右,1MB的图片太大了,导致那个位图转化的二进制数据流太大了,数据库无法一次读取完,会导致程序直接崩溃,解决办法就是不存入太大的图片。毕竟它还只是个”孩砸“啊,sqlite是个轻量级的数据库,不要存入太大的图片

总结

写代码的过程中遇到了不少问题,感谢互联网各位大佬发的参考资料,由于参考了许多资料和文献,也因为当时写的太快了没有记住大佬的博客和文章,深表歉意,本项目后续完善后也会发到GitHub上面去,做一个开源小项目给大家参考,本人目前大二计科学生,希望和各位一同成长前进。

Android Studio中SQLite的使用,主要介绍sqlite插入和读出图片(ViewBinder)的操作方法的更多相关文章

  1. Eclipse和Android Studio中的DDMS使用时什么不同?

    http://www.jb51.net/softjc/454131.html Eclipse和Android Studio中的DDMS使用时什么不同? 相信很多经常开发Android应用的朋友应该都接 ...

  2. Android Studio中配置及使用OpenCV示例

    Android Studio配置及使用OpenCV 前言:最近在做项目移植,项目较大,在Eclipse中配置的Jni及OpenCV环境没任何问题,但是迁移到Studio中就问题一大堆,网上也找了一些资 ...

  3. 浅谈Windows下SVN在Android Studio中的配置、基本使用及解除关联

    看到网上很多关于svn环境配置和关联Android-Studio的很多博文,发现很零散,想集大家所长整理一下: 在AndroidStudio中开发版本控制中,除了Git就是SVN,和Eclipse不同 ...

  4. Android Studio中创建Kotlin For Android项目

    Kotlin俗称Android中的Swift,它是Jetbrains公司开发的基于JVM的一门语言,JetBrains公司可能大家并不熟悉,不过相信IntelliJ IDE大家一定知道,Android ...

  5. 浅谈Kotlin(一):简介及Android Studio中配置

    浅谈Kotlin(一):简介及Android Studio中配置 浅谈Kotlin(二):基本类型.基本语法.代码风格 浅谈Kotlin(三):类 浅谈Kotlin(四):控制流 前言: 今日新闻:谷 ...

  6. jdk1.8新特性之lambda表达式及在Android Studio中的使用举例

    Jdk1.8已经出很久了但是很多同学对它的特性在android studio 中的应用可能还不是很熟悉,今天我们就来对这个新特性在AS中做它的应用实践. 一.首先在有JDK1.8的情况下我们要在AS的 ...

  7. Android Studio 中的FindBugs插件使用,轻松帮你发现Bug (转)

    在日常开发过程中难免会因为一时疏忽而留下一些Bug,这些Bug就是埋在程序里的定时炸弹,如果不能及时铲除就会导致程序的不稳定,异常或闪退的现象,从而导致用户的体验的下降.那么怎么才能找出这些埋在程序里 ...

  8. 在Android Studio中调用so中的方法

    本节用的so是上节用Android Studio创建的so.想在Android Studio中调用so中的方法,需要先引用so.Android Studio中引用so的方法有二种,下面开始介绍. 一 ...

  9. 在Android Studio中创建项目和模拟器

    北京电子科技学院 实      验      报      告 课程:移动平台应用开发实践  班级:201592  姓名:杨凤  学号:20159213 成绩:___________  指导老师:娄嘉 ...

  10. Android IPC机制(三)在Android Studio中使用AIDL实现跨进程方法调用

    在上一篇文章Android IPC机制(二)用Messenger进行进程间通信中我们介绍了使用Messenger来进行进程间通信的方法.可是我们能发现Messenger是以串行的方式来处理client ...

随机推荐

  1. MQTT(EMQX) - Java 调用 MQTT Demo 代码

    POM <dependency> <groupId>org.eclipse.paho</groupId> <artifactId>org.eclipse ...

  2. 柏林噪声算法(Perlin Noise)

    概述 引述维基百科的介绍: Perlin噪声(Perlin noise,又称为柏林噪声)指由Ken Perlin发明的自然噪声生成算法,具有在函数上的连续性,并可在多次调用时给出一致的数值. 在电子游 ...

  3. go微服务框架kratos学习笔记三(构建单独的http或者grpc demo项目)

    go微服务框架kratos学习笔记三(构建单独的http或者grpc demo项目) 前面两篇跑通了demo项目,和大概了解了kratos demo整体结构,本篇分别构建一个http和一个grpc微服 ...

  4. vue之事件修饰符

    目录 修饰符 .stop事件 .self事件 .prevent事件 .once事件 修饰符 事件修饰服 释义 .stop 只处理自己的事件,子控件不再冒泡给父控件 .self 只处理自己的事件,子控件 ...

  5. 更新pip遇到的问题及解决方法

    问题ython -m pip install --upgrade pip --user D:\APP\Anaconda3\python.exe: No module named pip解决方法 pyt ...

  6. NextCloud 在lnmp下 nginx 的配置

    server { listen 80; listen [::]:80; server_name lnmp.org www.lnmp.org; root /home/wwwroot/nextcloud; ...

  7. 做个清醒的程序员之拥抱AI

    阅读时长约 13 分钟,共计约 3100个字. 昨天我体验了AI自动生成短视频,具体说来,首先我在域名为FreeGPT的免费网站,向它提问,然后生成一段文字.之后呢,再用剪映里面的"图文成片 ...

  8. iOS APP启动广告实现方式 与 APP唤端调用

    APP启动广告功能实现要从2个方面思考 一是UI方案,怎样处理广告页与主页之间的切换方式. 二是广告页展示时机,是使用后台实时广告数据还是使用本地缓存广告数据.后台数据方式获取广告最新但是用户要等待后 ...

  9. 快速上手Linux核心命令(八):网络相关命令

    目录 前言 测试主机之间网络是否联通 ifconfig 配置或显示网络信息 route 显示或管理路由表 netstat 查看网络状况 telnet 远程登录主机 ssh 安全的远程登录主机 wget ...

  10. 打开conda环境报错:UnicodeDecodeError: ‘gbk‘ codec can‘t decode byte 0x9a in position 317: illegal multibyt

    解决打开conda环境报错:UnicodeDecodeError: 'gbk' codec can't decode byte 0x9a in position 317: illegal multib ...