HTML5モバイルアプリ:バグまたは成功。 試行番号1

モバイルプラットフォーム向けのHTML5アプリケーションを開発するという私の夢の実現を続けています。一度書いただけで、いつでもどこでも動作します。 前回の記事では、ネットワークのない仕事は提供されなかったため、モバイルサイトではなくモバイルアプリケーションを受け取りました。 私はそれを修正しようとしますが、誰もが(ほとんど)それがすべて個人のデバイスでどのように機能するかを試すことができます。



そのため、いくつかのマウスボタンでクリックするだけで、いくつかのモバイルプラットフォームで実行できる小さなモバイルWebアプリケーションを取得します。



画像








小さなメモ:この記事は、新技術の研究の対象となる資料を統合するために書かれました。 この種のアプリケーションの作成における実際の経験が完全に不足しているため、可能性のある欠陥について事前に謝罪します。





建築



簡単なものを実装します。





サーバーから必要なデータを取得し、ローカルに保存します。

サーバー側は、ODataアプリケーションを備えたスタンドアロンの.net MVCです。 この記事では、サーバーはODataプロトコルを使用してデータを送信するだけでよいため、実装を検討する理由はありません。

クライアント部分は、 PhoneJSおよびBreezeJSというライブラリーを備えたphonegapアプリケーションです。



それでは、始めましょう...



高速化のために、次の構造のPhoneJSアプリケーションテンプレートを使用します。



何のためにすべてが明確なようです。 index.htmlファイルで、BreezeJSに必要なライブラリへのリンクを追加します。



アプリケーションの起動



アプリケーション自体はindex.jsファイルで作成され、ナビゲーションおよびその他のサービス機能が説明されています。 PhoneJSは、いくつかのレイアウトを提供しますスライドアウトを選択しました 。 それでは、アプリケーションを作成しましょう。

$(function () { app = ms.app = new DevExpress.framework.html.HtmlApplication(APP_SETTINGS); app.router.register(":view/:item", { view: "Home", item: undefined }); ms.app.viewShown.add(onViewShown); ms.app.navigationManager.navigating.add(onNavigate); startApp(!ms.dataservice.initUserData()); setTimeout(function () { document.addEventListener("deviceready", onDeviceReady, false); console.log("delay"); if (device.platform == "tizen") { document.addEventListener("tizenhwkey", function (e) { if (e.keyName === "back") onBackButton(); }); } }, 1000); });
      
      







APP_SETTINGS-ナビゲーションとレイアウトを示すアプリケーションパラメーター

非表示のテキスト
 APP_SETTINGS = { namespace: ms, navigationType: "slideout", navigation: [ { "id": "Home", "title": "Home", "action": "#Home", "icon": "home" }, { "id": "Settings", "title": "Settings", "action": "#Settings", "icon": "card" }, { "id": "About", "title": "About", "action": "#about", "icon": "info" } ] };
      
      





まず、「ルーティング」とデフォルトビューを設定し、その後アプリケーションを起動し、ms.dataservice.initUserData()関数を使用してローカルストレージに既にデータがあるかどうかを確認します(少し後で検討します)。 データが利用可能な場合、関数はtrueを返します。 つまり 初めて起動する場合は、 [設定]ビューに移動してデータを取得します。

  function startApp(needToSynchronize) { if (needToSynchronize) ms.app.navigate("Settings/1"); else ms.app.navigate(); }
      
      





また、アプリケーションを起動する前に、わずかな遅延を導入します-将来、スプラッシュスクリーンを作成します。

データを操作する



データを操作するには、別のdataservice.jsファイルを作成します。

