【Phonegap/Cordova 入門05】データをストレージに保存する

みなさん、こんにちは!

今回は、アプリの各種データの保存方法を取り上げていきます。Phonegapにおけるデータの格納は大変簡単です。ですが、使用頻度としてはかなり高いのでしっかり覚えておきたいところですね。

(前回の記事はこちら⇒【Phonegap/Cordova 入門04】BootstrapとjQueryで住所検索アプリを作る)

また1から新規プロジェクトを作っていっても良いのですが、ちょっと面倒なので、前回作成した住所検索アプリを改修する形で進めていこうと思います。

早速、前回の住所検索アプリに修正を加えていきます。今回付け加える機能は、
「住所検索後に表示される保存ボタンを押下すると住所データを1件保存」
「保存したデータを見るボタンを押下すると、保存されているデータをポップアップで表示」
「保存したデータを削除ボタンを押下すると、全保存データを削除する」
としました。

【/www/index.html】

 <head>
 <meta charset="utf-8" />
 <meta name="format-detection" content="telephone=no" />
 <meta name="msapplication-tap-highlight" content="no" />
 <!-- WARNING: for iOS 7, remove the width=device-width and height=device-height attributes. See https://issues.apache.org/jira/browse/CB-4323 -->
 <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi" />

 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>

 <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
 <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
 
 
 <style>
 body{
   font-family: "ヒラギノ角ゴシック Pro", "Hiragino Kaku Gothic Pro", 'メイリオ' , Meiryo , Osaka, "MS Pゴシック", "MS PGothic", sans-serif;
 }
 .contents{
   width: 90%;
   margin: auto;
 }
 .jumbotron{
   width: 100%;
   border-radius: 8px;
 
   padding-left: 12px;
 }
 </style>

 <script type="text/javascript" src="cordova.js"></script>
 <script type="text/javascript" src="js/searchAddress.js"></script>
 <script type="text/javascript" src="js/storageManager.js"></script>
 
 <script>
 var smanager = new storageManager("ZIP_ADDRESS_DATA");

 function showSavedData(){
   var msg = "";
   var data = smanager.getAll();
   for(var p in data){ msg += p + ": " + data[p] + "\n"; }
     alert(msg);
   }

 function saveData(zip_no, address){
   smanager.set(zip_no, address);
   alert("保存しました");
 }

 function deleteAll(){
   smanager.deleteAll();
   alert("削除しました");
 }
 </script>

 <title>郵便番号検索</title>
 
 </head>
 <body>
 
 <div class="contents">

 <div class="jumbotron">
 <h1>郵便番号検索</h1>
 <p>ハイフンなし7桁の郵便番号を入力し、検索ボタンを押してしてください</p>
 <input type="text" id="zipno" />
 <button class="btn btn-primary" onclick="searchAddressFromZipno()"><span class="glyphicon glyphicon-search" aria-hidden="true"></span>Search</button>
 <button class="btn btn-default" onclick="showSavedData()">保存したデータを見る</button>
 <button class="btn btn-danger" onclick="deleteAll()">保存したデータを削除</button>
 </div>
 
 <div id="result"></div>
 
 </div>

</body>
</html>

32行目に、新たな外部jsファイルインクルードを追加しています。これは、今回の目的となるデータ保存に関するjsファイルです。

34~53行目は、データ保存関連jsに定義されているオブジェクトのインスタンス化と、各種ボタンからのイベントハンドル用の関数を定義しています。データ表示、データ保存、データ削除の動作を行います。

67,68行目は、保存したデータの表示用ボタンと、削除用ボタンです。折角Bootstrapを使用しているので、削除用ボタンはbtn-primaryクラスを与えることで、赤ボタンにしています。

以上で見た目に関する所は修正完了です。次に、前回作成した住所検索関連jsを少し修正します。修正点は、検索後に保存用のボタンを付け加える、という部分です。

【/www/js/searchAddress.js】

// 取得データの描画を行う
function drawData2result(data){
 jQuery("#result").css("opacity", 0.0).css("font-size", "100%"); // 一旦可視性を0に

 if(data.results){ // 取得データに対象のプロパティが存在するか
   var div_st = "<div>";
   var div_ed = "</div>";
   var res = "";

   for(var i = 0; i < data.results.length; i++){ // 一応順番を担保するために
     var d = data.results[i];
     res += div_st;
     res += d.address1 + " " + d.address2 + " " + d.address3;
     res += div_ed;

     res += "<button onclick='saveData(\"" + d.zipcode + "\"" + ",\" " + d.address1 + " " + d.address2 + " " + d.address3 + "\")'>保存</button>";
   }

   jQuery("#result").html(res); // 結果をDOMに反映
 }

 jQuery("#result").animate({
   opacity: 1.0
 }, 1000);
}

