APP本地数据库简单操作和升级(Android/Flutter)

Flutter 本地数据库sqflite实战操作 Flutter本地化数据库操作、sqflite操作方法、数据库操作 阅读详情

Android

项目中用到本地数据库存储数据,数据量以及类型比较多而且繁杂,于是乎,就用GreenDao插件来存储了。
先说一下配置情况:
1、工程build.gradle中添加如下:
这里写图片描述

说明:dependencies节点下添加

classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2'

2、Moudle下的build.gradle添加如下:
这里写图片描述

说明:顶部最外层添加:

apply plugin: 'org.greenrobot.greendao'

android节点下添加:

greendao {
        schemaVersion 1//数据库版本号,数据库升级会用到,如果不需要升级,一直为1就好
        daoPackage 'com.thtj.demo.dao'//DaoMaster、DaoSession以及各种实体Dao的生成路径
        targetGenDir 'src/main/java'
    }

dependencies节点下添加:

compile 'org.greenrobot:greendao:3.2.2'

最后Aysnc一下就算完成了。

3、创建实体类表,比如:

import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.Unique;
import org.greenrobot.greendao.annotation.Generated;


@Entity
public class Person {
    @Id
    private Long id;
    @Unique
    private String name;
    private int age;
    private String sex;
    private int salary;
    @Generated(hash = 72938267)
    public Person(Long id, String name, int age, String sex, int salary) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.salary = salary;
    }
    @Generated(hash = 1024547259)
    public Person() {
    }
    public Long getId() {
        return this.id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getName() {
        return this.name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return this.age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getSex() {
        return this.sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public int getSalary() {
        return this.salary;
    }
    public void setSalary(int salary) {
        this.salary = salary;
    }
    
}

声明完属性以后,rebuild一下工程,会自动生成上面的那些get、set等方法,对应的dao包路径下也会生成相应的Dao文件。这些都不需要手动添加,全是rebuild工程之后自动生成的,而且不建议修改。你只需要声明属性(也就是表中的字段)就好。

4、创建MyApplication:

public class MyApplication extends Application {
    private MySQLiteOpenHelper mHelper;
    public static MyApplication instance;

    @Override
    public void onCreate() {
        super.onCreate();
        instance = this;
        setDatabase();
    }

    public static MyApplication getInstances() {
        return instance;
    }

    private void setDatabase() {
        // 注意:默认的 DaoMaster.DevOpenHelper 会在数据库升级时,删除所有的表,意味着这将导致数据的丢失。
        // 在正式的项目中,还应该做一层封装,来实现数据库的安全升级。
        mHelper = new MySQLiteOpenHelper(this, "notes-db", null);
    }

    public DaoSession getDaoSession() {
        return new DaoMaster(mHelper.getWritableDatabase()).newSession();
    }
}

里面有这么一句话:“在正式的项目中,还应该做一层封装,来实现数据库的安全升级”。网上的很多Demo是未封装的。如果你的数据库不需要升级的话,可以直接使用,但是如果你的数据库需要升级的话,显然就不可取了。
因为数据库版本升级的话,会默认先删除所有的表,再重新创建,意味着如果用户之前数据库里已经保存了数据,你这样不作处理,直接修改为schemaVersion2然后打包给用户安装的话,会导致用户之前手机数据库里存的数据全部丢失。下面DaoMater里那两行代码也意味着:删除、重建。
这里写图片描述
所以在升级的时候需要对用户已经保存的数据进行一下处理。
借助于:

compile 'com.github.yuweiguocn:GreenDaoUpgradeHelper:v2.0.1'

工程build.gradle中allprojects节点下的repositories下添加

maven { url "https://jitpack.io" }

github上搜一下就行,当然网上也有很多使用教程。

compile完成之后,创建一个MySQLiteOpenHelper,也就是上面MyApplication中用到的。

public class MySQLiteOpenHelper extends DaoMaster.OpenHelper {
    public MySQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {
        super(context, name, factory);
    }
    @Override
    public void onUpgrade(Database db, int oldVersion, int newVersion) {
        MigrationHelper.migrate(db, new MigrationHelper.ReCreateAllTableListener() {
                    @Override
                    public void onCreateAllTables(Database db, boolean ifNotExists) {
                        DaoMaster.createAllTables(db, ifNotExists);
                    }
                    @Override
                    public void onDropAllTables(Database db, boolean ifExists) {
                        DaoMaster.dropAllTables(db, ifExists);
                    }
                }, PersonDao.class);
    }
}

重写了升级里面的方法,这样就保证了即使数据库添加字段升级了,数据也不会丢失。
上面的PersonDao就是Person这个表新增字段有改动的dao,可以添加多个,比如:

PersonDao.class,MoneyDao.class...

然后就可以使用了,Demo如下:

public class MainActivity extends Activity {
    private TextView tv;
    private String s = "";
    private PersonDao dao = MyApplication.getInstances().getDaoSession().getPersonDao();

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

        List<Person> personList = dao.loadAll();
        if (personList.size() == 0) {
            for (int i = 0; i < 2; i++) {
                Person p = new Person();
                p.setName("挨踢" + i);
                p.setAge(i);
                p.setSex("男");
                dao.insertOrReplace(p);
            }
            queryData();
        } else {
            queryData();
        }
        tv.setText(s.substring(0, s.length() - 1));

        tv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Person p = dao.queryBuilder()
                        .where(PersonDao.Properties.Name.eq("挨踢0")).unique();
                if (p != null) {
                    p.setSex("女");
                    dao.insertOrReplace(p);
//                    dao.update(p);//也可以这样,检测到存在都会更新
                }
                queryData();
                tv.setText(s.substring(0, s.length() - 1));
            }
        });
    }

    public void queryData(){
        s = "";
        List<Person> pl = dao.loadAll();
        if (pl != null && pl.size() > 0) {
            for (Person p : pl) {
                s += new GsonBuilder().serializeNulls().create().toJson(p) + ",";
            }
        }
    }
}