非表示のテキスト
 MobileSales.dataservice =function ($, DX, app, undefined) { var DATA_VERSION_KEY = "mobilesales-version", DATA_KEY = "mobilesales-data", logger = app.logger; serviceName = "http://mobsalessrv.azurewebsites.net/odata/"; breeze.config.initializeAdapterInstances({ dataService: "OData" }); var manager = new breeze.EntityManager(serviceName); var store = manager.metadataStore; var queries = { Routes: { name: "Routes", query: breeze.EntityQuery.from("Routes").orderBy("RouteID"), }, Customers: { name: "Customers", query: breeze.EntityQuery.from("Customers").orderBy("CustomerName"), }, ProductTypes: { name: "ProductTypes", query: breeze.EntityQuery.from("ProductTypes").orderBy("ProductTypeName"), }, Products: { name: "Products", query: breeze.EntityQuery.from("Products").orderBy("ProductName"), }, Orders: { name: "Orders", query: breeze.EntityQuery.from("Orders").orderBy("Date"), }, OrderDetails: { name: "OrderDetails", query: breeze.EntityQuery.from("OrderDetails"), }, }; function initUserData() { var dataFromStorage = localStorage.getItem(DATA_KEY); if (dataFromStorage) { manager.importEntities(dataFromStorage); return true; } else { return false; } } function loadData(query) { return manager.executeQuery(query); } function getRoutes(){ return manager.executeQueryLocally(queries.Routes.query); }; function getCustomers() { return manager.executeQueryLocally(queries.Customers.query); }; function getProduct(productID) { var query = queries.Products.query.where("ProductID", "==", productID); return manager.executeQueryLocally(query)[0]; }; function getOrders(customerID) { var query = queries.Orders.query; if (typeof customerID != "undefined" && customerID > 0) query= query.where("CustomerID", "==", customerID); return manager.executeQueryLocally(query); }; function getOrderDetails(orderID) { var query = queries.OrderDetails.query; if (typeof orderID != "undefined" && orderID > 0) query = query.where("OrderID", "==", orderID); var result = manager.executeQueryLocally(query); result.forEach(function (item) { item.ProductName = getProduct(item.ProductID()).ProductName; }); return result; }; function saveDataLocally() { var exportData = manager.exportEntities(); localStorage.setItem(DATA_KEY, exportData); } var dataservice = { manager: manager, metadataStore: manager.metadataStore, initUserData: initUserData, queries: queries, loadData: loadData, getRoutes: getRoutes, getCustomers: getCustomers, saveDataLocally: saveDataLocally, getOrders: getOrders, getOrderDetails: getOrderDetails, }; return dataservice; }(jQuery, DevExpress, MobileSales);
      
      





前回の記事で読んだ微風を扱う方法。 私はいくつかの点にのみ焦点を当てます。 クエリオブジェクトには、データを受信するためのクエリのリストが含まれています。今後、さまざまなパラメータを使用してそれを拡張し、一般にサーバーからこのリストを受信して​​、データの動的な充填を制御できるようにする予定です。



Breezeには、 manager.exportEntities()およびmanager.importEntities(dataFromStorage)をそれぞれ使用して、すべてのデータをローカルに保存および復元する絶好の機会があります。 initUserData関数は、 DATA_KEYキーを使用してローカルストレージのデータをチェックし、取得します。 フォームgetXXXの他のすべての機能は、必要なエンティティをローカルで選択し、必要なタイプで使用されます。



サーバーからすべてのデータをダウンロードするには、個別の設定ビューを使用します。このビューには、データをダウンロードするためのボタン、ロードパネル、およびエンティティのリストがあります。

 <div data-options="dxView : { name: 'Settings', title: 'Settings' } "> <div data-options="dxContent : { targetPlaceholder: 'content' } "> <div class="actions"> <div data-bind="dxButton: { text: 'Synchronize', clickAction: synchData }"></div> </div> <div data-bind="dxLoadPanel: { message: message, visible: loading().length>0 }"></div> <div data-bind="dxList: { items: entityList }"> <div data-options="dxTemplate : { name: 'item' }"> <div data-bind="text: $data.name" class="entity-name"> </div> <div data-bind="text: $data.status" class="entity-status"></div> </div> </div> </div> </div>
      
      





BreezeとPhonejsの両方がすばらしいノックアウトライブラリを使用していることを完全に忘れていたので、これらすべてをまとめるのは非常に便利です。

settings.js
 MobileSales.Settings = function (params) { var app = MobileSales, needToSynchonize = params.item==="1", self = this; var vm = { entityList: ko.observableArray([]), loading: ko.observableArray(), viewShowing: function () { if (needToSynchonize) getEntities(); }, viewShown: function () { $(".dx-active-view .dx-scrollable").data("dxScrollView").scrollTo(0); }, synchData: getEntities, }; vm.message = ko.computed(function () { return "Loading ...(left:" + this.loading().length + ")" }, vm); function getEntities() { var mapped = $.map(app.dataservice.queries, function (item) { item.status = ko.observable("Loading"); vm.loading.push(true); app.dataservice.loadData(item.query).then(function (data) { app.logger.log("Loaded data: " + item.query.resourceName); item.status("Succeded"); app.logger.log(app.dataservice.getRoutes()); vm.loading.pop(); if (vm.loading().length === 0) app.dataservice.saveDataLocally(); }).fail(function (error) { item.status("Error"); app.logger.error("Error Loading data"); app.logger.log(error); vm.loading.pop(); }); return item; }); vm.entityList(mapped); }; return vm; };
      
      