// 住所検索を行う
function searchAddressFromZipno(){
 var zip_no = document.getElementById("zipno").value;
 if(zip_no && (zip_no.match(/[0-9]{7}/) != null)) {
   // 規定の入力がされていれば

   var params = {};
   params["zipcode"] = zip_no;

   // 住所検索APIにrequestを発行
   jQuery.ajax({
     type: "GET",
     url: "http://zipcloud.ibsnet.co.jp/api/search",
     dataType: "jsonp",
     jsonpCallback: "myCallback",
     data: params,
     success: function (data) {
       console.log("ajax success!!");
       drawData2result(data); // 画面に結果を表示する
       return;
     },
     error: function (data) {
       alert("ajax error occured!!)");
     }
   });
 }
 else{
   alert("7桁の数字を入力してください");
 }
}


16行目を追加しています。住所検索後に表示される保存用のボタンです。saveData関数をclick時に駆動するように指定しています。引数として、郵便番号、住所を与えるようにしています。

最後に、新規作成のデータ保存に関するjsファイルです。今回は入門サンプルですので、もっと簡単に記述しようかと思ったのですが…

【/www/js/storageManager.js】

var storageManager = function(storage_name){
 this._storage_name = storage_name;
 this._storage_data = this.getAll();
}

storageManager.prototype.set = function(key, value){
 this._storage_data[key] = value;
 window.localStorage.setItem(this._storage_name, JSON.stringify(this._storage_data));
}

storageManager.prototype.get = function(key){
 return this._storage_data[key];
}

storageManager.prototype.getAll = function(){
 var str_data = window.localStorage[this._storage_name];
 var parsed_data;
 
 try{
   if(str_data){
     parsed_data = JSON.parse(str_data);
     return parsed_data;
   }
 }
 catch(e){
   cosnole.log("parse error occurred...");
 }

 return {};
}

storageManager.prototype.deleteAll = function(){
 this._storage_data = {};
 window.localStorage.setItem(this._storage_name, JSON.stringify(this._storage_data));
}

住所情報だけでなく、他のデータ管理をするかもしれない!ということを想定し、一応クラス的な感じにしました。set, get, getAll, deleteAll という4のメソッドが定義されています。

で、今回の本来の目的である、データの保存/取得については、8行目(保存), 12行目(取得)で使用されています。

はい。データの永続的保存は、webアプリ同様、localStorageを使用します。localStorageは、key-value形式で値を保存できるというものです。保存できる値は、key, value共に文字列型のみです。ですので、オブジェクトをvalueとして保存したいときは、JSON.stringifyを使用、取り出す時は、JSON.parseして使用する必要があります。

また、1つしか保存ストレージを使用しないのであれば、

localStorage["1000014"] = "東京都 千代田区 ...";

のように保存しても良いかもしれませんが、保存すべきデータの種類が複数ある場合に備えて、localStorageに直にプロパティを指定して値保存という形はとらずに、

 localStorage.setItem(this._storage_name, JSON.stringify(this._storage_data));

のように、ストレージ種類ごと(_storage_nameごと)に、オブジェクトをstringifyした値をkey-valueペアとして保存するのが妥当かと思われます。

無駄に(今回の例では郵便番号をキーに住所を格納するという方式を取っているためストレージ種類は1つ)、この点を意識したためコードが長くなってしまっていますが、少し実践に近づけるという意味でこんなコードにしました。

はい。前回の住所検索アプリを書き換え、phonegap serveして結果を確認してみますと、下記のような結果になると思います。

input要素に7桁郵便番号入力、Searchを押下で住所を取得。

Screenshot_2016-07-22-01-03-54

結果の下に表示される保存ボタンを押下。何件か保存した後、保存したデータを表示ボタンを押下した所。

Screenshot_2016-07-22-01-04-24

このような感じの結果になります。この結果は、アプリを終了後、再度起動してすぐ保存したデータを表示しても、ちゃんと以前のデータが表示されます。

まとめです。

  • webアプリと同様、localStorageを使用することで、端末にデータを保存することができる

今回は以上です。

 

Phonegap/Cordova入門シリーズはこれで一旦終わります。

興味のある方は、Phonegap/Cordovaと相性のいいフレームワークである、OnsenUI関連のシリーズもどうぞ。
記事はこちら⇒【Phonegap/Cordova + Onsen UI 01】ハイブリッドアプリに最適なOnsen UIとは

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です