插入一条数据常用方法:insert或者insertOrReplace,后者也起到了更新的功能,跟update功能一样,只不过在数据库里的顺序会改变,直接update更新的话,顺序不会改变。关于查询和删除的方法就不多说了,网上很多。

Flutter

flutter借助插件sqflite: ^1.1.6+3来实现。
以模拟创建简单的用户表为例:

import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';

final String tableName = "user"; //表名
final String columnId = "id"; //主键
final String columnUserId = "userId"; //用户唯一标识
final String columnName = "name"; //用户名
final String columnAge = "age"; //年龄
final String columnSex = "sex"; //version:2 新增的性别字段

class User {
  int id;
  int userId;
  String name;
  int age;
  String sex; //version:2 新增的性别字段

  User();

  Map<String, dynamic> toMap() {
    return <String, dynamic>{
      columnId: id,
      columnUserId: userId,
      columnName: name,
      columnAge: age,
      columnSex: sex, //version:2 新增的性别字段
    };
  }

  User.fromMap(Map<String, dynamic> map) {
    id = map[columnId];
    userId = map[columnUserId];
    name = map[columnName];
    age = map[columnAge];
    sex = map[columnSex]; //version:2 新增的性别字段
  }

  @override
  String toString() {
    return 'User{id: $id, userId: $userId, name: $name, age: $age, sex: $sex}';
  }
}

class SqlLite {
  Database db;

  ///创建数据库
  openSqlLite() async {
    var databasesPath = await getDatabasesPath();
    String path = join(databasesPath, "test.db");
    db = await openDatabase(
      path,
      version: 2,
      onCreate: _onCreate,
      onUpgrade: _onUpgrade,
    );
  }

  void _onCreate(db, version) async {
    var batch = db.batch();
    _createTableUser(batch); //可在此创建多个表
    await batch.commit();
  }

  ///创建用户表
  void _createTableUser(batch) {
    batch.execute('''
          create table $tableName (
            $columnId integer primary key,
            $columnUserId integer,
            $columnName text,
            $columnAge integer )
          ''');
  }

  ///升级
  void _onUpgrade(db, oldVersion, newVersion) async {
    print("升级");
    var batch = db.batch();
    if (oldVersion == 1) {
      _updateTableUser(batch); //升级过程中也可以在此创建新表
    }
    await batch.commit();
  }

  ///user表增加性别字段
  void _updateTableUser(batch) {
    batch.execute('alter table $tableName add $columnSex text');
  }

  /// 插入数据
  Future<int> insert(user) async {
    return await db.insert(tableName, user.toMap());
  }

  /// 查询所有数据
  Future<List<User>> queryAll() async {
    List<Map> maps = await db.query(tableName, columns: null);
    if (maps == null || maps.length == 0) {
      return null;
    }
    List<User> users = List();
    for (int i = 0; i < maps.length; i++) {
      users.add(User.fromMap(maps[i]));
    }
    return users;
  }

