Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions sql_db/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/

# IntelliJ related
*.iml
*.ipr
*.iws
.idea/

# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/

# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/build/

# Web related
lib/generated_plugin_registrant.dart

# Symbolication related
app.*.symbols

# Obfuscation related
app.*.map.json

# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release
10 changes: 10 additions & 0 deletions sql_db/.metadata
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.

version:
revision: 8328b56ef37c511097545f24a054b6abe7631b0b
channel: master

project_type: app
113 changes: 113 additions & 0 deletions sql_db/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# sql_db

flutter에서 sqldb 사용법을 배운다.
예제는 구글링에서 찾은 [블로그](https://suragch.medium.com/simple-sqflite-database-example-in-flutter-e56a5aaa3f91)를 기본으로 한다.

## 의존성
sqflite와 path_provider가 필요하다.
sql이 아니고 sqf이다. 파일db라서 그런것인가??
path_provider는 문서 디렉토리를 찾기 위해 사용된다.
```
sqflite: ^1.2.0
path_provider: ^1.5.1
```

## 데이터베이스 헬퍼 클래스
우선 눈에 띄는 부분이 싱클톤 객체로 만드는 부분이다.
코드와 주석은 이해가 되는데, _privateConstructor();이게 공식적인 문법인지 애매하다.
구글링을 해봐도 명확하게 나오지는 않는데, 코드 실행상 이상이 없으니 맞겠죠??
```
// make this a singleton class
DatabaseHelper._privateConstructor();
static final DatabaseHelper instance = DatabaseHelper._privateConstructor();
```

실제 instance부분은 싱글톤 객체로 유일한 데이터접근 경로인것이고,
실제 데이터베이스 객체는 아래와 같이 선언되어 있다.

역시 static으로 선언되어 있고, get을 할때 최초 한번 초기화를 수행한다.
초기화에는 데이터베이스 생성을 위한 ddl도 포함되어 있다.
테이블 구조는 목적에 맞게 정의하되, app이기때문에 너무 복잡한 구조는 피하게 좋을듯 하다.
```
// only have a single app-wide reference to the database
static Database _database;
Future<Database> get database async {
if (_database != null) return _database;
// lazily instantiate the db the first time it is accessed
_database = await _initDatabase();
return _database;
}

// this opens the database (and creates it if it doesn't exist)
_initDatabase() async {
Directory documentsDirectory = await getApplicationDocumentsDirectory();
String path = join(documentsDirectory.path, _databaseName);
return await openDatabase(path,
version: _databaseVersion, onCreate: _onCreate);
}

// SQL code to create the database table
Future _onCreate(Database db, int version) async {
await db.execute('''
CREATE TABLE $table (
$columnId INTEGER PRIMARY KEY,
$columnName TEXT NOT NULL,
$columnAge INTEGER NOT NULL
)
''');
}
```

## 데이터베이스 CRUD
실제 sql과는 조금 다르다.
orm같은 느낌이 더 강하다.
간단한 코드저장/select 용도이기 때문에 크게 문제가 없을것 같다.
실제 SQL도 되는것 같지만, 코드 샘플상 sql보다는 프로그램코드를 권장하는 느낌이다.
(당연히 app개발 영역이니 복잡한 sql보다 심플한 코드가 선호되는게 맞다고 본다.)
```
// All of the rows are returned as a list of maps, where each map is
// a key-value list of columns.
Future<List<Map<String, dynamic>>> queryAllRows() async {
Database db = await instance.database;
return await db.query(table);
}

// All of the methods (insert, query, update, delete) can also be done using
// raw SQL commands. This method uses a raw query to give the row count.
Future<int> queryRowCount() async {
Database db = await instance.database;
return Sqflite.firstIntValue(
await db.rawQuery('SELECT COUNT(*) FROM $table'));
}

// We are assuming here that the id column in the map is set. The other
// column values will be used to update the row.
Future<int> update(Map<String, dynamic> row) async {
Database db = await instance.database;
int id = row[columnId];
return await db.update(table, row, where: '$columnId = ?', whereArgs: [id]);
}
```


## 데이터 베이스 사용
싱글턴객체를 통해서 일단 데이터베이스 객체를 구한다.
그리고, 선언된 crud 메소드를 통해 실제 database객체로 접근하도록 가이드 되고 있다.
```
// reference to our single class that manages the database
final dbHelper = DatabaseHelper.instance;

...
...

void _insert() async {
// row to insert
Map<String, dynamic> row = {
DatabaseHelper.columnName: 'Bob',
DatabaseHelper.columnAge: 23
};
final id = await dbHelper.insert(row);
print('inserted row id: $id');
}

```
11 changes: 11 additions & 0 deletions sql_db/android/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java

# Remember to never publicly share your keystore.
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
key.properties
63 changes: 63 additions & 0 deletions sql_db/android/app/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}

def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}

def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}

def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"

android {
compileSdkVersion 29

sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}

lintOptions {
disable 'InvalidPackage'
}

defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.example.sql_db"
minSdkVersion 16
targetSdkVersion 29
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}

buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
}
}
}

flutter {
source '../..'
}

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
7 changes: 7 additions & 0 deletions sql_db/android/app/src/debug/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.sql_db">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
41 changes: 41 additions & 0 deletions sql_db/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.sql_db">
<application
android:label="sql_db"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<!-- Displays an Android View that continues showing the launch screen
Drawable until Flutter paints its first frame, then this splash
screen fades out. A splash screen is useful to avoid any visual
gap between the end of Android's launch screen and the painting of
Flutter's first frame. -->
<meta-data
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/launch_background"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.example.sql_db

import io.flutter.embedding.android.FlutterActivity

class MainActivity: FlutterActivity() {
}
12 changes: 12 additions & 0 deletions sql_db/android/app/src/main/res/drawable/launch_background.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" />

<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 18 additions & 0 deletions sql_db/android/app/src/main/res/values-night/styles.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>
18 changes: 18 additions & 0 deletions sql_db/android/app/src/main/res/values/styles.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.

This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>
7 changes: 7 additions & 0 deletions sql_db/android/app/src/profile/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.sql_db">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
31 changes: 31 additions & 0 deletions sql_db/android/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
buildscript {
ext.kotlin_version = '1.3.50'
repositories {
google()
jcenter()
}

dependencies {
classpath 'com.android.tools.build:gradle:3.5.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}

allprojects {
repositories {
google()
jcenter()
}
}

rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}

task clean(type: Delete) {
delete rootProject.buildDir
}
Loading