0%

[Flutter] 플러터(Flutter) 모바일 앱 개발 - 스팀잇 피드 구현하기

안녕하세요. @anpigon 입니다.

이번에는 스팀잇 피드를 가져와서 출력하는 화면을 개발해보았습니다. 이전글 "First Flutter App"에서 추가로 학습할 부분이 거의 없어 코드 설명은 짧게 하였습니다. 그리고 핵심 로직에 집중하기 위해서 UI 컴포넌트는 최소한으로 사용합니다.


이전 글


이번에 완성된 앱의 동작화면입니다.

1

에뮬레이터 실행 화면이라서 조금 느립니다. 그리고 아직 상세 페이지를 구현하지 않아서 목록을 클릭하면 브라우저가 실행됩니다.




외부 패키지 추가

pubspec.yaml 파일을 열고 dependencies 목록에 필요한 패키지(http, url_launcher)를 추가합니다.

1
2
3
4
5
6
7
dependencies:
flutter:
sdk: flutter

cupertino_icons: ^0.1.0
http: ^0.11.3+17 # 패키지 추가
url_launcher: ^4.0.1 # 패키지 추가




PostList와 Post 클래스 생성

스팀잇에서 Feed 를 가져와서 데이터를 담을 PostList와 Post 모델 클래스를 생성한다.

model/Post.dart

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Post
final num id;
final String title;
final String body;
final String url;

Post({
this.id,
this.title,
this.body,
this.url,
});

factory Post.fromJson(Map<String, dynamic> json) {
return Post(
id: json['id'] as num,
title: json['title'] as String,
body: json['body'] as String,
url: json['url'] as String,
);



model/PostList.dart

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import 'Post.dart';

class PostList
final List<Post> result;

PostList({this.result});

factory PostList.fromJson(Map<String, dynamic> json) {
return PostList(
result: (json['result'] as List)
?.map((e) => e == null ? null : new Post.fromJson(e as Map<String, dynamic>))
?.toList()
);


JSON 직렬화를 자동으로 할 수도 있다. 자세한 내용은 JSON and serialization 문서를 참고한다.




fetchFeedList 함수 구현

fetchFeedList는 Future를 async/await와 같이 사용하여 비동기 함수로 구현한다. 참고로 JavaScript(ES7)의 async/await와 동작방식은 같다.


Steemit.dart

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import 'dart:async';    // 비동기
import 'dart:convert'; // JSON 파싱
import 'package:http/http.dart' as http;
import 'package:steemlog/model/PostList.dart';

class Steemit
/**
* 스팀잇 피드 리스트를 조회
*/
Future<PostList> fetchFeedList(String username, int limit) async
final _url = "https://api.steemit.com";

final body = '{"jsonrpc":"2.0", "method":"condenser_api.get_discussions_by_feed", "params":[{"tag":"${username}","limit":${limit
.toString()}}], "id":1}';
final response = await http.post(_url, body: body);

if (response.statusCode == 200) {
// If server returns an OK response, parse the JSON
return PostList.fromJson(json.decode(response.body));
else
// If that response was not OK, throw an error.
throw Exception('Failed to load post');






화면에 출력하기

이전에 만들었던 첫번째 앱에서 _buildSuggestions()_buildRow() 함수를 수정하자. FutureBuilder의 future를 이용하여 스팀잇 피드를 비동기로 가져온다. 만약 future가 완료되지 않았다면 CircularProgressIndicator()를 사용하여 프로그래스 이미지를 보여준다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import 'package:url_launcher/url_launcher.dart';
import 'package:steemlog/model/Post.dart';
import 'package:steemlog/model/PostList.dart';
import 'package:steemlog/Steemit.dart';

// ... 생략 ...

class FeedListState extends State<FeedList> {
final String _username = 'anpigon'; // 사용자 이름
final int _limit = 20; // 가져올 피드 개수

@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('Feed List'),
),
body: _buildSuggestions()
);


Widget _buildSuggestions() {
return new Center(
child: FutureBuilder<PostList>(
future: Steemit().fetchFeedList(_username, _limit),
builder: (context, post) {
if (post.hasData) {
return new ListView.builder(
padding: const EdgeInsets.all(5.0),
itemCount: post.data.result.length,
itemBuilder: (BuildContext _context, int position) {
return _buildRow(post.data.result[position]);
},
);
else if (post.hasError) {
return Text("${post.error}");

return CircularProgressIndicator();

)
);


Widget _buildRow(Post post) {
return new Column(
children: <Widget>[
new ListTile(
title: new Text(post.title),
subtitle: new Text(post.body,
overflow: TextOverflow.ellipsis,
maxLines: 3
),
onTap: () {
_launchURL(post.url);
},
),
const Divider()
]
);


_launchURL(String _url) async
final String url = "https://steemit.com${_url}";
if (await canLaunch(url)) {
await launch(url);
else
throw 'Could not launch $url';



Text에서 제공하는 overflow 속성을 사용하여 내용을 최대 3줄만 표시되도록 했다.




여기서 작성한 코드는 모두 깃허브에 올려놓았습니다.


여기까지 읽어주셔서 감사합니다.



Sponsored ( Powered by dclick )
드디어 이지 스팀잇이 출간되었습니다(+M-shape도요~)

안녕하세요. 포해피우먼입니다. 오늘은 반가운 소식을 가지고 왔습니다. 아기다리고기다리 (-_-…

logo

이 글은 스팀 기반 광고 플랫폼
dclick 에 의해 작성 되었습니다.


Originally posted on http://steemit.com