  ///根据userId查询数据
  Future<User> getUser(userId) async {
    List<Map> maps = await db.query(tableName,
        columns: null, where: '$columnUserId = ?', whereArgs: [userId]);
    if (maps.length > 0) {
      return User.fromMap(maps.first);
    }
    return null;
  }

  /// 删除数据
  Future<int> delete(userId) async {
    return await db
        .delete(tableName, where: '$columnUserId = ?', whereArgs: [userId]);
  }

  /// 更新数据
  Future<int> update(user) async {
    return await db.update(tableName, user.toMap(),
        where: '$columnUserId = ?', whereArgs: [user.userId]);
  }

  /// 关闭数据库
  close() async {
    await db.close();
  }
}

测试用例:

import 'package:flutter/material.dart';

import 'bean/User.dart';
import 'header.dart';

class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> with TickerProviderStateMixin {
  SqlLite sqlLite = SqlLite();
  TextEditingController controller = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: Header(
        title: "首页",
        backgroundColor: Colors.grey,
      ),
      body: ListView(
        children: <Widget>[
          RaisedButton(
            onPressed: _insertData,
            child: Text("增加数据"),
          ),
          RaisedButton(
            onPressed: _deleteData,
            child: Text("删除数据"),
          ),
          RaisedButton(
            onPressed: _queryData,
            child: Text("修改数据"),
          ),
          RaisedButton(
            onPressed: _queryAll,
            child: Text("查询数据"),
          ),
        ],
      ),
    );
  }

  ///插入数据
  void _insertData() async {
    await sqlLite.openSqlLite();
    User u1 = User();
    u1.userId = 101;
    u1.name = "镜花水月1";
    u1.age = 31;
    await sqlLite.insert(u1);
    User u2 = User();
    u2.userId = 102;
    u2.name = "镜花水月2";
    u2.age = 32;
    await sqlLite.insert(u2);
    await sqlLite.close();
  }

  ///删除数据
  void _deleteData() async {
    await sqlLite.openSqlLite();
    await sqlLite.delete(102);
    await sqlLite.close();
  }

  ///修改数据
  Future _queryData() async {
    await sqlLite.openSqlLite();
    User user = await sqlLite.getUser(101);
    if (user != null) {
      user.name = "flutter";
      await sqlLite.update(user);
    }
    await sqlLite.close();
  }

  ///查询数据
  void _queryAll() async {
    await sqlLite.openSqlLite();
    List<User> users = await sqlLite.queryAll();
    if (users != null) {
      print(users);
    }
    await sqlLite.close();
  }
}
Flutter for OpenHarmony实战:口腔护理App今日任务模块开发全解析 跨端框架与本地数据持久化是移动应用开发的核心基础。在鸿蒙生态快速演进背景下,如何复用既有Flutter技术栈实现业务落地,成为众多团队关注焦点。本文从数据库设计、同步策略、状态管理到网络调试,系统梳理了在OpenHarmony上使用Flutter开发“今日任务”模块的完整工程实践。借助drift实现类型安全的本地存储与响应式数据流,结合Riverpod自动驱动UI刷新,有效解决了弱网环境下的任务打卡与数据一致性问题。同时针对鸿蒙原生能力兼容、抓包调试等现实挑战给出了可操作的解决方案,为跨端应用适配鸿蒙系统提 阅读详情

相关推荐

Flutter跨平台本地存储实战:OpenHarmony二手置换App数据库设计与适配

在Flutter跨平台开发中,本地存储是连接业务逻辑与系统能力的关键环节。从基础的数据分类出发,结构化数据适合交给SQLite这类关系型数据库管理,轻量状态用键值对存储,二进制图片则建议保存路径而非直接入库。理解查询、事务与数据库升级原理,是保证数据一致性和性能的前提。通过合理的Repository层封装,开发者能有效隔离底层差异,提升代码可维护性。本文以二手物品置换App为例,结合Android与OpenHarmony双平台适配经历,展示如何利用sqflite插件完成建表、增删改查、分页筛选及迁移升级,并

weixin_29628635的博客 321

Flutter 5 大本地数据库解决方案

Flutter 5 大本地数据库解决方案 原文 https://levelup.gitconnected.com/top-5-local-database-solutions-for-flutter-development-6351cd494070 前言 这里列出了最流行的数据库解决方案以及代码示例。 选择正确的数据管理系统对于提高效率和可 extension 性以及影响可用性和用户体验至关重要。尽管 flutter 仍然处于早期阶段,但是有很多数据管理解决方案可供选择,其中一些已经可以投入生产。我

