2024-09-02 ほぼOK

This commit is contained in:
2024-09-02 21:25:19 +09:00
parent dc58dc0584
commit fe46d46ab6
59 changed files with 2006 additions and 677 deletions

View File

@ -13,6 +13,11 @@ class DatabaseHelper {
static Database? _database;
Future<Database> get database async => _database ??= await _initDatabase();
// データベース初期化:
//
// シングルトンパターンを使用してDatabaseHelperのインスタンスを管理しています。
// _initDatabase()メソッドでデータベースを初期化し、必要なテーブルを作成します。
//
Future<Database> _initDatabase() async {
Directory documentDirectory = await getApplicationDocumentsDirectory();
String path = join(documentDirectory.path, 'rog.db');
@ -30,7 +35,10 @@ class DatabaseHelper {
onCreate: _onCreate);
}
// DBを初期化する際に、必要なテーブルを作成します。
//
Future _onCreate(Database db, int version) async {
// destinationテーブル: 目的地の情報を保存(位置、名前、住所、連絡先情報など)。
await db.execute('''
CREATE TABLE destination(
location_id INTEGER PRIMARY KEY,
@ -63,6 +71,7 @@ class DatabaseHelper {
)
''');
// rogainingテーブル: ロゲイニングorienteering的なアクティビティの記録を保存。
await db.execute('''
CREATE TABLE rogaining(
rog_id INTEGER PRIMARY KEY AUTOINCREMENT,
@ -76,6 +85,7 @@ class DatabaseHelper {
)
''');
// rogテーブル: ロゲイニングのチェックポイント情報を保存。
await db.execute('''
CREATE TABLE rog(
id INTEGER PRIMARY KEY AUTOINCREMENT,
@ -138,6 +148,22 @@ class DatabaseHelper {
await db.delete('rog');
}
Future<void> deleteAllRogainingExceptToday() async {
Database db = await instance.database;
// 今日の開始時刻をエポックミリ秒で取得
final now = DateTime.now();
final startOfDay = DateTime(now.year, now.month, now.day).millisecondsSinceEpoch;
// 今日チェックインしたもの以外を削除
await db.delete(
'rog',
where: 'checkintime < ?',
whereArgs: [startOfDay]
);
}
Future<bool> isRogAlreadyAvailable(int id) async {
Database db = await instance.database;
var rog = await db.query('rog', where: "id = $id");
@ -229,6 +255,27 @@ class DatabaseHelper {
await db.delete('destination');
}
Future<void> deleteAllDestinationsExceptTodayCheckins() async {
Database db = await instance.database;
// 今日の開始時刻をエポックからのミリ秒で取得
final now = DateTime.now();
final startOfDay = DateTime(now.year, now.month, now.day).millisecondsSinceEpoch;
// 今日チェックインされ、buy_pointを持つ目的地を除いて全て削除
await db.rawDelete('''
DELETE FROM destination
WHERE location_id NOT IN (
SELECT d.location_id
FROM destination d
JOIN rog r ON d.location_id = r.cp_number
WHERE date(r.checkintime / 1000, 'unixepoch', 'localtime') = date('now', 'localtime')
AND d.buy_point > 0
AND d.checkedin = 1
)
''', [startOfDay]);
}
Future<bool> isAlreadyAvailable(int locationId) async {
Database db = await instance.database;
var dest =

View File

@ -129,20 +129,25 @@ class LocationController extends GetxController {
// 現在位置を調整するメソッドを追加
LatLng? adjustCurrentLocation(Position? position) {
if (position == null) {
if (position == null) { // positionがnullなら、lastValidLocationを使用する。
if( lastValidLocation!=null ) {
debugPrint("== 現在位置なし。最後の位置を使用 ==");
//debugPrint("=== adjustCurrentLocation (Position:Null and using LastValidLocation ${lastValidLocation})===");
return LatLng(lastValidLocation!.latitude, lastValidLocation!.longitude);
}else {
print("=== adjustCurrentLocation (Position:Null and No LastValidLocation ... )===");
debugPrint("== 現在位置なし。最後の位置も無し ==");
//print("=== adjustCurrentLocation (Position:Null and No LastValidLocation ... )===");
return null;
}
//return lastValidLocation ?? LatLng(0, 0);
}
final signalStrength = getGpsSignalStrength(position);
if (signalStrength == 'high' || signalStrength == 'medium') {
debugPrint("== 信号強度 ${signalStrength} ==> 最新位置を使用 ==");
//debugPrint("=== adjustCurrentLocation (Position:Get and return Valid location:${position} ... )===");
lastValidLocation = LatLng(position.latitude, position.longitude);
}else{
debugPrint("== 信号強度 ${signalStrength} ==> 最後の位置を使用 ==");
}
return lastValidLocation ?? LatLng(lastValidLocation!.latitude, lastValidLocation!.longitude);
}
@ -169,10 +174,39 @@ class LocationController extends GetxController {
void onInit() {
super.onInit();
// Start listening to location updates when the controller is initialized
startPositionStream();
_initLocationService();
}
Future<void> _initLocationService() async {
try {
bool serviceEnabled;
LocationPermission permission;
serviceEnabled = await Geolocator.isLocationServiceEnabled();
if (!serviceEnabled) {
return Future.error('Location services are disabled.');
}
permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied) {
permission = await Geolocator.requestPermission();
if (permission == LocationPermission.denied) {
return Future.error('Location permissions are denied');
}
}
if (permission == LocationPermission.deniedForever) {
return Future.error(
'Location permissions are permanently denied, we cannot request permissions.');
}
startPositionStream();
} catch( e ){
print('Error initializing location service: $e');
}
}
// 位置情報のストリームを開始するメソッドです。
// 位置情報サービスが有効か確認し、無効な場合はダイアログを表示します。
// 位置情報の権限を確認し、必要な権限がない場合は権限をリクエストします。
@ -185,7 +219,26 @@ class LocationController extends GetxController {
// 2024-4-8 Akira : See 2809
// stopPositionStreamメソッドを追加して、既存のストリームをキャンセルするようにしました。また、ストリームが完了したらnullに設定し、エラー発生時にストリームをキャンセルするようにしました。
//
void startPositionStream() async {
void startPositionStream() {
positionStream = Geolocator.getPositionStream(
locationSettings: const LocationSettings(
accuracy: LocationAccuracy.high,
distanceFilter: 5, //10, 10mから5mに変更
),
).listen((Position position) {
currentPosition.value = position;
//debugPrint("== startPositionStream: ${position} ==");
locationMarkerPositionStreamController.add(
LocationMarkerPosition(
latitude: position.latitude,
longitude: position.longitude,
accuracy: position.accuracy,
),
);
});
}
void startPositionStream_old() async {
// Check for location service and permissions before starting the stream
// 位置情報サービスの有効性をチェックし、無効な場合はエラーハンドリングを行います。
//

View File

@ -0,0 +1,89 @@
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:get/get.dart';
import 'dart:async';
void _performMemoryCleanup() {
//debugPrint('Performing memory cleanup');
// キャッシュのクリア
Get.deleteAll(); // GetXを使用している場合、すべてのコントローラをクリア
imageCache.clear(); // 画像キャッシュをクリア
imageCache.clearLiveImages(); // 使用中の画像キャッシュをクリア
// 大きなオブジェクトの解放
_clearLargeObjects();
// 未使用のリソースの解放
_releaseUnusedResources();
// ガベージコレクションの促進
_forceGarbageCollection();
debugPrint('Memory cleanup completed');
}
void _clearLargeObjects() {
// 大きなリストやマップをクリア
// 例: myLargeList.clear();
// 例: myLargeMap.clear();
}
void _releaseUnusedResources() {
// 使用していないストリームのクローズ
// 例: myStream?.close();
// 未使用のアニメーションコントローラーの破棄
// 例: myAnimationController?.dispose();
// テキスト編集コントローラーの破棄
// 例: myTextEditingController?.dispose();
}
void _forceGarbageCollection() {
// Dart VMにガベージコレクションを促す
Timer(const Duration(seconds: 1), () {
//debugPrint('Forcing garbage collection');
// この呼び出しは必ずしもガベージコレクションを即座に実行するわけではありませんが、
// Dart VMにガベージコレクションの実行を強く促します。
// ignore: dead_code
bool didRun = false;
assert(() {
didRun = true;
return true;
}());
if (didRun) {
//debugPrint('Garbage collection forced in debug mode');
}
});
}
// メモリ使用量を監視し、必要に応じてクリーンアップを実行する関数
void startMemoryMonitoring() {
const Duration checkInterval = Duration(minutes: 5);
Timer.periodic(checkInterval, (Timer timer) {
_checkMemoryUsage();
});
}
void _checkMemoryUsage() async {
// ここでメモリ使用量をチェックするロジックを実装
// 例えば、プラットフォーム固有の方法でメモリ使用量を取得する
// 仮の閾値(実際のアプリケーションに応じて調整が必要)
const int memoryThreshold = 100 * 1024 * 1024; // 100 MB
// 仮のメモリ使用量チェック(実際の実装に置き換える必要があります)
int currentMemoryUsage = await _getCurrentMemoryUsage();
if (currentMemoryUsage > memoryThreshold) {
debugPrint('High memory usage detected: $currentMemoryUsage bytes');
_performMemoryCleanup();
}
}
Future<int> _getCurrentMemoryUsage() async {
// プラットフォーム固有のメモリ使用量取得ロジックを実装
// この例では仮の値を返しています
return 150 * 1024 * 1024; // 仮に150MBとする
}