Flutter Web Service Client Sample 範例 (續) – 自動儲存和載入最後一次查詢條件

承前一天的查詢方塊功能,透過 SharedPreferences 套件儲存和載入查詢的條件。讓 App開啟時自動載入最後一次的查詢條件。(此機制常用於儲存使用者的登入帳號密碼並自動登入)

daos/shared_preferences_dao.dart

import 'package:shared_preferences/shared_preferences.dart';

class SharedPreferencesDao {
static SharedPreferences? _prefs;

static void initialize() async {
_prefs ??= await SharedPreferences.getInstance();
}

static String getSearchKey() {
String? searchKey;
if(_prefs != null) {
searchKey = _prefs!.getString("searchKey");
}
searchKey ??= '';

return searchKey;
}

static void setSearchKey(String searchKey) {
if(_prefs != null) {
_prefs!.setString("searchKey", searchKey);
}
}
}

daos/post_dao.dart

import 'package:webservice_client/models/post.dart';
import 'package:http/http.dart' as http;
import 'package:webservice_client/daos/shared_preferences_dao.dart';
import 'dart:convert';

class PostDao {
static Future<List<Post>> getPostsAndInitializeSharedPreferences() async {
SharedPreferencesDao.initialize();

var url = Uri.parse('https://jsonplaceholder.typicode.com/posts');
var response = await http.get(url);

List<Post> posts = (jsonDecode(response.body) as List<dynamic>).map((jsonObject) {
return Post.fromJson(jsonObject);
}).toList();

return posts;
}
}

components/post_table_with_search.dart

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:webservice_client/daos/shared_preferences_dao.dart';
import 'package:webservice_client/models/post.dart';

// ignore: must_be_immutable
class PostTableWithSearch extends StatefulWidget {
PostTableWithSearch(this.posts, {super.key});
List<Post> posts;

@override
State createState() {
return _PostTableWithSearch();
}
}

class _PostTableWithSearch extends State<PostTableWithSearch> {
String filterInput = '';
List<Post> filteredPosts = [];

void changeFilteredPosts(String userInput) {
filterInput = userInput;
filteredPosts = widget.posts.where(
(element) {
if(userInput == '') {
return true;
}
else if(element.title.contains(userInput)) {
//print(element.title);
return true;
}
else {
return false;
}
},
).toList();

if(filteredPosts.isEmpty) {
filteredPosts.add(Post(0, 0, "查無資料", "查無資料"));
}

SharedPreferencesDao.setSearchKey(userInput);
}

@override
void initState() {
super.initState();

filterInput = SharedPreferencesDao.getSearchKey();
}

@override
Widget build(BuildContext context) {

if(filteredPosts.isEmpty) {
changeFilteredPosts(filterInput);
}

var searchTextEditingController = TextEditingController()..text = filterInput;

Widget searchBar = TextField(
controller: searchTextEditingController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
hintText: 'Enter a search term'
),
onSubmitted: (userInput){
setState(() {
changeFilteredPosts(userInput);
});
},
);

// Convert object variables to data column list
List<String> columnNames = (jsonDecode(filteredPosts[0].toJsonObjectString()) as Map<String, dynamic>).keys.toList();
List<DataColumn> dataColumns = columnNames.map((key) {
return DataColumn(label: Text(key));
},).toList();

// Convert object variables to data row list
List<DataRow> dataRows = filteredPosts.map((post) {
Map<String, dynamic> postJson = jsonDecode(post.toJsonObjectString()) as Map<String, dynamic>;
List<DataCell> dataCells = columnNames.map((key){
return DataCell(
Text(postJson[key].toString()));
}).toList();

return DataRow(cells: dataCells);
},).toList();

return SingleChildScrollView(
child: Container(
alignment: Alignment.topCenter,
child: Column(children: [
SizedBox(
width: 800,
child: searchBar,
),
SizedBox(
width: 800,
child: DataTable(columns: dataColumns, rows: dataRows),
)
]),
),
);
}
}

screens/post_screen.dart

import 'package:flutter/material.dart';
import 'package:webservice_client/components/post_table_with_search.dart';
import 'package:webservice_client/daos/post_dao.dart';
import 'package:webservice_client/models/post.dart';

class PostScreen extends StatefulWidget {
const PostScreen({super.key});



@override
State createState() {
return _PostScreen();
}
}

class _PostScreen extends State<PostScreen> {
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: PostDao.getPostsAndInitializeSharedPreferences(),
builder: (BuildContext context, AsyncSnapshot<List<Post>> asyncSnapshot) {
List<Post> posts = [];
if(asyncSnapshot.connectionState == ConnectionState.done) {
posts = asyncSnapshot.requireData;

return Scaffold(
body: PostTableWithSearch(posts),
);
}
else if(asyncSnapshot.hasError) {
return const Scaffold(body: Text('Initial data fail!'),);
}
else {
return const Scaffold();
}
}
);
}
}

pubspec.yaml

name: webservice_client
description: "A http client sample project."
publish_to: 'none'
version: 0.1.0+1

environment:
sdk: '>=3.2.6 <4.0.0'

dependencies:
flutter:
sdk: flutter
http: ^0.13.4
shared_preferences: ^2.0.8

dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^2.0.0

flutter:
uses-material-design: true

留言

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.