У меня есть приложение, созданное с использованием Appcelerator Titanium (для iOS, последних SDK от Ti и Apple), и часть его в значительной степени опирается на карты.У меня проблема в том, что память не высвобождается, когда я закрываю окно, содержащее MapView.В результате переход с экрана меню на карту и обратно замедляет работу iPhone до тех пор, пока он не перестанет отвечать вообще (загрузка 3-5 карт).
Я использовал вызов Ti.Platform.availableMemory
от Titanium, чтобы увидеть памятьпри входе в окно с картой и после закрытия карты.Результатом является устойчивый нисходящий тренд с каждым последующим входом / выходом вдоль линий:
25 (начальная загрузка map.js)
20 (после аннотаций)
20 (после win.close()
)
19 (вторая загрузка map.js)
18 (аннотации)
19 (оставить)
18 (ввести)
16 (аннотации)
15 (оставить)
В симуляторе он может немного подняться, когда окно закрыто, но даже показывает устойчивый нисходящий тренд.
Вот код карты, который находится в ее собственном файле "map.js".Я сократил его до используемого функционального кода (поэтому здесь только прослушиватель событий для button_index
).
button_index.addEventListener('click', function()
{
Ti.App.xhr.abort();
if (mapview) {
mapview.removeAllAnnotations();
mapview = null;
}
if(policeJson){
policeJson = null;
fireJson = null;
}
Ti.App.police = false;
Ti.App.types = null;
win.close(); //This should clean up everything, according to the docs
Ti.API.info('Memory: ' + Ti.Platform.availableMemory);
});
var mapview;// = Ti.App.mapview;
Titanium.Geolocation.purpose = "Recieve User Location";
Titanium.Geolocation.accuracy = Titanium.Geolocation.ACCURACY_BEST;
Ti.API.info('Memory: ' + Ti.Platform.availableMemory);
function getMarkers(e){
var miles = Ti.App.miles;
Ti.API.info("Getting markers");
//Google's API radius is in meters, so we need to convert
var radius = miles * 1610; // 1mi = 1609.344 meters, so we just round up to 1610.
// http connection setup
Ti.App.xhr.setTimeout(10000);
googleLatLng = e.coords.latitude + "," + e.coords.longitude;
Ti.App.xhr.onload = function()
{
var data = Ti.XML.parseString(this.responseText);
var ref = data.documentElement.getElementsByTagName("reference");
if(ref != null && Ti.App.xhr.readyState == 4){
for(var i =0; i < ref.length; i++){
var marker = new Object();
marker.lat = data.documentElement.getElementsByTagName("lat").item(i).text;
marker.lng = data.documentElement.getElementsByTagName("lng").item(i).text;
marker.name = data.documentElement.getElementsByTagName("name").item(i).text;
marker.ref = ref.item(i).text;
addMarker(marker);
marker = null;
}
}
};
Ti.App.xhr.open("GET","https://maps.googleapis.com/maps/api/place/search/xml?location=" + googleLatLng + "&radius=" + radius + "&types=" + Ti.App.types + "&sensor=true&key=" + Ti.App.apiKey,false);
Ti.App.xhr.send();
Ti.API.info('Memory: ' + Ti.Platform.availableMemory);
}
// find the user's location and mark it on the map
function waitForLocation(e)
{
var region = null;
if ( e.error ) {
region = regionDefault; // User didn't let us get their location
var alertDialog = Titanium.UI.createAlertDialog({
title: 'Geolocation',
message: 'We were unable to center the map over your location.',
buttonNames: ['OK']
});
alertDialog.show();
} else {
region = {
latitude: e.coords.latitude,
longitude: e.coords.longitude,
animate:true,
latitudeDelta:0.05,
longitudeDelta:0.05
};
}
Ti.App.lat = region.latitude;
Ti.App.lng = region.longitude;
mapview.setLocation(region);
mapview.removeAllAnnotations();
currentLoc = Titanium.Map.createAnnotation({
latitude: region.latitude,
longitude: region.longitude,
title: e.error ? "Columbus" : "You are here!",
pincolor: Titanium.Map.ANNOTATION_RED,
animate:true
});
mapview.addAnnotation(currentLoc);
mapview.selectAnnotation(currentLoc);
mapview.addEventListener('click', function(e){
if (e.clicksource == 'rightButton') {
if (e.annotation.spotUrl != '') {
alert('Website!');
}
else {
alert('No website available');
}
}
});
if(Ti.App.police == true) {
var fire_img = "../../images/iNeighborhood/fire.png";
var police_img = "../../images/iNeighborhood/police.png";
serviceMarkers(fire_addr, fire_title, fire_lat_1, fire_long_1,fire_img);
serviceMarkers(police_addr, police_title, police_lat_1, police_long_1,police_img);
}
getMarkers(e);
}
function addMarker(marker){
var ann = Titanium.Map.createAnnotation({
animate:true,
latitude:marker.lat,
longitude:marker.lng,
title:marker.name,
pincolor: Titanium.Map.ANNOTATION_GREEN
});
mapview.addAnnotation(ann);
}
// Automatically refresh current location.
/*
* IN PROGRESS
*/
function getLocation(){
// create the mapView and center it on Columbus
if (!mapview) {
mapview = Titanium.Map.createView({
mapType: Titanium.Map.STANDARD_TYPE,
animate: true,
region: {
latitude: 39.961176,
longitude: -82.998794,
latitudeDelta: 0.1,
longitudeDelta: 0.1
},
regionFit: true,
userLocation: true,
visible: true,
top:29
});
//Ti.App.mapview = mapview;
win.add(mapview);
}
refresh();
//Get the current position and set it to the mapview
Titanium.Geolocation.getCurrentPosition(waitForLocation);
}
getLocation();
// pretty self explanatory...
function cleanMap(){
if (mapview) {
mapview.removeAllAnnotations();
}
if(xhr){
xhr.abort();
}
}
Ti.App.addEventListener('map:mapIt',function(){
cleanMap();
getLocation();
});
Вот часть кода со страницы индекса, которая загружает карту:
var winMap = Titanium.UI.createWindow({
url:'map.js',
tabBarHidden:false
});
btnEducation.addEventListener('click',function(){
Ti.App.types = Ti.App.schools;
Ti.UI.currentTab.open(winMap);
Ti.App.police = false;
});
Я создал глобальный HTTPClient и использовал его снова, как и предлагали некоторые ответы на другие вопросы и ответы (как на SO, так и на сайте Appcelerator), что, похоже, помогло (не так много памятиопустошенный при каждой загрузке карты), я также пытался вручную установить переменные (особенно большие) в ноль (что может или не может быть эффективным), но что-то все еще держится.Я также попытался создать окно карты внутри прослушивателя событий для кнопок, открывающих окно, но это, похоже, не дало никакого эффекта.
Я также запустил Инструменты, чтобы посмотреть, что он может найти, ине нашел ничего примечательного (я даже показал это своему коллеге, который занимается мобильной разработкой полный рабочий день, и он сказал, что не было ничего необычного, что он мог видеть).
Я искалв этом коде уже несколько часов, и это не весь мой код, так что вполне возможно, что я упускаю что-то очевидное, но есть ли причина в моем коде, почему память не освобождается должным образом?Могу ли я сделать что-то еще, чтобы освободить больше памяти?Сейчас я занимаюсь только разработкой для iOS, поэтому приемлемы решения для iOS.
Редактировать - Я также попытался включить часть карты в файл, который ее вызывает (используяTi.include('map.js')
).Я сделал быструю и грязную настройку, чтобы посмотреть, будет ли она работать:
Ti.include('map.js');
var button_index = Ti.UI.createButton({
text:'Back',
height:20,
width:50,
top:0,
left:0,
color:'#000'
});
button_index.addEventListener('click', function()
{
Ti.App.xhr.abort();
if (mapview) {
mapview.removeAllAnnotations();
// mapview = null;
}
if(policeJson){
policeJson = null;
fireJson = null;
}
Ti.App.police = false;
Ti.App.types = null;
Ti.App.title = null;
mapview.hide();
Ti.API.info('Memory: ' + Ti.Platform.availableMemory);
});
mapview.add(button_index);
mapview.hide();
btnArts.addEventListener('click',function(){
Ti.App.types = Ti.App.arts;
// Ti.UI.currentTab.open(winMap);
mapview.show();
Ti.App.fireEvent('map:mapIt'); //Triggers the chain of events to clear the map and add the necessary annotations to it
Ti.App.police = false;
Ti.App.title = 'arts';
});
Кажется, она работает лучше, но количество доступной памяти по-прежнему неуклонно уменьшается при входе и выходе изmapview, и начальная загрузка памяти делает его таким же непригодным для использования на устройствах, как и другой метод (объем памяти уменьшается примерно до 3 МБ).