会煮咖啡的猫咪 3346

0基础APP开发工作台搭建全攻略:从设计到打包一站式指南

移动应用开发已成为产品落地的重要环节,而一套完整、可落地的开发工作台是新手入门的关键。从环境配置、工具选型到跨平台开发框架,构建高效工作流需要理解设计、编码、调试与发布的协同原理。通过统一技术栈(如Dart/Flutter),开发者能够实现一次编写多端运行,大幅降低移动开发门槛。无论是原型设计、数据库管理还是接口联调,每个环节都有成熟的免费工具支撑。本文面向零基础学习者,系统梳理从设计到开发APP的全流程方案,帮助读者快速搭建属于自己的开发环境。

weixin_34072637的博客 451

Flutter本地数据库sqflite

一、 前言 sqflite是一款轻量级的数据库,用法类似于SQLite。 同时支持Android和iOS 二、引用 sqflite 版本:^2.0.0+4 功能:控制mp3文件播放。 地址:https://pub.dev/packages/sqflite 方法:数据库的操作。 三、使用 使用单例模式来进行操作。 增删改都含有事务处理。 1. 模型 final _version = 1;//数据库版本号 final _databaseName = "User.db";//数据库名称 final _tabl

鲸落 2960

高考后个人成长APP开发指南:Flutter+FastAPI技术实现与部署

在移动应用开发领域,前后端分离架构已成为主流技术范式,它通过清晰的API接口定义实现客户端与服务端的解耦。其核心原理在于客户端专注于用户界面与交互逻辑,服务端则负责数据处理与业务规则,二者通过RESTful API进行通信。这种架构的价值在于提升开发效率、便于团队协作,并能支持多端一致体验。在个人成长与学习管理类应用场景中,该技术栈能有效支撑目标追踪、习惯养成等核心功能。本文以高考后学生自我提升工具为具体案例,详细解析如何运用Flutter与FastAPI技术栈,结合SQLite数据库,实现一个具备任务管理

weixin_34293246的博客 427

升级固件方法:Android详细教程

在开始升级之前,我们强烈建议您先备份您设备上的所有重要数据。通过以下步骤,您将能够更新您的Android设备以获取最新的功能和安全补丁。一旦设备重新启动,并应用了新的固件,您可以验证固件升级是否成功。检查设备的设置菜单中的固件版本,确认是否与您下载的固件版本相匹配。在进行固件升级之前,请确保阅读设备制造商提供的官方文档和说明。将您的Android设备连接到计算机,以便通过计算机进行固件升级。在升级之前,您需要检查是否有可用的固件更新。在手动升级固件之前,您需要启用设备的开发者选项。

HackDashX的博客 1458

flutter开发实战-本地SQLite数据存储

flutter开发实战-本地SQLite数据库存储正在编写一个需要持久化且查询大量本地设备数据的 app,可考虑采用数据库。相比于其他本地持久化方案来说,数据库能够提供更为迅速的插入、更新、查询功能。这里需要用到sqflite package 来使用 SQLite 数据库预览图。

一名开发者 2134

Flutter 集成uni-app

众所周知,不管是Flutter还是uni-app,其实都是一个UI框架,他们都是运行在原生系统之上的。自然,我们可以在Flutter工程中集成uni-app。 一、下载离线SDK 首先,我们创建一个Flutter普通应用,并使用Android Studio打开Android工程。接下来,打开uni-app官网https://nativesupport.dcloud.net.cn/AppDocs/download/android下载最新离线sdk,如下图所示。 解压后,可以使用Android Studio打

xiangzhihong8的专栏 3979

Flutter对原生app接入Flutter进行了优化和升级

概述 使用Flutter从零开始开发App是一件轻松惬意的事情,但对于一些成熟的产品来说,完全摒弃原有App的历史沉淀,全面转向Flutter是不现实的。因此使用Flutter去统一Android、iOS技术栈,把它作为已有原生App的扩展能力,通过有序推进来提升移动终端的开发效率。 目前,想要在已有的原生App里嵌入一些Flutter页面主要有两种方案。一种是将原生工程作为Flutter工程的子工程,由Flutter进行统一管理,这种模式称为统一管理模式。另一种是将Flutter工程作为原生工程的子模块

Android格调小窝 1037

基于python的超市历年数据可视化分析

包含:Order_Date Sales Quantity Profit year month。所有这些物品都在美国4个地区的49个州销售,来着793位客户的5009个订单。9994行,21列数据。

m0_74872863的博客 535