入力でパラメータを受け入れます。これは、強制同期の場合に送信されます。 Breezeはサーバーへのすべてのリクエストを非同期に実行します。これにより、エンティティをentityListにアップロードするためのエレガントなソリューションを作成できます。 これを行うには、observableArrayの読み込みが 1つだけ必要です。

getEntities関数を分析してみましょう。dataservice.queriesのすべての要素を調べて、それぞれにステータスフィールドを追加し、 vm.loading.push配列に値を追加します(true) 。 エラーの正常な実行または生成のためのハンドラーで、要素のステータスを更新し、 ローディング配列を減らします。 その結果、完了制御を備えた複数のエンティティの非同期読み込みが非常に簡単になります。 これがすべての外観です。

画像






プログラムの残りの部分はあまりおもしろくなく、リポジトリにダウンロードされたデータを表示するだけで、前の記事を複製します。 興味がある場合は、 ソースコードをご覧ください。

[ ホーム]ビューでは、ルートのルート上の販売地点を選択したり、この地点の注文を表示したりできます。 これはどのように見えるかです:

画像








数回クリックするだけでモバイルアプリケーションを取得できます。

http://build.phonegap.comにアクセスします。

●GitHub経由でログインします。

●目的のリポジトリを選択して、新しいアプリケーションを追加します

●マジックボタン「Ready to build」を押します

●そして、6つのプラットフォームのうち5つでアプリケーションを取得します(残念ながら、iOSにはキーがありません)。

画像






ちなみに、上の写真はPhoneGapバージョン2.9で撮影されたものです。WPはこちらのバージョン7です。バージョン3を選択すると、次のメッセージが表示されます



少しのtar(多分)を追加することは、パフォーマンスです。 古いデバイスや弱いデバイスで作業することは単純に不可能です-ブレーキは完全です。 しかし、デバイスをほぼ通常のパラメーターで使用するとすぐに、すべてがうまくいきました。 これはネイティブアプリケーションではありませんが、比較したくはありません。これらは2つの異なるものです。 そして、このアプローチ(まあ、一般的にHTML5の意味では)には未来があり、ニッチが見つかると確信しています。



アプリケーションリンク:



●ソースhttps://github.com/gfhfk/MobSales

●ブラウザでテストします(ChromeとIE11を試しました) http://mobsales.azurewebsites.net/

●サーバー側を気にする人: http : //mobsalessrv.azurewebsites.net/odata/

●プログラム自体:

バージョン3.4 https://build.phonegap.com/apps/727149

画像






バージョン2.9の管理者https://build.phonegap.com/apps/733422/

画像








注1 :qrコードを介してWindows Phoneにアプリケーションをインストールすると問題が発生し、エラーが発生します。 コンピューターからリンクをたどり、xapをダウンロードして、アプリケーション展開ツールで入力する必要があります。 おそらくPhonegap Buildグリッチ。

注2 :特に、最初に起動したとき、またはエミュレータで起動したときに、このエラーが表示されることがあります。

画像








この問題の解決策は非常に簡単です。

1. index.htmlファイルの名前をmain.htmlに変更します。

2.新しいindex.htmlを作成し、ピースを貼り付けます。

 <!doctype html> <html> <head> <title>tittle</title> <script> window.location='./main.html'; </script> <body> </body> </html>
      
      





3.すべて-これ以上のエラーはありません(バージョン2.9でも、一部のデバイスでは引き続きエラーが発生しました)。

注3 :WP8エミュレーターでは、理由がわかるまで、アプリケーションは最初に起動されません。 実際のデバイスでは試しませんでした。 WP8.1では、まったく起動しませんでした(まだわかりません)。

注4:サイトは、リソースが限られている無料のWindows Azhure WebSitesホスティングでホストされています。 ハブラー効果を考慮すると、サイトがダウンして、それから私に知らせてください-私はしばらくの間有料のものに移ります。

私は結果を書きません。誰もが自分でそれをテストし、調査に回答することをお勧めします。



All Articles