Flutter-保存用户数据 [英] Flutter - Saving user data
问题描述
我目前正在创建一个应用程序,该应用程序可以跟踪常规的加密数据,并与这些数据一起发布针对加密爱好者的新闻报道。该新闻文章数据的各个方面都以字符串形式存储,从图片网址到发布日期-下面的完整列表。
我正在寻找一种将数据保存到用户设备的方法。在理想情况下,我只是将这些数据保存在JSON数组中,但是除了不知道如何执行此操作之外,我不确定这是否是保存此数据以供以后显示的最有效方法。
如果您认为JSON是保存此数据的最佳方法,那么我只需要知道如何正确地将数据管理到一系列不同的已保存文章中,以及如何将其导入正确地放入我的Dart代码中
此代码示例很好,我希望在新年之前发布此应用,因此我需要获得所有帮助。非常感谢。
这是我希望从
I'm currently creating an application that tracks general crypto data, along with this data we also post news articles tailored to crypto enthusiasts. Every aspect of this news article data is stored in string form, from image url to date published - full list below.
I'm looking for a way to save this data to the user's device. In a perfect situation I'd just have this data saved in a JSON array, but apart from not knowing how to perform this, I'm not sure if it's the most efficient way to save this data for later display.
If you decide that JSON would be the best way of saving this data, all I need to know is how to properly manage this data into an array of different saved articles and how to import this properly into my Dart code.
An example of this code would be great, I'm looking to publish this app before the new year so I need all the help I can get. Many thanks.
This is the aforementioned data I'm looking to save / display from this source:
- Source -
source
- Author -
author
- Description -
description
- Date Published -
publishedAt
- Article Title -
title
- Url to Article -
url
- Article Image -
urlToImage
Edit: Trying to rework shadowsheep's answer to fit an index model
Each news widget is a new inkwell
that allows a new scaffold
to be built. From this scaffold
you are presented with the option to save the article. On saving, the code currently just changes the value of the following strings with the title
, description
, URL
and Image URL
.
_sTitle
_sDescription
_sURL
_sURLtoImage
I would really like a way of having the database, as described by shadowsheep, saved to the user's device. This means that the saved articles will become persistent on the device despite the user closing and opening the app.
The following code is the exact use case in which I'm displaying my news data.
CarouselSlider(
items: [1,2,3,4,5,6,7,8,9,10].map((index) {
return Builder(
builder: (BuildContext context) {
return Padding(
padding: EdgeInsets.only(
top: 5.0,
bottom: 20.0,
),
child: InkWell(
borderRadius: BorderRadius.only(
topLeft: const Radius.circular(15.0),
topRight: const Radius.circular(15.0),
),
onTap: () {
print('Opened article scaffold: "' + articles[index].title + "\"");
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Scaffold(
resizeToAvoidBottomPadding: false,
appBar: AppBar(
backgroundColor: const Color(0xFF273A48),
elevation: 0.0,
title: Container(
width: _width*0.90,
height: 30,
padding: const EdgeInsets.only(
bottom: 5,
top: 5,
left: 10,
right: 10,
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(10.0),
),
),
alignment: Alignment.center,
child: AutoSizeText(
'Published ' + DateFormat.yMMMd().format(DateTime.parse(articles[index].publishedAt)) + ", "+ DateFormat.jm().format(DateTime.parse(articles[index].publishedAt)),
overflow: TextOverflow.ellipsis,
maxLines: 1,
minFontSize: 5,
maxFontSize: 20,
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.black,
fontFamily: 'Poppins',
),
),
),
),
body: Center(
child: Scaffold(
resizeToAvoidBottomPadding: false,
body: Center(
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
const Color(0xFF273A48),
Colors.blueGrey
],
),
),
padding: const EdgeInsets.only(
top: 20,
left: 10,
right: 10,
bottom: 50
),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
FutureBuilder<Null>(future: _launched, builder: _launchStatus),
AutoSizeText(
articles[index].title,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center,
maxFontSize: 30,
minFontSize: 15,
maxLines: 3,
style: TextStyle(
color: Colors.white,
fontFamily: 'Poppins',
),
),
Divider(
color: Colors.transparent,
height: 15.0,
),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15.0),
color: Colors.transparent,
boxShadow: [
BoxShadow(
color: Colors.black.withAlpha(70),
blurRadius: 50.0,
)
],
image: DecorationImage(
image: NetworkImage(articles[index].urlToImage),
fit: BoxFit.fitHeight,
),
),
height: 220,
width: 317.5,
),
Divider(
color: Colors.transparent,
height: 15.0,
),
],
),
Container(
padding: const EdgeInsets.only(
left: 20,
right: 20
),
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius: BorderRadius.all(
Radius.circular(10.0),
),
),
child: AutoSizeText(
articles[index].description,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center,
maxFontSize: 30,
minFontSize: 10,
maxLines: 10,
style: TextStyle(
color: Colors.white,
fontFamily: 'Poppins',
),
),
width: _width*0.90,
height: _height*0.20,
),
Container(
padding: const EdgeInsets.all(4.0),
decoration: BoxDecoration(
color: const Color(0xFF273A48),
borderRadius: BorderRadius.all(
Radius.circular(10.0),
),
),
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
IconButton(
icon: Icon(
Icons.favorite_border,
color: Colors.red
),
iconSize: 35.0,
onPressed: () {
_sTitle = articles[index].title;
_sDescription = articles[index].description;
_sURL = articles[index].url;
_sURLtoImage = articles[index].urlToImage;
Navigator.push(
context,
MaterialPageRoute(builder: (context) => _favoritesScreen())
);
}
),
IconButton(
icon: Icon(
Icons.mobile_screen_share,
color: Colors.white,
),
iconSize: 35.0,
onPressed: () {
Share.share(
articles[index].title + "\n\nCheck out this article at:\n" + articles[index].url + "\n\nLearn more with Cryp - Tick Exchange",
);
}
),
IconButton(
icon: Icon(Icons.launch, color: Colors.lightBlueAccent),
iconSize: 32.5,
onPressed: () => setState(() { _launched = _launchInWebViewOrVC(articles[index].url);}),
),
],
),
),
],
),
),
),
),
),
)
)
);
},
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.0),
color: const Color(0xFF273A48),
boxShadow: [
BoxShadow(
color: Colors.black.withAlpha(70),
offset: const Offset(5.0, 5.0),
blurRadius: 12.5,
)
],
image: DecorationImage(
alignment: Alignment.topCenter,
image: NetworkImage(articles[index].urlToImage),
fit: BoxFit.cover,
),
),
height: _height*0.35,
width: _width*0.725,
child: Stack(
children: <Widget>[
Align(
alignment: Alignment.bottomCenter,
child: Stack(
alignment: Alignment.bottomRight,
children: <Widget>[
Container(
padding: EdgeInsets.only(left: 10.0, right: 10.0),
decoration: BoxDecoration(
color: const Color(0xFF273A48),
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(10.0),
bottomRight: Radius.circular(10.0)
),
),
height: 60.0,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Flexible(
child: Container(
width: _width*0.725,
child: Text(
articles[index].title,
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
maxLines: 2,
style: TextStyle(
color: Colors.white,
fontFamily: 'Poppins',
),
),
),
),
Text(
'Published ' + DateFormat.yMMMd().format(DateTime.parse(articles[index].publishedAt)) + ", "+ DateFormat.jm().format(DateTime.parse(articles[index].publishedAt)),
overflow: TextOverflow.ellipsis,
maxLines: 1,
style: TextStyle(
color: Colors.blueGrey,
fontSize: 10.0,
fontFamily: 'Poppins',
),
),
],
)
),
Container(
width: 25.0,
height: 20.0,
alignment: Alignment.center,
child: Text(
"$index",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.blueGrey,
fontSize: 10.0,
fontFamily: "Poppins"
),
)
),
],
),
)
],
),
),
),
);
},
);
}).toList(),
height: 400,
autoPlay: true,
)
If you want to save data in a persitance way in Dart code and be able to use it on Android and iOS I suggest you an sqlite plugin like that:
https://github.com/tekartik/sqflite
Otherwise if you only need to save a bunch of data use the shared_preferences plugin
https://github.com/flutter/plugins/tree/master/packages/shared_preferences
These two plugins both support either Android and iOS
You are requesting a lot of code ^_^ (ain't it).
So first of all you need to get your json through an HTTP call. For that use the http flutter package:
const request = "https://newsapi.org/v2/top-headlines?sources=crypto-coins-news&apiKey=d40a757cfb2e4dd99fc511a0cbf59098";
http.Response response = await http.get(request);
debugPrint("Response: " + response.body);
Wrap it up in an async method:
void _jsonAndSqlite() async {
...
}
And in the response
variable you have your full JSON
.
Now you need to serialize and I suggest you this really good reading.
I've choose for this answer the Manaul JSON Decoding
Manual JSON decoding refers to using the built-in JSON decoder in dart:convert. It involves passing the raw JSON string to the json.decode() method, and then looking up the values you need in the Map the method returns. It has no external dependencies or particular setup process, and it’s good for a quick proof of concept.
var myBigJSONObject = json.decode(response.body);
var status = myBigJSONObject['status'];
var totalResults = myBigJSONObject['totalResults'];
var myArticles = myBigJSONObject['articles'];
debugPrint("articles: " + myArticles.toString());
Now that we have articles will try to save them on Sqlite DB through Sqflite package
var myFirstArticle = myArticles[0];
var author = myFirstArticle['author'];
var title = myFirstArticle['title'];
// Get a location using getDatabasesPath
var databasesPath = await getDatabasesPath();
String path = join(databasesPath, 'test.db');
// Delete the database
await deleteDatabase(path);
// open the database
Database database = await openDatabase(path, version: 1,
onCreate: (Database db, int version) async {
// When creating the db, create the table
await db.execute(
'CREATE TABLE Article (id INTEGER PRIMARY KEY, author TEXT, title TEXT)');
});
// Insert some records in a transaction
await database.transaction((txn) async {
int id1 = await txn.rawInsert(
'INSERT INTO Article(author, title) VALUES("$author", "$title")');
debugPrint('inserted1: $id1');
});
And that's it! Have fun studing and coding. Read the articles I've posted for you for JSON serailization and play around with my code, and trying to adding some other best practices they may better fit your needs. This is just a quick playground to, well, play with.
So I ended up with this method:
[...]
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
[...]
void _jsonAndSqlite() async {
const request =
"https://newsapi.org/v2/top-headlines?sources=crypto-coins-news&apiKey=d40a757cfb2e4dd99fc511a0cbf59098";
http.Response response = await http.get(request);
debugPrint("Response: " + response.body);
var myBigJSONObject = json.decode(response.body);
var status = myBigJSONObject['status'];
var totalResults = myBigJSONObject['totalResults'];
var myArticles = myBigJSONObject['articles'];
debugPrint("articles: " + myArticles.toString());
var myFirstArticle = myArticles[0];
var author = myFirstArticle['author'];
var title = myFirstArticle['title'];
// Get a location using getDatabasesPath
var databasesPath = await getDatabasesPath();
String path = join(databasesPath, 'test.db');
// Delete the database
await deleteDatabase(path);
// open the database
Database database = await openDatabase(path, version: 1,
onCreate: (Database db, int version) async {
// When creating the db, create the table
await db.execute(
'CREATE TABLE Article (id INTEGER PRIMARY KEY, author TEXT, title TEXT)');
});
// Insert some records in a transaction
await database.transaction((txn) async {
int id1 = await txn.rawInsert(
'INSERT INTO Article(author, title) VALUES("$author", "$title")');
debugPrint('inserted1: $id1');
});
}
这篇关于Flutter-保存用户数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!