基于ESP32的气象雷达站设计与实现

物联网技术通过嵌入式设备实现环境数据的实时采集与可视化,其中ESP32凭借其双核处理器和WiFi/蓝牙功能成为热门选择。本项目利用ESP32结合LVGL图形库,构建了一个低成本气象监测系统,通过OpenWeatherMap API获取全球气象数据并在7英寸触摸屏上动态展示。系统采用三级优化策略处理高分辨率雷达图,包括服务端预处理、硬件加速解码和显示增强,有效解决了内存占用和帧率问题。在物联网设备开发中,类似方案可应用于智能家居、农业监测等场景,特别是需要实时数据可视化的领域。通过SPIFFS存储和zlib压

weixin_42524864的博客 422

Flutter 接入 Firebase Realtime Database:基于 using_firebase_db 的实时笔记应用实战

本文以 flutter-examples 仓库中的 [using_firebase_db](https://link.gitcode.com/i/b448aaf96e0b74895c6fe3b2d50f6b0e) 示例项目为主体,完整讲解如何在 Flutter 应用中集成 Firebase Realtime Database,并实现一个「新增笔记、实时同步、长按删除」的迷你笔记应用。通过阅读本文,

gitblog_00670的博客 407

FI 应计对象的创建和摊销

创建/修改:ACACTREE01/ACACTREE02 应计对象的过账:ACACPOSTING

nancyln9711的博客 903

Flutter本地数据库SQLite的ORM工具floor使用

Flutter本地持久化存储数据库SQLite,使用不够便捷,特别升级迁移时。插件floor是一个数据库orm工具,让我们可以轻松愉快的使用数据库,基本满足日常使用,让我们一起看看如何使用以及会有哪些坑

aberciozhang的博客 3044

基于卷积神经网络的人脸识别算法

摘要:近年来,随着科学技术的不断发展,人脸识别技术日渐成熟,使得人脸识别技术的使用率不断增大。例如:门禁、ATM机、公安系统以及新兴起的人机交互等领域,都应用到了人脸识别系统。在人脸识别研究领域中,深度学习扮演着重要的角色。由于深度学习的人脸识别技术凭借其识别率高、识别快等特点,逐渐成为整个领域的主流技术。在众多深度学习算法中,以卷积神经网络为代表的人脸识别系统得到了广泛应用,主要研究内容如下:首先,通过对经典损失函数进行研究,对比每种损失函数的特点,然后根据A-Softmax函数进行改进,借助Margin

yyq2263511327的博客 1万+

sentaurus学习笔记(一)器件仿真

之前有跟大家说,以后转到sentaurus,因此silvaco会用的比较少,结果发现真的有一点贪心厌旧的感觉,现在基本上不用silvaco(lll¬ω¬)故这篇文章,将为大家带来的是关于sentaurus的结构仿真和器件的特性的提取。我们还是老规矩,先上结构图。 还是一个经典的IGBT结构,这是一个典型的N型IGBT,下面我将把一些相关的结构,和具体的写法用下面一幅图表达出来。 这里因为方便看,我们把器件的比例画的比较抽象。可以看到的是,这里有很多的距离参数是用一些变量名来写的,这也是sentaurus

weixin_43262021的博客 2万+

利用好Android 15升级的好机会

前几天不是关注了一下鸿蒙系统吗顺带发现很多人也提到了Android 15升级的事情本来这个一年一度的开发者不得不做的适配没啥好说的但是这个版本略微有些特殊,所以说一下。

developer_laoliu的博客 1998

1.14、基于NARX神经网络的磁悬浮建模(matlab)

数据准备:首先,需要准备用于训练和测试的磁悬浮系统的输入和输出数据,包括磁力、电流、位置、速度等信息。数据可以被保存在MATLAB的数据文件中,并加载到工作空间中。使用MATLAB的神经网络工具箱,创建一个NARX神经网络。需要定义网络的层次结构、节点数、激活函数等参数。通常,NARX网络包括自回归层和外部输入层。数据预处理:对加载的数据进行预处理,包括去除噪声、归一化处理等操作,以确保数据质量和网络训练的稳定性。使用MATLAB的训练函数,如trainlm或者trainbr,对NARX神经网络进行训练。

XU157303764的博客 1998

Qwen-Image-Edit-Rapid-AIO:ComfyUI 一站式 Qwen 图像编辑模型,4 步 CFG 1 出图

本仓库提供 ComfyUI 的 Qwen 图像编辑与文生图合并模型:4 步推理、CFG 固定为 1、FP8 精度,一个 Load Checkpoint 节点跑通完整工作流,收录 v1 至 v23 共 23 个大版本。 ## 使用门槛:环境要求与模型获取 这套模型省事的原因在于:作者把 Lightning 加速 LORA、VAE、CLIP 文本编码器合并进了同一个 checkpoint。平时在

gitblog_00361的博客 932

ESP32-C3模组上实现蓝牙BLE配网功能(1)

ESP32-C3模组上实现蓝牙BLE配网功能(1)

phmatthaus的专栏 2279

数据分析案例-汽车客户信息数据可视化分析

本数据集来源于kaggle,原始数据集共有8068条,11个特征变量,各变量含义解释如下:ID:客户IDGender:客户性别Ever_Married:客户婚姻状况Age:客户年龄Graduated:客户是毕业生吗?Profession:客户的职业Work_Experience:多年工作经验Spending_Score:客户的消费评分Family_Size:客户家庭成员人数(含客户)Var_1:客户的匿名类别Segmentation:(目标)客户的客户群。

m0_64336780的博客 1万+

基于Flutter的跨平台漫画阅读器开发:从架构到实现

网络爬虫和API接口调用是数据聚合的核心技术,它们通过自动化请求与解析,高效地从分散的源站获取结构化信息。其技术价值在于解决了信息孤岛问题,实现了资源的统一访问与呈现。在移动应用开发领域,结合跨平台UI框架,可以快速构建功能一致的双端应用。例如,利用Flutter框架和cached_network_image等插件,开发者能够高效实现图片的加载、缓存与流畅展示,这正是构建聚合类内容阅读应用的关键。本文即围绕如何运用这些技术,实现一个聚合多源、支持高清阅读且体验流畅的漫画阅读工具展开,详细剖析了其从数据获取、

weixin_33827731的博客 361

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

Spotube:基于Flutter的开源跨平台音乐流媒体架构深度解析

Spotube是一款采用Flutter框架构建的开源跨平台音乐流媒体应用,通过创新的插件化架构实现了音乐元数据与音频源的分离。该项目不仅提供了完整的桌面端和移动端音乐播放体验,更重要的是建立了一个可扩展的音乐生态系统,让用户能够自由选择音乐来源和元数据服务。 ## 架构设计与技术选型 ### Flutter框架的跨平台优势 Spotube选择Flutter作为核心开发框架,这一决策带来了多方

gitblog_00178的博客 994

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

flutter_tflite部署避坑清单:Android和iOS上必须知道的5个构建错误

flutter_tflite 是接入 TensorFlow Lite 的 Flutter 插件,支持图像分类、目标检测、Deeplab 分割与 PoseNet 姿态估计。但在 Android 与 iOS 双端部署时,构建错误是最劝退新手的环节。本文整理了 5 个最高频的构建错误及其一键修复方法,帮你少走弯路。 ## 1. Android 打包报 verifyReleaseResources 失败

gitblog_00796的博客 475

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

DLSS Swapper 使用指南:不更新游戏,自由切换 DLSS、FSR、XeSS 版本

DLSS Swapper 是一款 Windows 桌面工具,专门下载和管理游戏里的图像增强 DLL,让 DLSS(NVIDIA 的超采样画质增强技术)、FSR(AMD 的同类方案)和 XeSS(Intel 的方案)随时升级或降级,全程不用等游戏官方更新。它解决两类痛点:嫌老游戏自带的增强版本太旧,或者新版更新后翻车想回退。普通玩家按步骤点几下就能用,想弄清"游戏里那几个 dll 到底从哪来"的折腾

gitblog_00058的博客 564

如何一次性理顺Windows右键菜单:免费开源工具ContextMenuManager快速上手

试着右键一个文件,看看菜单有多长?如果是两屏起步,想找到"重命名"还得滚一次鼠标轮,那说明该收拾了。ContextMenuManager 是一款免费的开源 Windows 右键菜单管理工具,绿色免安装,专门用来启用或禁用、修改、新增右键菜单项。它只盯着右键菜单这一件事,不碰系统设置,也不批量扫盘。 ## 三分钟跑起来的步骤 1. **获取程序**。它不是传统安装程序:从仓库发布页下载 zip

gitblog_00103的博客 715
上一篇: 刷新加载库
下一篇: 视频播放
尘彦
博客等级 码龄11年 92粉丝 22原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

打赏作者

尘彦

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

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

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

打赏作者

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

抵扣说明:

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

余额充值