luq techblog

o tworzeniu słów kilka…

Apcelerator Titanium dla Android`a 24 sierpnia 2010

Filed under: JS — Łukasz @ 14:05
Tags: , , , ,

Jakieś dwa tygodnie temu pokazano mi takie narzędzie jak Appcelerator Titanium. Titanium to platforma która umożliwia tworzyć aplikację deskoptowe jak i mobilne (iPhone, Android, iPad, BlackBerry) w językach czysto webowych (HTML, CSS, JavaScript, PHP, Python i Ruby). Jest to konkurencja dla Adobowego środowiska AIR z tą różnicą, że Titanium jest w pełni otwarte.

 

Przez te dwa tygodnie pracowałem (i dalej pracuję) nad pewną małą aplikacją dla Google Android, dlatego jedynie nad wersją mobilną API będę się rozwodzić.

 

Na początek rzuca się w oczy bardzo kiepska dokumentacja. Już wyjaśniam dlaczego kiepska… Po pierwsze, bardzo, ale to bardzo rzadko można spotkać jakiś przykład, co naprawdę, przynajmniej na początku, jest kłopotliwe. Po drugie, brakuje danych pewnych elementach API, które można wyczytać z cudzych kodów. Pierwszą z nich jest brak w ogóle wspomnienia w dokumentacji o aliasie do głównego obiektu API. Dokumentacja wspomina jedynie o Titanium natomiast wygodniej jest stosować o wiele krótszą nazwę Ti

// to samo
Titanium.userAgent;
Ti.userAgent;

Kolejnym takim elementem którego nie znalazłem w dokumentacji są setery do obiektów, np:

var bnt = Ti.UI.createButton({ title: 'foo' });
bnt.setTitle( 'bar' ); // o tym nie ma ani słowa 

Po trzecie, uważam, że fajnie by było dodać obrazki jak wygląda przykładowy obiekt z kontenera Ti.UI bo nie zawsze nazwa mówi sama za siebie, zresztą nawet jeśli mówi to wolałbym, żeby była możliwość podglądu obiektu, bo przecież nie mam zielonego pojęcia jak będzie wyglądał Ti.UI.Toolbar. Oczywiście każdy wie czym jest Toolbar ale jak ten konkretny obiekt wygląda z różnymi konfiguracjami parametrów już raczej nie bardzo.

 

W razie problemów i niejasności pomocy możemy szukać w Questions & Answers ale o wiele więcej informacji jest zawartych w panelu dyskusyjnym. Jeśli natomiast chcemy zobaczyć jakieś przykładowe kody to polecam pobrać i zaimportować do Titanium Kitchen Sink

 

Jadnak patrząc obiektywnie całe API jest bardzo proste, mamy łatwy dostęp do bazy danych urządzenia (jest to SQLite oczywiście), możemy korzystać z obiektu XHR, który obsługuje się dokładnie jak ten klasyczny znany z przeglądarek, tworzenie obiektów User Interface i dodawanie ich na ekran jest prościutkie. Przyszło mi bawić się także funkcjami dotyczącymi Facebooka i muszę powiedzieć, że umieszczenie czegoś na naszym Facebook`owym wall`u jest dziecinnie proste.

 

Najlepiej pokaże to na przykładnie. Nasza aplikacja będzie sprawdzała czy posiada dane w bazie urządzenia i tworzyła z tego tabele (obiekt TableView), natomiast jeśli nie będzie w bazie tych danych to nasza aplikacja spróbuje je pobrać w formacie JSON z przykładowej strony, zapisze je do bazy a następnie będzie postępować analogicznie jak wyżej. Efektem będzie wyświetlenie czegoś takiego:

Na początek tworzymy elementy GUI:

var loader = Ti.UI.createActivityIndicator({
    height :50,
    width :10,
	message : 'Loading data...'
});
var window = Ti.UI.createWindow({
	backgroundColor	:'#ddd',
	fullscreen : true
});
var table = Ti.UI.createTableView({
	backgroundColor : '#fff',
	width : 300,
	height : 360,
	top : 20,
	left : 10,
	borderRadius : 5,
	borderWidth : 1,
	borderColor : '#444',
	separatorColor : '#444',
	scrollable : true,
	rowHeight : 41
});
window.add( table );
window.open();

Tworzymy obiekt Window oraz TableView, którego dodajemy do okienka, następnie je otwieramy. Obiekt ActivityIndicator natomiast to okienko blokujące cały ekran jednocześnie informujące o wykonywaniu jakichś operacji. Będziemy je wyświetlać podczas pobieranie i zapisywania danych do bazy, po tych operacjach zostanie ukryte. Będzie to wyglądać tak:

Stworzymy sobie bazę danych:

Ti.Database.install( 'mybase.db', 'mybase' );
var db = Ti.Database.open( 'mybase' );
db.execute( 'CREATE TABLE IF NOT EXISTS user ( id INTEGER PRIMARY KEY, name VARCHAR, age INTEGER )' );

Z tego powodu, że nie wiemy czy user odpalił pierwszy raz aplikację czy po raz kolejny, tworzymy tabelkę najpierw sprawdzając czy aby na pewno takiej tabeli jeszcze nie ma. Następnie tworzymy dwie funkcję. Pierwsza pobiera nasze przykładowe dane:

function loadData(){
	loader.show(); // pokaż loader
	var data = null;
	
	var xhr = Ti.Network.createHTTPClient();
	xhr.onreadystatechange = function(){
		try{
			if( this.readyState == 4 && this.status == 200  ){
				data = eval( '(' + this.responseText + ')' );
				saveData( data ); // wywołanie kolejnej funckji
			}
		}
		catch( e ){
			Ti.API.info( e.name + ':' + e.message );
		}
	};
				
	xhr.open( 'GET', 'http://wls-team.ovh.org/projects/data.txt' );
	xhr.setTimeout( 5000 );
	xhr.send();
}

Po pobraniu danych z serwera uruchamiana jest kolejna zdefiniowana przez nas funkcja:

function saveData( dataArr ){
	var dataTable = [];
	
	for( var i = 0, len = dataArr.length; i < len; i++ ){
		db.execute( 
			'INSERT INTO user ( id, name, age ) VALUES ( ?, ?, ? )', 
			null,
			dataArr[i].name,
			dataArr[i].age
		);
		
		dataTable[i] = Ti.UI.createTableViewRow({ 
			title : dataArr[i].name + ' : ' + dataArr[i].age 
		});
	}
	
	table.setData( dataTable );
	loader.hide(); // ukryj loader
}

Zapisujemy dane do bazy i tworzymy obiekty wierszy dla tabeli, następnie dodajemy te dane do naszego obiektu TableView.

Pozostał nam jeszcze kod główny:

var q = db.execute( 'SELECT name, age FROM user' );

if( q.rowCount == 0 ){
	loadData();	
}
else{
	var dataTable = [];
	var i = 0;
	
	while( q.isValidRow() ){	
		dataTable[i] = Ti.UI.createTableViewRow({ 
			title : q.fieldByName( 'name' ) + ':' + q.fieldByName( 'age' ) 
		});
		
		i++;
		q.next();
	}
	q.close();
	
	table.setData( dataTable );
}

To wszystko. Prawda, że proste? Na koniec dodam tylko cały kod w jednej części:

ffunction loadData(){
	loader.show(); // pokaż loader
	var data = null;
	
	var xhr = Ti.Network.createHTTPClient();
	xhr.onreadystatechange = function(){
		try{
			Ti.API.info( 'state: ' + this.readyState ); //@log
			
			if( this.readyState == 4 && this.status == 200  ){
				data = eval( '(' + this.responseText + ')' );
				saveData( data );
			}
		}
		catch( e ){
			Ti.API.info( e.name + ':' + e.message );
		}
	};
				
	xhr.open( 'GET', 'http://wls-team.ovh.org/projects/data.txt' );
	xhr.setTimeout( 5000 );
	xhr.send();
}

function saveData( dataArr ){
	var dataTable = [];
	
	for( var i = 0, len = dataArr.length; i < len; i++ ){
		db.execute( 
			'INSERT INTO user ( id, name, age ) VALUES ( ?, ?, ? )', 
			null,
			dataArr[i].name,
			dataArr[i].age
		);
		
		dataTable[i] = Ti.UI.createTableViewRow({ 
			title : dataArr[i].name + ' : ' + dataArr[i].age 
		});
	}
	
	table.setData( dataTable );
	loader.hide(); // ukryj loader
}

// gui
var loader = Ti.UI.createActivityIndicator({
    height :50,
    width :10,
	message : 'Loading data...'
});
var window = Ti.UI.createWindow({
	backgroundColor	:'#ddd',
	fullscreen : true
});
var table = Ti.UI.createTableView({
	backgroundColor : '#fff',
	width : 300,
	height : 360,
	top : 20,
	left : 10,
	borderRadius : 5,
	borderWidth : 1,
	borderColor : '#444',
	separatorColor : '#444',
	scrollable : true,
	rowHeight : 41
});
window.add( table );
window.open();

// database
Ti.Database.install( 'mybase.db', 'mybase' );
	var db = Ti.Database.open( 'mybase' );
	db.execute( 'CREATE TABLE IF NOT EXISTS user ( id INTEGER PRIMARY KEY, name VARCHAR, age INTEGER )' );
	
// main
var q = db.execute( 'SELECT name, age FROM user' );

if( q.rowCount == 0 ){
	loadData();	
}
else{
	var dataTable = [];
	var i = 0;
	
	while( q.isValidRow() ){	
		dataTable[i] = Ti.UI.createTableViewRow({ 
			title : q.fieldByName( 'name' ) + ':' + q.fieldByName( 'age' ) 
		});
		
		i++;
		q.next();
	}
	q.close();
	
	table.setData( dataTable );
}
Reklamy
 

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Wyloguj / Zmień )

Facebook photo

Komentujesz korzystając z konta Facebook. Wyloguj / Zmień )

Google+ photo

Komentujesz korzystając z konta Google+. Wyloguj / Zmień )

Connecting to %s