keywords:html
ionic,phonegap,cordova,網絡制式,動態切換,變動,API,服務器地址,$resource,localstorage,urlapi
場景promise
APP以項目的形式提供,一個客戶須要部署一套服務器,一個APP,因此APP的後臺服務器地址不能寫死。並且要求若是有wifi且在內網,須要用內網服務器地址,若是用3G或者4G,則需切換爲外網服務器地址服務器
需求網絡
APP第一次運行,若是沒有設置過服務器地址,須要設置好後臺服務器地址(含內網和外網,外網是必選,內網是可選)ionic
APP運行過程當中,若是用戶手機網絡制式發生改變,則須要根據移動網絡制式選擇合適的服務器地址ide
原有URL的設置post
之前APP的API地址,是直接寫到一個constant裏面,例如:優化
(function () { "use strict"; angular.module("gaia.config", []) .constant("ENV", { "version": "1.0.1", "name": "production", "debug": true, "api": "http://111.111.111.111:8088/gaia/api", }); })();
resource的調用url
var resource = $resource(ENV.api + '/customer',{},{ login:{ method:'post', url:ENV.api + '/customer/login' }, accesstoken:{ method:'get', url:ENV.api + '/customer/accesstoken' } });
(後面實現方案有部分變更)
保留ENV,APP第一次啓動將設置的url存到localstorage裏面,在之後每次啓動前,從localstorage裏面取出來賦值給ENV.api,當網絡制式發生改變時,再根據狀況賦值改變ENV.api。全部與後臺相關的Service 的$resource 的初始化都依賴於ENV.api。
設計的關鍵點:
設置頁面
請忽略美觀(-__-)b
Service $resource 聲明方式的改造:
var resource = null; var _initResource = function(apiUrl){ resource = $resource(apiUrl + '/customer',{},{ login:{ method:'post', url:apiUrl + '/customer/login' }, accesstoken:{ method:'get', url:apiUrl + '/customer/accesstoken' } }); }; _initResource(ENV.api); return { initResource:function(url){ _initResource(url); }, .....
新增Service,統一變動$resource
每次變動就調用先設置ENV.api,再_Sys.changeResource(ENV.api);
(function () { 'use strict'; angular.module('gaia.services') .factory('_Sys', function (ENV, User, Projects, Plans) { return { changeResource: function (url) { User.initResource(url); Projects.initResource(url); Plans.initResource(url); } }; }); })();
網絡制式切換,調整URL
關於網絡制式的監控的相關細節見:ngcordova 監控網絡制式改變
$rootScope.$on('$cordovaNetwork:online', function (event, networkState) { var type = $cordovaNetwork.getNetwork(); if (type == Connection.WIFI) { var wifiApi = Settings.getWIFIAPI(); if (wifiApi) { //test方法定義見方案二Setting定義 Settings.test(wifiApi).$promise.then(function (response) { if (response.success) { //切換內網服務器地址中.... _Sys.changeResource(wifiApi); } }, function (e) {}); } } else if (type == Connection.CELL_4G || type == Connection.CELL_3G) { var wlanApi = Settings.getAPI(); //切換移動網(3G|4G)服務器地址中.... _Sys.changeResource(wlanApi); } });
大致思路同方案一,只是在思想方案一過程當中,又是localstorage 又是ENV.api,各類判斷,給繞暈了,後來一想,url最終仍是以localstorage裏面存儲的爲準,何不拋棄ENV.api,實現大統一(●ˇ∀ˇ●)
設計思路改動點:
1.用戶設置的API地址,存儲到localstorage裏面,定義兩個基礎Service,一個用於localstorage操做,一個用於APP參數設置
//Storage Service 定義
(function(){ 'use strict'; angular.module('gaia.services') .factory('Storage',function($log){ $log.debug("Storage Service init"); return { set:function(key,data){ return window.localStorage.setItem(key,window.JSON.stringify(data)); }, get:function(key){ return window.JSON.parse(window.localStorage.getItem(key)); }, remove:function(key){ return window.localStorage.removeItem(key); } }; }); })();
//Settings Service 定義
(function () { 'use strict'; angular.module('gaia.services') .factory('Settings', function ($resource, $log, Storage) { var storageKey = 'settings'; var _settings = Storage.get(storageKey) || {}; var addOn = '/gaia/api'; return { getSettings: function () { return _settings; }, save: function (settings) { Storage.set(storageKey, settings); _settings = settings;//改變內存中的_settings,便於每次調用getAPI時都能取到最新值 return settings; }, getAPI: function () { if (_settings.wlan) { return "http://" + _settings.wlan + addOn; } return ""; }, getWIFIAPI: function () { if (_settings.wifiMode && _settings.wifi) { return "http://" + _settings.wifi + addOn; } return ""; }, test: function (url) { var resource = $resource("http://" + url + addOn + "/test", {}, { query: { method: 'get', isArray: false, timeout: 2000 } }); return resource.query(); } }; }); })();
2.Service $resource 的部分改動
var resource = null; var _initResource = function(apiUrl){ resource = $resource(apiUrl + '/customer',{},{ login:{ method:'post', url:apiUrl + '/customer/login' }, accesstoken:{ method:'get', url:apiUrl + '/customer/accesstoken' } }); }; //將此處的ENV.api 換成Settings.getAPI() // _initResource(ENV.api); _initResource(Settings.getAPI());
3.檢測是否存在API地址,不存在則彈出設置頁面
$scope.api = Settings.getAPI(); $ionicModal.fromTemplateUrl('templates/urlSetting.html', { scope: $scope }).then(function (modal) { $scope.settingModal = modal; if ((!$scope.api) || ($scope.api.indexOf("http://") === -1)) { if (window.StatusBar) { StatusBar.styleDefault(); } $scope.settingModal.show(); } }); //保存設置值方法 $scope.saveSettings = function () { //1.save setting 到localstorage if (!$scope.settings.wifiMode) { $scope.settings.wifi = ""; } Settings.save($scope.settings); $ionicLoading.show({ noBackdrop: true, template: "<div><h1><i class='icon ion-checkmark-circled balanced'></i></h1>保存成功</div>", duration: 1000 }); $scope.api = Settings.getAPI(); //2.變動全部Service 中的resource _Sys.changeResource($scope.api); $scope.settingModal.hide(); };
爲了實現APP的後臺API地址動態改變,只要找到問題的核心,不外乎圍繞着API_URL 的獲取 和設置 來實現該功能
獲取:
設置:
【原創】,轉載請帶上原地址http://www.cnblogs.com/sloong/p/5151019.html