ionic 運行過程當中動態切換API服務器地址

ionic 運行過程當中動態切換API服務器地址

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。

設計的關鍵點:

  • 啓動時須要檢查localstorage裏面是否有url的值,沒有則彈出設置頁
  • ENV.api的賦值必定要先於APP的啓動,不然Service的$resource的url 都爲空了
  • Service 須要將$resource的定義封裝並開放出接口,便於後期改變$resource的url定義
  • 網絡制式改變,ENV.api的改變,Service的$resource的從新定義

設置頁面

請忽略美觀(-__-)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,實現大統一(●ˇ∀ˇ●)

設計思路改動點:

  • 拋棄ENV.api,全部獲取和設置,均以localstorage爲準
  • 簡化、優化API地址的獲取和設置,見下面Setting Service 的定義(新增getAPI(),getWIFIAPI())
  • 全部Service $resource中的URL,均取於Setting.getAPI()方法
  • 進入第一個頁面前,判斷Setting.getAPI()的值是否存在,不存在則彈出設置頁面進行設置

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 的獲取 和設置 來實現該功能

獲取:

  • 判斷localstroage是否存儲了API_URL - 增長判斷方法
  • 與後臺服務器請求相關的Service - 變動$resource 的定義方法,並開放出改變的接口

設置:

  • localstroage裏面沒有API_URL ,彈出頁,保存時
  • 網絡制式發生變化時

【原創】,轉載請帶上原地址http://www.cnblogs.com/sloong/p/5151019.html

相關文章
相關標籤/搜索