プログラミング モバイルアプリ

【React Native(Expo) × Firebase】画像をキャッシュし、Cloud Storageの料金を節約する

スポンサーリンク

こんにちは!

今回は「React Native(Expo) × Firebase」で画像をキャッシュする方法をについて、お伝えしていきたいと思います。

React Native(Expo)で画像をキャッシュするには「React Native Expo Image Cache」というライブラリを使うのがおすすめです!

本記事では、簡単な使い方使ってみてよかった点について、書いていきたいと思います。

React Native Expo Image Cacheの使い方

パッケージをインストール

npmの場合

MacBookPro:~ app$ npm install react-native-expo-image-cache

yarnの場合

MacBookPro:~ app$ yarn add react-native-expo-image-cache

 

画像をキャッシュする

 // 画像パスを保有している任意のファイル
// import文を追加
import {CacheManager} from 'react-native-expo-image-cache';

async function getUserData() {
  // uriをfirestoreやその他APIなどから取得
  const uri = 'https://.....png';
  // awaitをつけるのを忘れずに
  const path = await CacheManager.get(uri).getPath();
}

 

 

FirestoreのonSnapshotとの組み合わせ例

Firestoreに画像パスを保存する方も多いと思いますので、書き方の例を書いてみます。

(もっといい書き方があればご指摘ください🙇‍♂️)

// firestoreを使った例
import React, {useState, useEffect} from 'react';
import {CacheManager} from 'react-native-expo-image-cache';
import firebase from '../firebase';
import 'firebase/firestore';

const db = firebase.firestore();

async function getCacheImages(obj) {
  const cacheUserData = Object.assign({}, obj);
  // オブジェクトのループ
  for (const userId of Object.keys(cacheUserData)) {
    // パスが空白の場合、cache処理は行わず、空白を設定
    cacheUserData[userId] = cacheUserData[userId] ?
      await CacheManager.get(cacheUserData[userId]).getPath() : '';
  }
  return cacheUserData;
}

function getAllUserData() {
  // Firestoreのsnapshotで画像パスを取得
  db.collection('data')
      .where('state', '==', 'alive')
      .onSnapshot(async (res) => {
        let obj = {};
        res.forEach((doc) => {
          obj = {...obj, ...doc.data()};
        });
        // obj = {'user1' : 'https:...image1.png', 'image2' : 'https:...iamge2.png'}

        // awaitで呼び出すことで、全てキャッシュ完了後、後続のsetStateが実行されます
        const cacheUserData = await getCacheImages(obj);
        // 必要に応じて、contextで管理
        setState(cacheUserData);
      });
}

useEffect(() => {
  getAllUserData();
}, []);

 

キャッシュがちゃんと機能しているか確認

まず、以下のように画像をキャッシュして表示させます

//省略
const path = await CacheManager.get(uri).getPath(); // 処理①

ここで、一度urlの画像を削除してみます。

そしてもう一度、上記の処理①を実行させてみると、ちゃんと画像が表示されているのを確認できました。

このことから、キャッシュする1回目のみurlからダウンロードされることがわかります。

FirebaseのCloud Storage等を使用している場合、ダウンロード量を大幅に減らすことが可能です。

 

画像をキャッシュすることで、どうだったのか?

画像を全てローカルキャッシュから読み込むことで、画面がチカチカすることがなくなった

1つ目は、外部URLから<image source= {url: https://....} /> のように書くと、画面遷移のたびに画像がチカチカします。

画像機能を実装したことがある方は経験済みかもしれません。。

僕のような神経質な方はとても気になります。笑

キャッシュし、ローカルパスから読み込むことで改善されました。

Firebase FireStorageのダウンロード数(読み取り)が格段に減った

もう1つはFirebase FireStorageのダウンロード数(読み取り)が減り、課金対象のダウンロードの容量が大幅に減った点です。

先ほど説明したように、一度アプリ起動後一度だけダウンロードし、その後はキャッシュから取得します。

画面遷移のたびにダウンロードするのとは何十倍も課金額が変わる可能性があります。

FirestoreのonSnapshotのコールバック処理が重くなった(FireStoreでパスを管理している場合)

僕の場合、FireStoreでパスを管理しており、onSnapshotのコールバック処理で画像をキャッシュするようにしていました。

そのため、更新があるたびに、画像をキャッシュする処理が実行されるので、少し負荷になってしまいました。

他にいい方法があれば、教えてくださいませ🙇‍♂️

スポンサーリンク

-プログラミング, モバイルアプリ
-,

© 2020 エンジニア×モチベアップ Powered by AFFINGER5