10
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

[Flutter]Algoliaを使ってRitsBookにメルカリ風の全文検索機能をつけてみた

Last updated at Posted at 2022-12-01

はじめに

始めましてwatnowに所属してますしゅんやです。
今日はRitsbookにAlgoliaを用いた全文検索機能をメルカリ風に実装していきたいと思います!!
楽しみですね!:raised_hands:

RitsBookとは

RitsBook

立命館大学BKCキャンパス専用の教科書フリマアプリです。元々、所属している学生団体の先輩が作っていたものなのですが、現在はその方含め3人(エンジニア2名、デザイナー1名)でモバイル版の開発を行っています。
元々WEB版には完全一致検索はあったのですが、今回は全文検索機能を実装していきたいと思います。

Algoliaの連携

元々連携の方法について記事を書こうと思っていたのですが、すでにとてもわかりやすくまとめられていた方がいたので是非 

こちらの記事
をご覧になってください。

連携の流れとしては、
Algoliaのアカウント登録、設定

Firebaseとの連携

FirestoreのデータをAlgoliaに連携

Flutterに導入

といった流れになっています。

検索フォームの実装

それでは検索フォームを作っていきます。
今回はメルカリの検索フォームのようにしていきたいと思っております。 メルカリは商品一覧ページのAppBarに検索窓がありそこから検索するUIかと思いきや、実はボタンでそこから検索ページに遷移する形で実装されていたのでその通り実装していこうと思います。

商品一覧画面

101006.jpg

検索画面

101008.jpg

まずホームの画面(商品の一覧が載っている画面に検索ページに遷移するボタン)をつけていきたいと思います

LandingPage.dart
import 'package:flutter/material.dart';
//クラス名などは省略
 @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Padding(
          padding: const EdgeInsets.all(8.0),
          child: SizedBox(
            child: ElevatedButton(
              onPressed: () {
                Navigator.push(
                    context, MaterialPageRoute(builder: (context) => Search()));
              },
              style: ElevatedButton.styleFrom(
                backgroundColor: const Color(0xfff5f5f5),
              ),
              child: const Align(
                alignment: Alignment.centerLeft,
                child: Text(
                  '検索',
                  style: TextStyle(color: Color(0xff8f8f8f), fontSize: 12),
                ),
              ),
            ),
          ),
        ),
        backgroundColor: Colors.white,
      ),
      //以下省略

これで検索フォームが完成しました。
Simulator Screen Shot - iPhone 14 Pro Max - 2022-11-30 at 14.39.08.png

検索画面の実装

とりあえずUIは作らず、タイトルのみを表示してみました。続きはまた投稿する予定です。
SearchPage.dart
import 'dart:async';
import 'package:algolia/algolia.dart';
import 'package:flutter/material.dart';

class Application {
  static final Algolia algolia = Algolia.init(
    applicationId: 'Algoliaに載ってているapplicationId',
    apiKey: 'Algoliaに載っているapiKey',
  );
}

class Search extends StatefulWidget {
  @override
  _SearchState createState() => _SearchState();
}

class _SearchState extends State<Search> {
  StreamController searchController = StreamController();

  Future searchFireStore(word) async {
    Algolia algolia = Application.algolia;
    AlgoliaQuery query = algolia.instance.index("ItemName").query(word);
    AlgoliaQuerySnapshot snap = await query.getObjects();
    List<AlgoliaObjectSnapshot> hits = snap.hits;
    searchController.add(hits);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: SearchItems(),
        backgroundColor: Colors.white,
      ),
      body: Column(
        children: <Widget>[
            Expanded(
              child: StreamBuilder(
                stream: searchController.stream,
                builder: (context,AsyncSnapshot snapshot) {
                  if (snapshot.hasData) {
                    return ListView.builder(
                      itemCount: snapshot.data.length,
                      itemBuilder: (context, index) {
                        return Text((snapshot.data[index].data['ItemName']);
                      },
                    );
                  } else {
                    return Center(
                      child: Text("No Data"),
                    );
                  }
                
                },
              ),
            )
        ],
      ),
    );
  }
}

class SearchItems extends StatefulWidget {
  @override
  _SearchItemsState createState() => _SearchItemsState();
}

class _SearchItemsState extends State<SearchItems> {
  String searchWord = "";
  @override
  Widget build(BuildContext context) {
    return TextField(
      decoration: const InputDecoration(
        hintText: '検索',
      ),
      controller: TextEditingController(text: searchWord),
      onChanged: (String text) {
        searchWord = text;
      },
      onSubmitted: (searchWord) => _SearchState().searchFireStore(searchWord),
    );
  }
}

商品一覧画面

Simulator Screen Shot - iPhone 14 Pro Max - 2022-11-30 at 14.39.08.png

検索画面

Simulator Screen Shot - iPhone 14 Pro Max - 2022-12-01 at 02.09.08.png

感想

今回はAlogoliaを使ってRitsBookにリアルタイム検索機能を実装していきました。Algoliaを使えば思っていたより簡単に実装できたのでびっくりです。個人的にStreamでのデータの取得に一番苦戦しました。まだまだ理解が浅かったみたいです。RitsBookはWEBアプリ版とはデザインも一新されていて、検索画面のUIも整えてリリースするので完成されたRitsBookを是非見てみてください! それでは良いFlutterライフを!:blush:
10
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?