<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Blog Technologiczny ATENA &#187; Bez kategorii</title>
	<atom:link href="http://blog.atena.pl/category/uncategorized/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.atena.pl</link>
	<description>JavaEE, AJAX, xHTML, RIA, JBoss</description>
	<lastBuildDate>Fri, 20 Jan 2012 11:18:46 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>JavaFX 2 &#8211; aplikacja wielowątkowa</title>
		<link>http://blog.atena.pl/javafx-2-aplikacja-wielowatkowa</link>
		<comments>http://blog.atena.pl/javafx-2-aplikacja-wielowatkowa#comments</comments>
		<pubDate>Fri, 20 Jan 2012 11:18:46 +0000</pubDate>
		<dc:creator>Marcin Garniewski</dc:creator>
				<category><![CDATA[Bez kategorii]]></category>

		<guid isPermaLink="false">http://blog.atena.pl/?p=1183</guid>
		<description><![CDATA[Kontynuując nasz wątek blogowy o JavaFX 2.0, chciałbym dziś zaprezentować kilka możliwości JavaFX. Głównym tematem jest oczywiście wielowątkowość, ale znajdzie się też miejsce na wiązanie danych pomiędzy warstwą danych a warstwą prezentacji, definiowanie akcji oraz pracę z biblioteką JavaFX z wykorzystaniem środowiska Maven. Temat wielowątkowości, szczególnie w kontekście aplikacji typu „gruby klient”, nigdy nie był [...]]]></description>
			<content:encoded><![CDATA[<p>Kontynuując nasz wątek blogowy o JavaFX 2.0, chciałbym dziś zaprezentować kilka możliwości JavaFX. Głównym tematem jest oczywiście wielowątkowość, ale znajdzie się też miejsce na wiązanie danych pomiędzy warstwą danych a warstwą prezentacji, definiowanie akcji oraz pracę z biblioteką JavaFX z wykorzystaniem środowiska Maven.<br />
<span id="more-1183"></span><br />
Temat wielowątkowości, szczególnie w kontekście aplikacji typu „gruby klient”, nigdy nie był łatwy. Zapewnienie odpowiedniej synchronizacji, komunikacji oraz braku zakleszczeń może niejednego programistę przyprawić o zawrót głowy. Śmiało można śmiało powiedzieć, że JavaFX wprowadza nową jakość w tworzeniu tego typu aplikacji. Udogodnienia dostępne w wersji 2.0 dają wiele możliwości. W efekcie kod aplikacji oraz czas wykonania są znacznie krótsze w porównaniu do tworzenia bliźniaczej aplikacji w bibliotece SWING.<br />
<span><br />
W JavaFX klasy i interfejsy związane z obsługą wielowątkowości znajdują się w pakiecie <b>javafx.concurrent</b>. Interfejs <b>Worker</b> jest implementowany przez pozostałe dwie klasy: <b>Task</b> i <b>Service</b>. Obiekt typu Worker wykonuje prace w jednym lub kilku równoległych wątkach. Stan jest w pełni obserwowalny i dostępny dla głównego wątku interfejsu GUI. Nie da się natomiast bezpośrednio modyfikować stanu interfejsu GUI. Próba taka kończy się wyjątkiem. Abstrakcyjna klasa <b>Task</b> służy do enkapsulacji pracy, jaka ma być wykonywana w danym wątku. Implementująca klasa musi wypełnić metodę <b>call</b>, która będzie wykonywana podczas uruchomienia wątku. Obiektu tej klasy nie można ponownie uruchomić. Ostatnią klasą jest <b>Service</b>, która &#8211; dla odmiany &#8211; da się użyć ponownie  poprzez restart lub reset.<br />
</span><br />
Z kodu tych wątków nie można bezpośrednio modyfikować stanu GUI. Wszystkie operacje komunikacji wykonuje za nas silnik JavaFX. Wystarczy powiązać (ang. bind) odpowiedni parametr z elementem graficznym. Domyślnie interfejs <b>Worker</b> oferuje nam całą listę parametrów związanych ze stanem wątku. Niektóre z nich to:</p>
<ul>
<li>ReadOnlyStringProperty 	messageProperty()</li>
<li>ReadOnlyDoubleProperty 	progressProperty()</li>
<li>ReadOnlyBooleanProperty 	runningProperty()</li>
<li>ReadOnlyObjectProperty<Worker.State> 	stateProperty()</li>
<li>ReadOnlyStringProperty 	titleProperty()</li>
<li>ReadOnlyDoubleProperty 	totalWorkProperty()</li>
</ul>
<p>Można też oczywiście dodawać własne parametry. Przykładowo, aby powiązać parametr „message” z elementem wizualnym typu TextField, należy wykonać polecenie:</p>
<div class="codecolorer-container java5 default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="java5 codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">task.<span style="color: #006633;">messageProperty</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">bind</span><span style="color: #009900;">&#40;</span>textField.<span style="color: #006633;">textProperty</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>A następnie w kodzie wątku wywołać polecenie:</p>
<div class="codecolorer-container java5 default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="java5 codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">updateMessage<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;tekst do prezentacji&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>Demonstracyjna aplikacja będzie uruchamiała wątki typu <b>Task</b> i <b>Service</b>. Każdy z nich będzie informował interfejs o postępie wykonania swojego zadania. Każdy wiersz w tabeli to jeden wątek. Pierwsza kolumna w tabeli będzie zawierała nazwę wątku nadaną przez maszynę wirtualną Javy. Druga kolumna będzie zawierała element typu ProgressBar, który będzie na bieżąco pokazywał stan zaawansowania wykonania danego wątku. W naszym przypadku wątek nie będzie nic robił oprócz ustawienia stanu postępu i przejścia w stan uśpienia. W docelowej aplikacji wątek taki może wykonywać dowolne zadanie, nie blokując jednocześnie GUI. Aplikację utworzyłem w edytorze IDE Eclipse, wykorzystująć środowisko Maven.</p>
<p><a href="http://blog.atena.pl/wp-content/uploads/2012/01/JavaFXThreads1.png"><img src="http://blog.atena.pl/wp-content/uploads/2012/01/JavaFXThreads1-300x235.png" alt="" title="JavaFXThreads" width="300" height="235" class="aligncenter size-medium wp-image-2324" /></a></p>
<p><b>Przygotowanie środowiska i utworzenie nowego projektu</b></p>
<ol>
<li>
Utworzenie projektu</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">mvn archetype:generate <span style="color: #660033;">-DarchetypeGroupId</span>=org.apache.maven.archetypes <span style="color: #660033;">-DgroupId</span>=pl.atena.javafxblog <span style="color: #660033;">-DartifactId</span>=JavaFXBlog</div></td></tr></tbody></table></div>
</li>
<li>
Dodanie plików konfiguracyjnych wymaganych przez Eclipse. Wchodzimy do katalogu JavaFXBlog i wykonujemy polecenie:</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">mvn eclipse:eclipse</div></td></tr></tbody></table></div>
</li>
<li>
Modyfikacja pliku konfiguracyjnego pom.xml. W sekcji <b>&lt;dependencies&gt;</b> dodajemy zależność do biblioteki JavaFX2:</p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>javafx<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>javafxrt<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>2.0.2<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;scope<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>system<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/scope<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;systemPath<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>C:/Program Files/Oracle/JavaFX 2.0 SDK/rt/lib/jfxrt.jar<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/systemPath<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></td></tr></tbody></table></div>
<p>Ścieżka do biblioteki <b>jfxrt.jar</b> w elemencie &lt;systemPath&gt; powinna odpowiadać lokalizacji tego pliku na naszym komputerze.
</li>
<li>
Import projektu do środowiska Eclipse</p>
<p>W aplikacji Eclipse wybieramy opcje File->Import&#8230;->Existing Projects into Workspace i wskazujemy katalog z projektem.
</li>
</ol>
<h4>Kod aplikacji</h4>
<p>Aplikacja składa się z dwóch elementów: tabeli i przycisku. Przykładowe ułożenie elementów może być wykonane w następujący sposób:</p>
<div class="codecolorer-container java5 default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br /></div></td><td><div class="java5 codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #006600; font-weight: bold;">void</span> start<span style="color: #009900;">&#40;</span>Stage primaryStage<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <a href="http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/lang/Exception.html"><span style="color: #003399; font-weight: bold;">Exception</span></a> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; tableData = <span style="color: #000000; font-weight: bold;">new</span> TableView<span style="color: #339933;">&lt;</span>Worker<span style="color: #339933;">&lt;</span>Void<span style="color: #339933;">&gt;&gt;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; runTaskButton = <span style="color: #000000; font-weight: bold;">new</span> <a href="http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/awt/Button.html"><span style="color: #003399; font-weight: bold;">Button</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Nowy wątek typu Task&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; runServiceButton = <span style="color: #000000; font-weight: bold;">new</span> <a href="http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/awt/Button.html"><span style="color: #003399; font-weight: bold;">Button</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Nowy wątek typu Service&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; BorderPane rootGroup = <span style="color: #000000; font-weight: bold;">new</span> BorderPane<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; FlowPane paneFlow = <span style="color: #000000; font-weight: bold;">new</span> FlowPane<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; paneFlow.<span style="color: #006633;">getChildren</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">addAll</span><span style="color: #009900;">&#40;</span>runTaskButton, runServiceButton<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; paneFlow.<span style="color: #006633;">setPadding</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> <a href="http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/awt/Insets.html"><span style="color: #003399; font-weight: bold;">Insets</span></a><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">10</span>, <span style="color: #cc66cc;">10</span>, <span style="color: #cc66cc;">10</span>, <span style="color: #cc66cc;">10</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; paneFlow.<span style="color: #006633;">setHgap</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">10</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; paneFlow.<span style="color: #006633;">setVgap</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">10</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; paneFlow.<span style="color: #006633;">setAlignment</span><span style="color: #009900;">&#40;</span>Pos.<span style="color: #006633;">CENTER</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; rootGroup.<span style="color: #006633;">setCenter</span><span style="color: #009900;">&#40;</span>tableData<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; rootGroup.<span style="color: #006633;">setBottom</span><span style="color: #009900;">&#40;</span>paneFlow<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; Scene scene = <span style="color: #000000; font-weight: bold;">new</span> Scene<span style="color: #009900;">&#40;</span>rootGroup, <span style="color: #cc66cc;">800</span>, <span style="color: #cc66cc;">600</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; scene.<span style="color: #006633;">setFill</span><span style="color: #009900;">&#40;</span><a href="http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/awt/Color.html"><span style="color: #003399; font-weight: bold;">Color</span></a>.<span style="color: #006633;">OLDLACE</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; primaryStage.<span style="color: #006633;">setTitle</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;JavaFX Blog&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; primaryStage.<span style="color: #006633;">setScene</span><span style="color: #009900;">&#40;</span>scene<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; configTable<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; attachActions<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; bindData<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; primaryStage.<span style="color: #006633;">show</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Powiązanie tabeli z listą utworzonych wątków. Ważne jest, aby kolekcja przechowująca listę wątków była typu „ObservableList”</p>
<div class="codecolorer-container java5 default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="java5 codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #006600; font-weight: bold;">void</span> bindData<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; tableData.<span style="color: #006633;">setItems</span><span style="color: #009900;">&#40;</span>listThreads.<span style="color: #006633;">getThreadList</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>gdzie obiekt <b>threadList</b> został utworzony w następujący sposób:</p>
<div class="codecolorer-container java5 default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="java5 codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">final</span> ObservableList<span style="color: #339933;">&lt;</span>ThreadTask<span style="color: #339933;">&gt;</span> threadList = FXCollections.<span style="color: #006633;">observableArrayList</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>W tabeli znajdują się dwie kolumny. Pierwsza będzie wyświetlać nazwę wątku, druga postęp wykonania zadania. Konfiguracja tabeli z dwiema kolumnami:</p>
<div class="codecolorer-container java5 default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br /></div></td><td><div class="java5 codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #006600; font-weight: bold;">void</span> configTable<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; tableData.<span style="color: #006633;">setEditable</span><span style="color: #009900;">&#40;</span><span style="color: #006600; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/swing/table/TableColumn.html"><span style="color: #003399; font-weight: bold;">TableColumn</span></a> nameCol = <span style="color: #000000; font-weight: bold;">new</span> <a href="http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/swing/table/TableColumn.html"><span style="color: #003399; font-weight: bold;">TableColumn</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Nazwa wątku&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; nameCol.<span style="color: #006633;">setCellValueFactory</span><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">new</span> PropertyValueFactory<span style="color: #339933;">&lt;</span>ThreadTask,Integer<span style="color: #339933;">&gt;</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;name&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #666666; font-style: italic;">//1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; nameCol.<span style="color: #006633;">setPrefWidth</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">150</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> &nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/swing/table/TableColumn.html"><span style="color: #003399; font-weight: bold;">TableColumn</span></a> progressCol = <span style="color: #000000; font-weight: bold;">new</span> <a href="http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/swing/table/TableColumn.html"><span style="color: #003399; font-weight: bold;">TableColumn</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Postęp&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; progressCol.<span style="color: #006633;">setCellValueFactory</span><span style="color: #009900;">&#40;</span> <span style="color: #000000; font-weight: bold;">new</span> Callback<span style="color: #339933;">&lt;</span>CellDataFeatures<span style="color: #339933;">&lt;</span>ThreadTask, ProgressBar<span style="color: #339933;">&gt;</span>, ObservableValue<span style="color: #339933;">&lt;</span>ProgressBar<span style="color: #339933;">&gt;&gt;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @<a href="http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/lang/Override.html"><span style="color: #003399; font-weight: bold;">Override</span></a><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> ObservableValue<span style="color: #339933;">&lt;</span>ProgressBar<span style="color: #339933;">&gt;</span> call<span style="color: #009900;">&#40;</span>CellDataFeatures<span style="color: #339933;">&lt;</span>ThreadTask, ProgressBar<span style="color: #339933;">&gt;</span> arg0<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ThreadTask task = arg0.<span style="color: #006633;">getValue</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ProgressBar bar = <span style="color: #000000; font-weight: bold;">new</span> ProgressBar<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bar.<span style="color: #006633;">setPrefWidth</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">630</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bar.<span style="color: #006633;">progressProperty</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">bind</span><span style="color: #009900;">&#40;</span>task.<span style="color: #006633;">progressProperty</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//2</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000000; font-weight: bold;">new</span> SimpleObjectProperty<span style="color: #339933;">&lt;</span>ProgressBar<span style="color: #339933;">&gt;</span><span style="color: #009900;">&#40;</span>bar<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; progressCol.<span style="color: #006633;">setPrefWidth</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">630</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; tableData.<span style="color: #006633;">getColumns</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">addAll</span><span style="color: #009900;">&#40;</span>nameCol, progressCol<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Dane w komórkach tabeli powiązane są z polami w klasie typu ThreadTask. W pierwszej kolumnie definiujemy odczytywanie danych z funkcji getName() — linia nr 1. Druga kolumna <b>progressCol</b> jest trochę bardziej skomplikowana. Umieszczony został w niej element typu <b>ProgressBar</b>. Powinien on wyświetlać aktualny stan wykonania zadania. Powiązanie to jest wykonane w linii nr 2.</p>
<p>Teraz najważniejszy element demonstracyjnej aplikacji: uruchomienie nowego wątku po wciśnięciu przycisku „Nowy wątek typu Task” lub &#8222;Nowy wątek typu Service&#8221;. Kod akcji uruchamiany po wciśnięciu przycisku:</p>
<div class="codecolorer-container java5 default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br /></div></td><td><div class="java5 codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #006600; font-weight: bold;">void</span> attachActions<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; runTaskButton.<span style="color: #006633;">setOnAction</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> EventHandler<span style="color: #339933;">&lt;</span>ActionEvent<span style="color: #339933;">&gt;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #006600; font-weight: bold;">void</span> handle<span style="color: #009900;">&#40;</span><a href="http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/awt/event/ActionEvent.html"><span style="color: #003399; font-weight: bold;">ActionEvent</span></a> t<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ThreadTask task = <span style="color: #000000; font-weight: bold;">new</span> ThreadTask<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">new</span> <a href="http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/lang/Thread.html"><span style="color: #003399; font-weight: bold;">Thread</span></a><span style="color: #009900;">&#40;</span>task<span style="color: #009900;">&#41;</span>.<span style="color: #006633;">start</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//2</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; listThreads.<span style="color: #006633;">getThreadList</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span>task<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; runServiceButton.<span style="color: #006633;">setOnAction</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> EventHandler<span style="color: #339933;">&lt;</span>ActionEvent<span style="color: #339933;">&gt;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #006600; font-weight: bold;">void</span> handle<span style="color: #009900;">&#40;</span><a href="http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/awt/event/ActionEvent.html"><span style="color: #003399; font-weight: bold;">ActionEvent</span></a> t<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Service service = <span style="color: #000000; font-weight: bold;">new</span> ServiceTask<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//3</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; service.<span style="color: #006633;">setExecutor</span><span style="color: #009900;">&#40;</span>executor<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//4</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; service.<span style="color: #006633;">start</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//5</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; listThreads.<span style="color: #006633;">getThreadList</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span>service<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//6</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>W linii nr 1 tworzymy nowy obiekt typu ThreadTask (kod poniżej). Implementuje on interfejs &#8222;Runnable&#8221; a więc można go uruchomić jak zwykły wątek javowy &#8211; linia nr 2. Obiekt klasy ServiceTask jest uruchamiany poprzez wywołanie metody &#8222;start()&#8221;, linia nr 5. Politykę zarządzania wątkami ustawia się metodą &#8222;setExecutor&#8221;. W linii nr 6 dodajemy wątek do listy wyświetlanej przez obiekt Table. Kod klasy ThreadTask:</p>
<div class="codecolorer-container java5 default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br /></div></td><td><div class="java5 codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> ThreadTask <span style="color: #000000; font-weight: bold;">extends</span> Task<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #006600; font-weight: bold;">int</span> MAX = <span style="color: #cc66cc;">100</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// maksymalna wartość postępu</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #006600; font-weight: bold;">int</span> SLEEP_TIME = <span style="color: #cc66cc;">200</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// czas wstrzymania wątku w ms</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> <a href="http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/lang/String.html"><span style="color: #003399; font-weight: bold;">String</span></a> threadName<span style="color: #339933;">;</span> &nbsp; &nbsp;<span style="color: #666666; font-style: italic;">// nazwa wątku</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #008000; font-style: italic; font-weight: bold;">/**<br />
&nbsp; &nbsp; &nbsp;* @return Nazwa wątku<br />
&nbsp; &nbsp; &nbsp;*/</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <a href="http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/lang/String.html"><span style="color: #003399; font-weight: bold;">String</span></a> getName<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> threadName<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #008000; font-style: italic; font-weight: bold;">/**<br />
&nbsp; &nbsp; &nbsp;* Wykonanie zadania<br />
&nbsp; &nbsp; &nbsp;* @see javafx.concurrent.Task#call()<br />
&nbsp; &nbsp; &nbsp;*/</span><br />
&nbsp; &nbsp; @<a href="http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/lang/Override.html"><span style="color: #003399; font-weight: bold;">Override</span></a><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">protected</span> <a href="http://www.google.com/search?sitesearch=java.sun.com&amp;q=allinurl%3Aj2se%2F1+5+0%2Fdocs%2Fapi+Object"><span style="color: #003399; font-weight: bold;">Object</span></a> call<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <a href="http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/lang/Exception.html"><span style="color: #003399; font-weight: bold;">Exception</span></a> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; threadName = <a href="http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/lang/Thread.html"><span style="color: #003399; font-weight: bold;">Thread</span></a>.<span style="color: #006633;">currentThread</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">getName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; &nbsp;font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #006600; font-weight: bold;">int</span> i=<span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span> i<span style="color: #339933;">&lt;</span>=MAX<span style="color: #339933;">;</span> i++<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> &nbsp;<span style="color: #666666; font-style: italic;">// pętla od 1 do 100</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; updateProgress<span style="color: #009900;">&#40;</span>i, MAX<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> &nbsp; <span style="color: #666666; font-style: italic;">// aktualizacja postępu pracy wątku</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/lang/Thread.html"><span style="color: #003399; font-weight: bold;">Thread</span></a>.<span style="color: #006633;">sleep</span><span style="color: #009900;">&#40;</span>SLEEP_TIME<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// wstrzymanie czasu pracy wątku &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #006600; font-weight: bold;">null</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Aktualizacja postępu wykonania jest ustawiana za pomocą metody <b>updateProgress(int,int)</b>. Pierwszy argument to stan pracy, drugi wartość maksymalna.</p>
<p> Kod klasy ThreadService:</p>
<div class="codecolorer-container java5 default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br /></div></td><td><div class="java5 codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> ThreadService <span style="color: #000000; font-weight: bold;">extends</span> Service<span style="color: #339933;">&lt;</span>Void<span style="color: #339933;">&gt;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> ThreadTask task<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <a href="http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/lang/String.html"><span style="color: #003399; font-weight: bold;">String</span></a> getName<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #0000ff;">&quot;[Service] &quot;</span> + task.<span style="color: #006633;">getThreadName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; @<a href="http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/lang/Override.html"><span style="color: #003399; font-weight: bold;">Override</span></a><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">protected</span> Task createTask<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; task = <span style="color: #000000; font-weight: bold;">new</span> ThreadTask<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> task<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<h4>Podsumowanie</h4>
<p>Jak widać, programowanie wielowątkowe w JavaFX 2 jest dość łatwe. Po poznaniu mechanizmu tworzenia i uruchamiania wątków oraz komunikacji wątków z interfejsem javafx mamy pewność, że pisane przez nas programy będą stabilne i wydajne. </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.atena.pl/javafx-2-aplikacja-wielowatkowa/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Wstęp do Androida</title>
		<link>http://blog.atena.pl/wstep-do-androida</link>
		<comments>http://blog.atena.pl/wstep-do-androida#comments</comments>
		<pubDate>Wed, 14 Dec 2011 07:13:07 +0000</pubDate>
		<dc:creator>Piotr Łabuński</dc:creator>
				<category><![CDATA[Bez kategorii]]></category>

		<guid isPermaLink="false">http://blog.atena.pl/?p=2004</guid>
		<description><![CDATA[Android jest obecnie najpopularniejszym systemem operacyjnym przeznaczonym dla urządzeń mobilnych. Według danych firmy Canalys w ostatnim kwartale 2010 roku Android osiągnął wynik 32,9 miliona sprzedanych telefonów, wyprzedzając Symbiana (31 mln) oraz pozostawiając w tyle iOS (16,2 mln). Od przejęcia w roku 2005 roku firmy Android Inc. rozwijany jest przez Google. Opiera się na jądrze Linuxa. [...]]]></description>
			<content:encoded><![CDATA[<p>Android jest obecnie najpopularniejszym systemem operacyjnym przeznaczonym dla urządzeń mobilnych.  Według danych firmy Canalys w ostatnim kwartale 2010 roku Android osiągnął wynik 32,9 miliona sprzedanych telefonów, wyprzedzając Symbiana (31 mln) oraz pozostawiając w tyle iOS (16,2 mln). Od przejęcia w roku 2005 roku firmy Android Inc. rozwijany jest przez Google. Opiera się na jądrze Linuxa. Działa na zasadach wolnego oprogramowania (Apache License 2.0) – nie licząc linii 3.x przeznaczonej wyłącznie na tablety. Android udostępnia bardzo rozbudowane możliwości deweloperskie: bazę danych SQLite, WebKit, GPS, sensory, bibliotekę graficzną OpenGL ES, TTS i wiele innych. W tym artykule przedstawię podstawowe informacje dotyczące Androida oraz pokażę, jak zacząć swoją przygodę z programowaniem w ramach tej platformy.</p>
<p><span id="more-2004"></span></p>
<h3>Ważniejsze pojęcia</h3>
<ul>
<li>Activity – klasa,  która odpowiada za stworzenie okna aplikacji. Zawiera takie metody jak onCreate (wywoływana w momencie inicjalizacji klasy) oraz inne metody reagujące na przejście klasy w inne stany cyklu życia, np. onPause, onStop, onResume i inne. </li>
<li>Layout – schemat określający rozmieszczenie elementów na ekranie. </li>
<li>Intent – klasa opisująca operację, którą mamy zamiar wykonać.</li>
<li>SDK (Software Development Kit) &#8211; zbiór narzędzi umożliwiający pisanie, uruchamianie oraz testowanie aplikacji w danej technologii &#8211; w naszym przypadku dla platformy Android.</li>
<li>NDK (Native Development Kit) – zbiór narzędzi umożliwiający pisanie aplikacji w języku C/C++ dla platformy Android.</li>
<li>ADT (Android Development Tools) – plugin umożliwiający pisanie aplikacji na Androida przy wykorzystaniu środowiska Eclipse.</li>
<li>AVD (Android Virtual Device) – emulator systemu Android umożliwiający uruchomienie plików .apk na komputerze.</li>
</ul>
<h3>Jak zacząć</h3>
<h4>Język programowania</h4>
<p>Podstawowym językiem programowania dla tej platformy jest Java z ograniczonym API,  dostosowana do potrzeb smartfonów i tabletów (Android SDK). Przy pomocy NDK (Native Development Kit) można również korzystać z języka C/C++, co może spowodować znaczne zwiększenie szybkości pracy aplikacji, np. w wypadku zaawansowanych operacji graficznych. NDK umożliwia pisanie mieszanych aplikacji Java/C/C++ jak również (od wersji  r5) samodzielnych aplikacji C/C++.</p>
<h4>Środowisko programistyczne</h4>
<p> Do pisania aplikacji na urządzenia z systemem Android można wykorzystać takie IDE, jak Eclipse, NetBeans czy IntelliJ IDEA. W tym przykładzie skorzystamy z pierwszego z nich. Instalacja środowiska (oryginalna instrukcja pod adresem <a href="http://developer.android.com/sdk/installing.html">http://developer.android.com/sdk/installing.html</a>):</br><br />
1. Ściągamy i instalujemy JDK5 lub JDK6. Samo JRE jest niewystarczające.</p>
<ul>
<li><a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html">http://www.oracle.com/technetwork/java/javase/downloads/index.html</a></li>
</ul>
<p>2. Ściągamy i instalujemy Eclipse (for Java Developers, for Java EE Developers lub Classic w wersji 3.5.1 lub wyższej).</p>
<ul>
<li><a href="http://www.eclipse.org/downloads/">http://www.eclipse.org/downloads/</a></li>
</ul>
<p>3. Ściągamy i instalujemy Android SDK.</p>
<ul>
<li><a href="http://developer.android.com/sdk/index.html">http://developer.android.com/sdk/index.html</a></li>
</ul>
<p>4. Dodajemy komponent do SDK.</p>
<ul>
<li>Włączamy „SDK Manager”.</li>
<li>Automatycznie zostaną wyszukane wszystkie aktualizacje.</li>
<li>Akceptujemy licencje paczek, które nas interesują i klikamy Install.</li>
</ul>
<p><a href="http://blog.atena.pl/wp-content/uploads/2011/12/instalowaniePaczek.jpg"><img src="http://blog.atena.pl/wp-content/uploads/2011/12/instalowaniePaczek.jpg" alt="" title="instalowaniePaczek" width="740" height="370" class="aligncenter size-full wp-image-2122" /></a><br />
<strong>Wskazówka:</strong> Gdy łączymy się przez serwer Proxy, należy włączyć SDK Manager, wejść w Tools > Options… (w starszych wersjach SDK wchodzimy w Settings) i tam skonfigurować swoje połączenie.</br><br />
5. Dodajemy AVD (Android Virtual Device).</p>
<ul>
<li>Włączamy „SDK Manager”.</li>
<li>Wchodzimy w Tools > Manage AVDs…</li>
<li>Klikamy New.</li>
<li>W nowym oknie nadajemy nazwę nowemu AVD.</li>
<li>W polu Target wybieramy interesującą nas wersję API. Numer API określa minimalną wersję Androida, dla której aplikacja będzie działać poprawnie, np. API 7 określa wersję Androida 2.1. Kolejne platformy wersji 1.x i 2.x są kompatybilne wstecz.</li>
<li>Wybieramy rodzaj wyświetlacza w polu Skin oraz inne parametry sprzętowe w polu Hardware.</li>
<li>Możemy również zaznaczyć opcję Snapshot, która umożliwi szybsze włączanie się emulatora.</li>
<li>Klikamy Create AVD.</li>
</ul>
<p><a href="http://blog.atena.pl/wp-content/uploads/2011/12/AVD.jpg"><img src="http://blog.atena.pl/wp-content/uploads/2011/12/AVD.jpg" alt="" title="AVD" width="421" height="598" class="aligncenter size-full wp-image-2119" /></a><br />
<strong>Wskazówka:</strong> Przy większych projektach lub wymagających dostępu do niektórych elementów sprzętowych korzystanie z emulatora może okazać się bardzo uciążliwe lub w ogóle niemożliwe.  W takich przypadkach warto skorzystać z możliwości bezpośredniego instalowania/debugowania aplikacji w telefonie. Aby to zrobić, należy w ustawieniach telefonu wybrać opcję Aplikacje, zaznaczyć pole Nieznane źródła oraz w zakładce Dla programistów zaznaczyć Debugowanie USB. Następnie podłączamy telefon do komputera przy pomocy kabla USB. Aby sprawdzić, czy nasze urządzenie jest widziane przez Android Debug Bridge (ADB), należy w konsoli wywołać komendę adb devices. Powinna pojawić się lista podłączonych urządzeń z systemem Android oraz włączonych emulatorów. Jeżeli na tej liście znajduje się nasz telefon, możemy z poziomu Eclipse instalować, uruchamiać oraz debugować (przy pomocy DDMS) w nim nasze aplikacje.</br><br />
6. Instalujemy ADT(Android Development Tools).</p>
<ul>
<li>Włączamy Eclipse.</li>
<li>Wchodzimy w Help > Install New Software.</li>
<li>Klikamy Add.</li>
<li>Location: <a href="https://dl-ssl.google.com/android/eclipse/">https://dl-ssl.google.com/android/eclipse/.</a></li>
<li>Klikamy Ok.</li>
<li>Zaznaczamy Developer Tools i klikamy Next.</li>
<li>Kolejny raz klikamy Next, następnie pojawią się warunki licencji, akceptujemy i klikamy Finish</li>
<li>Restartujemy Eclipsa.</li>
</ul>
<p><strong>Wskazówka:</strong> Gdy łączymy się przez serwer Proxy, należy włączyć Eclipse i wejść w Window > Preferences > General > Network Connections i tam skonfigurować swoje połączenie.</br><br />
7. Konfiguracja ADT</p>
<ul>
<li>Włączamy Eclipse.</li>
<li>Wchodzimy w Window > Preferences.</li>
<li>Wybieramy zakładkę Android.</li>
<li>Klikamy Browse i wybieramy miejsce, w którym zainstalowaliśmy Android SDK.</li>
<li>Klikamy Apply a następnie Ok.</li>
</ul>
<p><a href="http://blog.atena.pl/wp-content/uploads/2011/12/ConfAVD.jpg"><img src="http://blog.atena.pl/wp-content/uploads/2011/12/ConfAVD.jpg" alt="konfiguracja AVD" title="ConfAVD" width="838" height="542" class="aligncenter size-full wp-image-2114" /></a></p>
<h3>Przykładowa aplikacja</h3>
<p>Pierwszą aplikacją na telefony z systemem Android będzie prosty notatnik umożliwiający dodawanie, usuwanie oraz edytowanie notatek. Nasza aplikacja będzie składała się z dwóch layout’ów: jednego zawierającego listę naszych notatek i drugiego umożliwiającego dodawanie i edycję notatek. Nasze informacje będziemy przechowywać z bazie SQLite. Dodawanie notatek będzie wywoływane poprzez przycisk w wysuwanym menu, a edycja i usuwanie poprzez przyciski w menu kontekstowym wywoływanym przy naciśnięciu danej notatki.  </p>
<h4>Tworzenie nowego projektu</h4>
<p>1. Włączamy Eclipse.</p>
<p>2. Wchodzimy w File > New > Android Project.</p>
<p>3. Nadajemy nazwę projektowi i klikamy Next.</p>
<p>4. Wybieramy interesującą nas wersję API i klikamy Next.</p>
<p><a href="http://blog.atena.pl/wp-content/uploads/2011/12/projekt1.jpg"><img src="http://blog.atena.pl/wp-content/uploads/2011/12/projekt1.jpg" alt="" title="projekt1" width="499" height="557" class="aligncenter size-full wp-image-2125" /></a><br />
5. Podajemy nazwę naszej paczki i klikamy Finish.</p>
<p>6. Eclipse wygenerował nam nasz projekt, w którym znajdują się między innymi:</p>
<p><a href="http://blog.atena.pl/wp-content/uploads/2011/12/projekt2.jpg"><img src="http://blog.atena.pl/wp-content/uploads/2011/12/projekt2.jpg" alt="" title="projekt2" width="200" height="360" class="aligncenter size-full wp-image-2128" /></a></p>
<ul>
<li>Folder src zawierający naszą paczkę oraz pierwszą klasę, do której powrócimy podczas pisania naszej pierwszej aplikacji.</li>
<li>Folder gen zawierający automatycznie wygenerowany plik R.java, którego nie należy modyfikować ręcznie. Klasa ta łączy zasoby graficzne z kodem Javy.</li>
<li>Folder bin, w którym będą się znajdować stworzone przez nas aplikacje oraz klasy po skompilowaniu.</li>
<li>Folder res zawierający nasze zasoby m. in. podfolder layout, w którym możemy w postaci plików xml zdefiniować wygląd interfejsów naszej aplikacji. Oczywiście można dodawać elementy w kodzie aplikacji analogicznie jak przy użyciu biblioteki Swing, jednak skorzystanie z plików xml jest o wiele wygodniejszą metodą. Dodatkowo Eclipse pozwala na automatyczne budowanie layoutów w postaci  plików xml dzięki prostemu edytorowi graficznemu.</li>
<li>Plik AndroidManifest.xml jest to główny plik konfiguracyjny Androida zawierający m. in. nazwę paczki, minimalną wersję API, zezwolenia na dostęp do zasobów sprzętowych, zdefiniowane klasy Activity, Serwisy</li>
</ul>
<h4>Elementy aplikacji</h4>
<p>1. Konfiguracja wyglądu</p>
<p>1.1. Konfiguracja poprzez xml</p>
<p>W Eclipsie w panelu Package Explorer klikamy prawym przyciskiem myszy na folder res/layout. Z menu wybieramy New -> Android XML File. Wprowadzamy nazwę nowego pliku – w naszym przypadku będzie to addnote. W tym miejscu możemy dodać elementy widoku, ale zrobimy to później, a więc klikamy Finish. Klikamy dwa razy na  nowo powstały plik, przez co otwieramy graficzny interfejs pozwalający na dodawanie elementów do widoku.</p>
<p><a href="http://blog.atena.pl/wp-content/uploads/2011/12/artykul1.jpg"><img src="http://blog.atena.pl/wp-content/uploads/2011/12/artykul1.jpg" alt="" title="artykul1" width="870" height="660" class="aligncenter size-full wp-image-2141" /></a><br />
Z panelu Form Widgets wybieramy Medium text i przeciągamy go na nasz ekran. Jego zawartość oraz id możemy ustalić, przechodząc do widoku xml (zakładka u dołu panelu). Analogicznie postępujemy z kolejnymi elementami. W edytorze graficznym możemy w zależności od wybranego layout’u (standardowo jest to LinearLayout) pozycjonować oraz zmieniać wielkość dodanych przez nas elementów. Po dodaniu wszystkich elementów wygenerowany plik xml powinien wyglądać tak:</p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br /></div></td><td><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;utf-8&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;LinearLayout</span> <span style="color: #000066;">xmlns:android</span>=<span style="color: #ff0000;">&quot;http://schemas.android.com/apk/res/android&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp;<span style="color: #000066;">android:layout_width</span>=<span style="color: #ff0000;">&quot;fill_parent&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp;<span style="color: #000066;">android:layout_height</span>=<span style="color: #ff0000;">&quot;fill_parent&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp;<span style="color: #000066;">android:orientation</span>=<span style="color: #ff0000;">&quot;vertical&quot;</span> <span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;TextView</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">android:id</span>=<span style="color: #ff0000;">&quot;@+id/textView1&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">android:layout_width</span>=<span style="color: #ff0000;">&quot;wrap_content&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">android:layout_height</span>=<span style="color: #ff0000;">&quot;wrap_content&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">android:text</span>=<span style="color: #ff0000;">&quot;Title: &quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">android:textAppearance</span>=<span style="color: #ff0000;">&quot;?android:attr/textAppearanceMedium&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;EditText</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">android:id</span>=<span style="color: #ff0000;">&quot;@+id/editText1&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">android:layout_width</span>=<span style="color: #ff0000;">&quot;fill_parent&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">android:layout_height</span>=<span style="color: #ff0000;">&quot;wrap_content&quot;</span> <span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;requestFocus</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/EditText<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;TextView</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">android:id</span>=<span style="color: #ff0000;">&quot;@+id/textView2&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">android:layout_width</span>=<span style="color: #ff0000;">&quot;wrap_content&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">android:layout_height</span>=<span style="color: #ff0000;">&quot;wrap_content&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">android:text</span>=<span style="color: #ff0000;">&quot;Text: &quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">android:textAppearance</span>=<span style="color: #ff0000;">&quot;?android:attr/textAppearanceMedium&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
<br />
<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;EditText</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">android:id</span>=<span style="color: #ff0000;">&quot;@+id/editText2&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">android:layout_width</span>=<span style="color: #ff0000;">&quot;fill_parent&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">android:layout_height</span>=<span style="color: #ff0000;">&quot;wrap_content&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">android:layout_weight</span>=<span style="color: #ff0000;">&quot;0.88&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">android:inputType</span>=<span style="color: #ff0000;">&quot;textMultiLine&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
<br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/LinearLayout<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></td></tr></tbody></table></div>
<p>Warto w tym miejscu podejrzeć plik R.java. W tym pliku wygenerował nam się fragment kodu przypisujący id naszych elementów pewne stałe.</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000066; font-weight: bold;">int</span> editText1<span style="color: #339933;">=</span>0x7f050001<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000066; font-weight: bold;">int</span> editText2<span style="color: #339933;">=</span>0x7f050003<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000066; font-weight: bold;">int</span> textView1<span style="color: #339933;">=</span>0x7f050000<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000066; font-weight: bold;">int</span> textView2<span style="color: #339933;">=</span>0x7f050002<span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>Jak już wspomniałem wcześniej, nie należy samodzielnie modyfikować tego pliku. Wartości tych stałych nie mają dla nas większego znaczenia. Te wpisy demonstrują, w jaki sposób android łączy zasoby graficzne z kodem Javy.</p>
<p>1.2. Konfiguracja z poziomu javy</p>
<p>W przypadku widoku listy najprostszym sposobem jest zrobienie tego z poziomu javy. Zmieniamy klasę, z której dziedziczy klasa AtenaNotepadActivity z</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> AtenaNotepadActivity <span style="color: #000000; font-weight: bold;">extends</span> Activity</div></td></tr></tbody></table></div>
<p>na</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> AtenaNotepadActivity <span style="color: #000000; font-weight: bold;">extends</span> ListActivity</div></td></tr></tbody></table></div>
<p>Teraz wystarczy ustawić adapter wskazujący, co ma wyświetlać nasza lista. Robimy to poprzez:</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">setListAdapter</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> ArrayAdapter<span style="color: #339933;">&lt;</span>String<span style="color: #339933;">&gt;</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">this</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; android.<span style="color: #006633;">R</span>.<span style="color: #006633;">layout</span>.<span style="color: #006633;">simple_list_item_1</span>,results<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>gdzie results jest to ArrayList<String> danych, które chcemy wyświetlić, a android.R.layout.simple_list_item_1 jest to stała określająca wygląd naszej listy.</p>
<p>2. Definiowanie napisów</p>
<p>Aby zdefiniować napisy, które wykorzystamy później w celu wyświetlenia ich na przyciskach naszych menu, wchodzimy w folder res naszego projektu. Następnie wybieramy katalog values i klikamy dwukrotnie na plik strings.xml. Klikamy Add, w kolejnym okienku wybieramy opcje String i klikamy OK. Następnie możemy nadać nazwę oraz wartość naszego stringa. Aby odwołać się do utworzonego napisu w kodzie wystarczy R.string.nazwa.</p>
<p>3. Stworzenie bazy danych oraz tablicy składającej się z 2 kolumn „Title” i „Text” .</p>
<ul>
<li>Definiujemy nazwę bazy danych.</li>
</ul>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">final</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> DB_NAME <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;AtenaNotepad&quot;</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">private</span> SQLiteDatabase baza <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<ul>
<li>Otwieramy (jeżeli istnieje) lub tworzymy bazę danych oraz tablicę Notepad poprzez metodę  execSQL. Poniższy fragment kodu wstawiamy do metody onCreate, która zostaje wywołana w momencie startu naszej aplikacji.</li>
</ul>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span><br />
baza <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">openOrCreateDatabase</span><span style="color: #009900;">&#40;</span>DB_NAME, MODE_PRIVATE, <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
baza.<span style="color: #006633;">execSQL</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;CREATE TABLE IF NOT EXISTS Notepad (Title VARCHAR UNIQUE, Text VARCHAR)&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
<span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">catch</span> <span style="color: #009900;">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Asqlexception+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">SQLException</span></a> e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; e.<span style="color: #006633;">printStackTrace</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<ul>
<li>Przykładowe zapytanie do bazy danych.</li>
</ul>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Acursor+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Cursor</span></a> cursor <span style="color: #339933;">=</span> baza.<span style="color: #006633;">rawQuery</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;SELECT Title FROM Notepad&quot;</span>, <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>4. Wywołanie okna wprowadzania i edycji notatki.</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Intent intent <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Intent<span style="color: #009900;">&#40;</span>getApplicationContext<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>, AddNote.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
startActivityForResult<span style="color: #009900;">&#40;</span>intent, REQUEST_CODE<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>5. Przekazywanie parametrów pomiędzy widokami.</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">intent <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Intent<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; intent.<span style="color: #006633;">putExtra</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Title&quot;</span>, title.<span style="color: #006633;">getText</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; intent.<span style="color: #006633;">putExtra</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Text&quot;</span>, text.<span style="color: #006633;">getText</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; AddNote.<span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">setResult</span><span style="color: #009900;">&#40;</span>RESULT_CODE, intent<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br />
AddNote.<span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">finish</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>6. Tworzenie oraz obsługa wysuwanego menu.</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">@Override<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">boolean</span> onCreateOptionsMenu<span style="color: #009900;">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Amenu+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Menu</span></a> menu<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">super</span>.<span style="color: #006633;">onCreateOptionsMenu</span><span style="color: #009900;">&#40;</span>menu<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; menu.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span>, ADD_ID, <span style="color: #cc66cc;">0</span>, R.<span style="color: #006633;">string</span>.<span style="color: #006633;">menu_add</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000066; font-weight: bold;">true</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
@Override<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">boolean</span> onMenuItemSelected<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> featureId, <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Amenuitem+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">MenuItem</span></a> item<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">switch</span><span style="color: #009900;">&#40;</span>item.<span style="color: #006633;">getItemId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">case</span> ADD_ID<span style="color: #339933;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; addNote<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000066; font-weight: bold;">true</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000000; font-weight: bold;">super</span>.<span style="color: #006633;">onMenuItemSelected</span><span style="color: #009900;">&#40;</span>featureId, item<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>7. Naciskając Run, tworzymy plik apk jednocześnie odpalając go na emulatorze (jeżeli stworzyliśmy AVD) lub na urządzeniu.</p>
<p>Cały projekt można pobrać z: <a href='http://blog.atena.pl/wp-content/uploads/2011/12/AtenaNotepad.zip'>AtenaNotepad</a><br />
<a href="http://blog.atena.pl/wp-content/uploads/2011/12/notepad2.jpg"><img src="http://blog.atena.pl/wp-content/uploads/2011/12/notepad2-187x300.jpg" alt="" title="notepad2" width="187" height="300" class="alignleft size-medium wp-image-2166" /></a><a href="http://blog.atena.pl/wp-content/uploads/2011/12/notepad1.jpg"><img src="http://blog.atena.pl/wp-content/uploads/2011/12/notepad1-187x300.jpg" alt="" title="notepad1" width="187" height="300" class="alignleft size-medium wp-image-2165" /></a><a href="http://blog.atena.pl/wp-content/uploads/2011/12/notepad3.jpg"><img src="http://blog.atena.pl/wp-content/uploads/2011/12/notepad3-188x300.jpg" alt="" title="notepad3" width="188" height="300" class="alignleft size-medium wp-image-2167" /></a></p>
<h3>Podsumowanie</h3>
<p>Programowanie na platformę Android jest bardzo szerokim tematem m.in. ze względu na ilość dostępnych peryferii oraz bibliotek. Ten artykuł jest jedynie wstępem, w którym skupiłem się na przygotowaniu środowiska oraz stworzeniem pierwszego projektu. Przedstawiona aplikacja pokazuje wykorzystanie takich elementów, jak menu kontekstowe, widok listy, komunikacja pomiędzy widokami, wysuwane menu, obsługa bazy danych oraz tworzenie widoków poprzez pliki xml. Jeżeli ktoś chciałby zapoznać się z innymi możliwościami, zachęcam do przeanalizowania przykładów zawartych w folderze samples z katalogu, w którym zainstalowaliśmy SDK.  Można je zaimportować do Eclipse poprzez wybranie opcji File->Import->Existing Project into Workspace. Działanie aplikacji demonstrujących możliwości poszczególnych API można również zaobserwować w emulatorze w folderze API Demos.</p>
<h4>Materiały</h4>
<ul>
<li>Android SDK &#8211; <a href="http://developer.android.com/sdk/index.html">http://developer.android.com/sdk/index.html</a></li>
<li>Andriod reference &#8211; <a href="http://developer.android.com/reference/packages.html">http://developer.android.com/reference/packages.html</a></li>
<li>Android guide &#8211; <a href="http://developer.android.com/guide/index.html">http://developer.android.com/guide/index.html</a></li>
<li>Przykłady, tutoriale, artykuły &#8211; <a href="http://developer.android.com/resources/index.html">http://developer.android.com/resources/index.html</a></li>
<li>Raport firmy Canalys &#8211; <a href="http://www.canalys.com/newsroom/android-takes-almost-50-share-worldwide-smart-phone-market">http://www.canalys.com/newsroom/android-takes-almost-50-share-worldwide-smart-phone-market</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.atena.pl/wstep-do-androida/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Aplikacje mobilne w HTML5, Phonegap, jQueryMobile</title>
		<link>http://blog.atena.pl/aplikacje-mobilne-w-html5-phonegap-jquerymobile</link>
		<comments>http://blog.atena.pl/aplikacje-mobilne-w-html5-phonegap-jquerymobile#comments</comments>
		<pubDate>Tue, 15 Nov 2011 09:12:08 +0000</pubDate>
		<dc:creator>Zbigniew Wysocki</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Bez kategorii]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[phonegap]]></category>

		<guid isPermaLink="false">http://blog.atena.pl/?p=1855</guid>
		<description><![CDATA[Poszukiwanie sposobu na łatwe i szybkie wytwarzanie aplikacji mobilnych to nieustająca zabawa. Mnogość technologii, platform oraz frameworków wspomagających ten proces jest spora. Tym razem postanowiłem wziąć na tapetę HTML5. Pisanie w technologii JavaScript, HTML5, CSS3 wydaje się prostsze niż Objective-C, a już na pewno łatwiej tu o programistę z doświadczeniem. Czy ta technologia jest faktycznie [...]]]></description>
			<content:encoded><![CDATA[<p>Poszukiwanie sposobu na łatwe i szybkie wytwarzanie aplikacji mobilnych to nieustająca zabawa. Mnogość technologii, platform oraz frameworków wspomagających ten proces jest spora. Tym razem postanowiłem wziąć na tapetę HTML5. Pisanie w technologii JavaScript, HTML5, CSS3 wydaje się prostsze niż Objective-C, a już na pewno łatwiej tu o programistę z doświadczeniem. Czy ta technologia jest faktycznie użyteczna w świecie smartfonów i tabletów? Postaram się odpowiedzieć na to pytanie oraz opisać pomocnicze narzędzia.<span id="more-1855"></span></p>
<h3>HTML5</h3>
<p>HTML5, jak dobrze wiadomo, jest następną wersją popularnego języka hyper text markup language (HTML). Pomyślano ją tak, aby ułatwiała pisanie nie tylko stron internetowych, ale również aplikacji pracujących nawet w trybie offline. Doszła możliwość rysowania nowych obiektów 2D canvas, obsługa plików wideo i audio oraz wiele innych. Nie będę zagłębiał się w wątek nowości HTML5, dla ciekawych poniżej znajduje się stosowny link do źródeł.<br />
Bardziej interesuje mnie, jak zrobić w HTML5 aplikację. Aby działała poprawnie na urządzeniu mobilnym, wymagana jest przeglądarka wspierająca tę technologię. Obecnie całkiem dobrze radzi sobie z tym Opera, która jednak nie jest domyślną przeglądarką w smartfonach. Spośród dostarczonych przez daną platformę, wsparcie dla HTML5 wygląda już nieco gorzej w przypadku Androida, a sporo gorzej w przypadku Blackberry czy Windows Phone. Zapewne z czasem sytuacja ta będzie się poprawiać. Jeśli ktoś chciałby sprawdzić, na ile dobrze wspiera HTML5 jego własna przeglądarka, polecam ten <a href="http://wapsbttest2.momac.net/html5/test/">test</a>. Mój Galaxy S2 i9100 z Androidem 2.3.3 uzyskał wynik 128 na 160 punktów. Skoro przeglądarki różnią się znacząco od siebie w implementacji specyfikacji HTML5, łatwo sobie wyobrazić, jakie problemy spotkają nas przy kodowaniu. Odmienne zachowanie aplikacji w zależności od przeglądarki jest kłopotliwe w testowaniu i programowaniu, a więc kosztowne. A może da się jakoś raz napisać aplikację w HTML5, aby tak samo działała na różnych telefonach?</p>
<h3>Phonegap i jQuery</h3>
<p>Phongap &#8211; tak właśnie nazywa się framework ułatwiający nam okiełznanie HTML5 i skłonienie tej technologii do poprawnego działania na różnych telefonach. Pozwala na pisanie jednej aplikacji i wydanie jej w postaci oddzielnych paczek dedykowanych dla odpowiedniej platformy. Dostęp do API urządzenia odbywa się przez funkcje javascriptowe dostępne w pliku phonegap-1.1.0.js. Instrukcja jak napisać &#8222;Hello World!&#8221; i skonfigurować środowisko znajduje się tutaj <a href="http://phonegap.com/start#android">http://phonegap.com/start#android</a>. Podałem linka do Androida, gdyż w nim postanowiłem napisać prostą aplikację, aby zobaczyć, jak to wszystko wygląda w tak zwanym praniu. Aplikacja miała za zadanie automatycznie logować nas do sieci wewnętrznej wifi, gdy włączy się połączenie. Dodatkowo wyświetlać obecny status połączenia z siecią i na osobnej stronie umożliwić konfigurację, która byłaby na stałe zapamiętana w telefonie. Pisanie w samym HTML i JS czegoś więcej niż &#8222;Hello World!&#8221; jest dość żmudne. Zwłaszcza jeśli chcemy zapewnić estetyczny wygląd formularzy, układ strony itd. Ponieważ dobry programista to &#8222;leniwy&#8221; programista, postanowiłem poszukać gotowych bibliotek wspomagających pracę z JS na mobilne urządzenia. Skorzystałem z jQueryMobile, gdyż  jQuery jest popularny i zawiera wiele przydatnych funkcji JS. Aby dodać go do naszego projektu, należy ściągnąć pliki z <a href="http://jquerymobile.com/download/">http://jquerymobile.com/download/</a> i zapisać w katalogu assets/www. Skoro mamy już wszystko, co nam potrzebne, zaczynamy!</p>
<h3>Trochę kodu</h3>
<p>Tworzymy stronkę index.html i w sekcji head dołączamy potrzebne pliki. W tym momencie najlepiej jest utworzyć plik lib.js na potrzeby własnych funkcji javascriptowych.</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&lt;script src=&quot;phonegap-1.1.0.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt; &lt;script src=&quot;jquery-1.6.4.min.js&quot;&gt;&lt;/script&gt;<br />
&lt;script src=&quot;jquery.mobile-1.0rc2.js&quot;&gt;&lt;/script&gt; &lt;script src=&quot;lib.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;</div></td></tr></tbody></table></div>
<p>Potrzebny będzie nam jeszcze dostęp do API Androida, aby wykryć połączenie z wifi oraz zapisanie lokalnie na telefonie ustawień aplikacji. Na zmiany połączenia z siecią możemy reagować poprzez funkcję nasłuchiwania odpowiednich zdarzeń.</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">document.addEventListener(&quot;offline&quot;, pgOffOnline, false);<br />
document.addEventListener(&quot;online&quot;, pgOnOnline, false);</div></td></tr></tbody></table></div>
<p>pgOffOnline i pgOnOnline to nazwy moich funkcji wywoływanych w momencie wystąpienia zdarzenia. Zapisanie danych w telefonie możliwe jest dzięki</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">localStorage.setItem(klucz, wartość);</div></td></tr></tbody></table></div>
<p>Pozostało jeszcze napisać formularze w HTML i połączyć wszystko w jedną całość. Kod index.html i lib.js poniżej na stronie, a cała aplikacja, którą można zaimportować do Eclipse na dole w dziale linki.</p>
<h5>index.html</h5>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&lt;script src=&quot;phonegap-1.1.0.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt; &lt;script src=&quot;jquery-1.6.4.min.js&quot;&gt;&lt;/script&gt;<br />
&lt;script src=&quot;jquery.mobile-1.0rc2.js&quot;&gt;&lt;/script&gt; &lt;script src=&quot;lib.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;<br />
<br />
&lt;script type=&quot;text/javascript&quot;&gt;<br />
&nbsp; &nbsp; document.addEventListener(&quot;deviceready&quot;, onDeviceReady, false);<br />
&nbsp; &nbsp; function onDeviceReady() {<br />
&nbsp; &nbsp; &nbsp; &nbsp; document.addEventListener(&quot;offline&quot;, pgOffOnline, false);<br />
&nbsp; &nbsp; &nbsp; &nbsp; document.addEventListener(&quot;online&quot;, pgOnOnline, false);<br />
&nbsp; &nbsp; &nbsp; &nbsp; checkConnection();<br />
&nbsp; &nbsp; }<br />
&lt;/script&gt;<br />
&lt;div id=&quot;home&quot;&gt;<br />
&lt;div&gt;<br />
&lt;h1&gt;Atena Wifi Connector&lt;/h1&gt;<br />
&lt;/div&gt;<br />
&lt;div&gt;<br />
<br />
Twoje obecne polaczenie to :<br />
<br />
&lt;a href=&quot;#settings&quot;&gt;Ustawienia&lt;/a&gt;<br />
<br />
&lt;/div&gt;<br />
&lt;/div&gt;<br />
&lt;div id=&quot;settings&quot;&gt;<br />
&lt;div&gt;<br />
&lt;h1&gt;Ustawienia&lt;/h1&gt;<br />
&lt;div class=&quot;ui-body ui-body-b&quot;&gt;<br />
&lt;fieldset&gt; &lt;legend&gt;Zaloguj autmatycznie:&lt;/legend&gt;&lt;input id=&quot;start&quot; class=&quot;custom&quot; name=&quot;start&quot; type=&quot;checkbox&quot; /&gt; &lt;label for=&quot;start&quot;&gt;Tak&lt;/label&gt;&lt;/fieldset&gt;<br />
&lt;div&gt;&lt;label for=&quot;login&quot;&gt;Login:&lt;/label&gt; &lt;input id=&quot;login&quot; name=&quot;login&quot; type=&quot;text&quot; /&gt;<br />
&lt;label for=&quot;pass&quot;&gt;Haslo:&lt;/label&gt; &lt;input id=&quot;pass&quot; name=&quot;pass&quot; type=&quot;password&quot; /&gt;&lt;/div&gt;<br />
&lt;button onclick=&quot;saveSettings();&quot;&gt;Zapisz&lt;/button&gt;&lt;button onclick=&quot;cancelSettings();&quot;&gt;Anuluj&lt;/button&gt;<br />
<br />
&lt;/div&gt;<br />
&lt;/div&gt;<br />
&lt;script type=&quot;text/javascript&quot;&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; $('#login').attr(&quot;value&quot;,getProperty(LOGIN_KEY,LOGIN_DEFAULT));<br />
&nbsp; &nbsp; &nbsp; &nbsp; $('#pass').attr(&quot;value&quot;,getProperty(PASSWORD_KEY,PASSWORD_DEFAULT));<br />
&nbsp; &nbsp; &nbsp; &nbsp; if(getProperty(STARTUPAPP_KEY,STARTUPAPP_DEFAULT)){<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $('#start').attr(&quot;checked&quot;,&quot;checked&quot;);<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
<br />
&lt;/script&gt;<br />
<br />
&lt;/div&gt;</div></td></tr></tbody></table></div>
<h5>lib.js</h5>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br />59<br />60<br />61<br />62<br />63<br />64<br />65<br />66<br />67<br />68<br />69<br />70<br />71<br />72<br />73<br />74<br />75<br />76<br />77<br />78<br />79<br />80<br />81<br />82<br />83<br />84<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">const PASSWORD_KEY = &quot;password&quot;;<br />
const LOGIN_KEY = &quot;login&quot;;<br />
const STARTUPAPP_KEY = &quot;STARTUPAPP&quot;;<br />
<br />
const PASSWORD_DEFAULT = &quot;xx&quot;;<br />
const LOGIN_DEFAULT = &quot;xxx&quot;;<br />
const STARTUPAPP_DEFAULT = true;<br />
<br />
function connect2Wifi(){<br />
var url = &quot;https://1.1.1.1/login.html&quot;;<br />
var login = getProperty(LOGIN_KEY,LOGIN_DEFAULT);<br />
var pass &nbsp;= getProperty(PASSWORD_KEY,PASSWORD_DEFAULT);<br />
$.ajax({<br />
type: 'post',<br />
url: url,<br />
data: {'buttonClicked':'4','err_flag':'0','err_msg':'0','info_flag':'0','info_msg':'','username':login,'password':pass},<br />
success: function(data){<br />
},<br />
});<br />
<br />
}<br />
<br />
function checkConnection() {<br />
<br />
var networkState = navigator.network.connection.type;<br />
<br />
var states = {};<br />
states[Connection.UNKNOWN] = 'Unknown connection';<br />
states[Connection.ETHERNET] = 'Ethernet connection';<br />
states[Connection.WIFI] = 'WiFi connection';<br />
states[Connection.CELL_2G] = 'Cell 2G connection';<br />
states[Connection.CELL_3G] = 'Cell 3G connection';<br />
states[Connection.CELL_4G] = 'Cell 4G connection';<br />
states[Connection.NONE] = 'No network connection';<br />
<br />
setConnectionStatus(states[networkState]);<br />
<br />
if(getProperty(STARTUPAPP_KEY,STARTUPAPP_DEFAULT)){<br />
if (networkState == Connection.WIFI) {<br />
connect2Wifi();<br />
}<br />
}<br />
<br />
}<br />
<br />
function saveSettings(){<br />
setProperty(LOGIN_KEY,$('#login').attr(&quot;value&quot;));<br />
setProperty(PASSWORD_KEY,$('#pass').attr(&quot;value&quot;));<br />
setProperty(STARTUPAPP_KEY,$('#start').attr(&quot;value&quot;));<br />
$.mobile.changePage( &quot;#home&quot;, { transition: &quot;slideup&quot;} );<br />
}<br />
<br />
function cancelSettings(){<br />
$.mobile.changePage( &quot;#home&quot;, { transition: &quot;slideup&quot;} );<br />
}<br />
<br />
function setConnectionStatus(status){<br />
document.getElementById('status').innerHTML = status<br />
<br />
}<br />
function pgOnOnline() {<br />
checkConnection();<br />
}<br />
function pgOffOnline() {<br />
checkConnection();<br />
}<br />
<br />
function getProperty(name,defaultvalue){<br />
var val =localStorage.getItem(name);<br />
if(jQuery.isEmptyObject(val)){<br />
return defaultvalue;<br />
}else{<br />
return val;<br />
}<br />
}<br />
function setProperty(name,value){<br />
try {<br />
localStorage.setItem(name, value);<br />
} catch (e) {<br />
if (e == QUOTA_EXCEEDED_ERR) {<br />
alert('Brak miejsca na zapisanie danych.');<br />
}<br />
}<br />
}</div></td></tr></tbody></table></div>
<h3>Podsumowanie</h3>
<p>Podsumowując, połączenie HTML5, Phonegapa z jQueryMobile wywołuje wrażenie jak najbardziej pozytywne. Nie było większych problemów czy błędów, które bym napotkał, mimo że jQuery jest jeszcze w wersji rc1. Dokumentacja do Phonegap jak i jQuery jest na bardzo dobrym poziomie &#8211; nic, tylko zacząć kodować. Zdecydowanie polecam to rozwiązanie, jeśli chcemy napisać prostą aplikację na różne telefony. Opanowanie HTML5 z JS jest znacznie szybsze, niż nauczenie się Javy dla Androida, Objective-C na iPhona itd. Ponadto możliwości, jakie udostępnia nam HTML5 pozwalają na stworzenie także rozbudowanych i zaawansowanych aplikacji.  Dodatkowo Phonegap dostarcza nam środowisko do kompilowania aplikacji na różne platformy. Tak więc wystarczy napisać sam plik index.html, wrzucić na serwer i pobrać naszą skompilowaną aplikację dla danej platformy <a href="https://build.phonegap.com/">https://build.phonegap.com/</a></p>
<h3>Linki</h3>
<ul>
<li><a href="http://en.wikipedia.org/wiki/HTML5">http://en.wikipedia.org/wiki/HTML5</a></li>
<li><a href="http://phonegap.com">http://phonegap.com</a></li>
<li><a href="http://docs.phonegap.com/en/1.1.0/index.html">http://docs.phonegap.com/en/1.1.0/index.html</a></li>
<li><a href="http://jquerymobile.com/">http://jquerymobile.com/</a></li>
<li><a href="http://blog.atena.pl/wp-content/uploads/2011/11/GapAPP.zip">http://blog.atena.pl/wp-content/uploads/2011/11/GapAPP.zip</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.atena.pl/aplikacje-mobilne-w-html5-phonegap-jquerymobile/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Różnorodność mobilnych systemów operacyjnych &#8211; ograniczenie czy szansa?</title>
		<link>http://blog.atena.pl/roznorodnosc-mobilnych-systemow-operacyjnych-ograniczenie-czy-szansa</link>
		<comments>http://blog.atena.pl/roznorodnosc-mobilnych-systemow-operacyjnych-ograniczenie-czy-szansa#comments</comments>
		<pubDate>Wed, 22 Jun 2011 08:22:45 +0000</pubDate>
		<dc:creator>Zbigniew Wysocki</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Bez kategorii]]></category>
		<category><![CDATA[InfoShare]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://blog.atena.pl/?p=1348</guid>
		<description><![CDATA[Rynek urządzeń mobilnych jest zdecydowanie jednym z najszybciej rozwijających się na świecie, a co za tym idzie &#8211; także zapotrzebowanie na aplikacje jest ogromne. A wraz ze wzrostem możliwości i dostępności tego rynku, również jego oczekiwania będą coraz większe. Mówiąc wprost, prędzej czy później firmy IT będą musiały rozpocząć prace nad tego typu aplikacjami, aby [...]]]></description>
			<content:encoded><![CDATA[<p>Rynek urządzeń mobilnych jest zdecydowanie jednym z najszybciej rozwijających się na świecie, a co za tym idzie &#8211; także zapotrzebowanie na aplikacje jest ogromne. A wraz ze wzrostem możliwości i dostępności tego rynku, również jego oczekiwania będą coraz większe. Mówiąc wprost, prędzej czy później firmy IT będą musiały rozpocząć prace nad tego typu aplikacjami, aby sprostać wymaganiom rynku. Jednak każdy, kto wytwarzał aplikacje mobilne lub zastanawiał się nad tym, zapewne zdaje sobie sprawę z trudności związanych z różnorodnością obecnych telefonów oraz tempem pojawiania się nowych modeli. Popularne od lat API Javy czy Symbiana także nie jest przyjazne dla programisty. Czy jednak tak jest ciągle? Co zmieniło się w ostatnich latach? Jak ten rynek będzie wyglądał za parę lat? Na jakie problemy można natrafić podczas prowadzenia projektu? <span id="more-1348"></span>Wybrałem się na wykład pod tytułem &#8222;Różnorodność mobilnych systemów operacyjnych &#8211; ograniczenie czy szansa&#8221; w ramach tegorocznej konferencji <a rel="nofollow" href="http://infoshare.pl/">InfoShare</a> z nadzieją, iż Łukasz Korzeniowski z firmy FancyFon S.A pomoże mi w znalezieniu odpowiedzi na te pytania.</p>
<h3><a name="Różnorodnośćmobilnychsystemówoperacyjnych-ograniczenieczyszansa-"></a></h3>
<h3><a name="Różnorodnośćmobilnychsystemówoperacyjnych-ograniczenieczyszansa-Opisprezentacji"></a>Opis prezentacji</h3>
<p>Podczas prezentacji Łukasz Korzeniowski skupił się na porównaniu czasu pisania aplikacji na różne platformy telefonów komórkowych oraz podsumowaniu co zaskoczyło twórców i z czym mieli największe problemy. Przedstawił także obecne trendy i przyszłe prognozy popularności telefonów. Nie zostały poruszone szczegółowe różnice platform w oferowanych możliwościach. Wszystkie wnioski, jakie zostały przekazane przez prowadzącego, pochodzą z realnego projektu Pakk wykonanego na zlecenie węgierskiego klienta Vodafone. Ważne jest też, że do każdego typu telefonu został przydzielony programista z doświadczeniem w pracy z daną platformą.</p>
<h3><a name="Różnorodnośćmobilnychsystemówoperacyjnych-ograniczenieczyszansa-Obecnedane"></a>Obecne dane</h3>
<p>Oto, jak przedstawia się procentowy udział platformy na rynku urządzeń mobilnych za pierwszy kwartał 2011 roku:</p>
<table>
<tbody>
<tr>
<th> Platforma</th>
<th> 2011 Market Share</th>
</tr>
<tr>
<td>Android</td>
<td>39.5%</td>
</tr>
<tr>
<td>BlackBerry</td>
<td>14.9%</td>
</tr>
<tr>
<td>iOS</td>
<td>15.7%</td>
</tr>
<tr>
<td>Symbian</td>
<td>20.9%</td>
</tr>
<tr>
<td>WindowsMobile</td>
<td>5.5%</td>
</tr>
<tr>
<td>Others</td>
<td>3.5%</td>
</tr>
</tbody>
</table>
<p>Według danych od Vodafhone wśród czołowych czterdziestu modeli telefonów występują:</p>
<ul>
<li>Java:    42%</li>
</ul>
<ul>
<li>Symbian: 26%</li>
</ul>
<ul>
<li>Android: 32%</li>
</ul>
<h3><a name="Różnorodnośćmobilnychsystemówoperacyjnych-ograniczenieczyszansa-Podsumowanieplatform"></a>Podsumowanie platform</h3>
<h4><a name="Różnorodnośćmobilnychsystemówoperacyjnych-ograniczenieczyszansa-java"></a>Java</h4>
<h5><a name="Różnorodnośćmobilnychsystemówoperacyjnych-ograniczenieczyszansa-Zalety"></a>Zalety</h5>
<ul>
<li>Stosunkowo krótki czas wytworzenia</li>
</ul>
<ul>
<li>Powszechny język programowania</li>
</ul>
<h5><a name="Różnorodnośćmobilnychsystemówoperacyjnych-ograniczenieczyszansa-Problemy:"></a>Problemy:</h5>
<ul>
<li>API nie działające zgodnie ze specyfikacją</li>
<li>rozmiar aplikacji</li>
<li>zróżnicowanie wielkości ekranu</li>
<li>zróżnicowanie możliwości przeglądarki</li>
<li>różna reprezentacja obiektów (np. kontakt)</li>
<li>wysoki koszt testów</li>
<li>problem z konfiguracją APN (Nokia) oraz uprawnień aplikacji &#8211; negatywny wpływ na wrażenia użytkownika!!!</li>
</ul>
<h4><a name="Różnorodnośćmobilnychsystemówoperacyjnych-ograniczenieczyszansa-Android"></a>Android</h4>
<h5><a name="Różnorodnośćmobilnychsystemówoperacyjnych-ograniczenieczyszansa-Zalety:"></a>Zalety:</h5>
<ul>
<li>wielozadaniowy system operacyjny &#8211; można więcej</li>
<li>duża swoboda aplikacji (szeroki dostęp do systemu)</li>
<li>popularny język programowania</li>
<li>szybkość tworzenia aplikacji</li>
<li>automatyczna dostępność aplikacji na tablety</li>
</ul>
<h5><a name="Różnorodnośćmobilnychsystemówoperacyjnych-ograniczenieczyszansa-"></a></h5>
<h5><a name="Różnorodnośćmobilnychsystemówoperacyjnych-ograniczenieczyszansa-Problemy:"></a>Problemy:</h5>
<ul>
<li>różnice w zachowaniu API na różnych modelach telefonów (raczej incydentalne)</li>
<li>pewne nienaruszalne założenia (np. sposób instalacji aplikacji) &#8211; ograniczenie możliwości</li>
<li>nie najlepsza dokumentacja</li>
</ul>
<h4><a name="Różnorodnośćmobilnychsystemówoperacyjnych-ograniczenieczyszansa-"></a></h4>
<h4><a name="Różnorodnośćmobilnychsystemówoperacyjnych-ograniczenieczyszansa-Symbian"></a>Symbian</h4>
<h5><a name="Różnorodnośćmobilnychsystemówoperacyjnych-ograniczenieczyszansa-Zalety:"></a>Zalety:</h5>
<ul>
<li>API pozwalające na dostęp do każdego elementu systemu</li>
<li>w nowych telefonach możliwość tworzenia aplikacji w Qt</li>
</ul>
<h5><a name="Różnorodnośćmobilnychsystemówoperacyjnych-ograniczenieczyszansa-Problemy:"></a>Problemy:</h5>
<ul>
<li>dużo wyższa pracochłonność  niż na innych platformach (bez użycia Qt)</li>
<li>archaiczny język i środowisko programistyczne</li>
<li>ukryte API</li>
<li>skomplikowany system podpisów</li>
<li>„sztuczki i kruczki&#8221; zarówno w systemie jak i w środowisku</li>
<li>zróżnicowanie między wersjami Symbiana</li>
<li>zróżnicowanie między urządzeniami</li>
</ul>
<h4><a name="Różnorodnośćmobilnychsystemówoperacyjnych-ograniczenieczyszansa-iPhone"></a>iPhone</h4>
<h5><a name="Różnorodnośćmobilnychsystemówoperacyjnych-ograniczenieczyszansa-Zalety:"></a>Zalety:</h5>
<ul>
<li>niewielka liczba urządzeń i wersji systemu</li>
<li>szybki development</li>
<li>„błyszczący&#8221; interfejs użytkownika</li>
<li>automatyczna dostępność aplikacji dla iPad</li>
</ul>
<h5><a name="Różnorodnośćmobilnychsystemówoperacyjnych-ograniczenieczyszansa-Wady:"></a>Wady:</h5>
<ul>
<li>nietypowy język programowania</li>
<li>konieczność posiadania sprzętu Apple</li>
<li>ograniczone API do dostępu do elementów systemu (np. skrzynka SMS)</li>
</ul>
<h3><a name="Różnorodnośćmobilnychsystemówoperacyjnych-ograniczenieczyszansa-"></a></h3>
<h3><a name="Różnorodnośćmobilnychsystemówoperacyjnych-ograniczenieczyszansa-Czasnapisaniaaplikacji"></a>Czas napisania aplikacji</h3>
<table>
<tbody>
<tr>
<th> Platforma</th>
<th> Czas</th>
</tr>
<tr>
<td>Java</td>
<td>półtora miesiąca</td>
</tr>
<tr>
<td>Symbian</td>
<td>ponad dwa i bez paru funkcjonalności</td>
</tr>
<tr>
<td>Android</td>
<td>miesiąc</td>
</tr>
<tr>
<td>iOS</td>
<td>trzy tygodnie</td>
</tr>
</tbody>
</table>
<h3><a name="Różnorodnośćmobilnychsystemówoperacyjnych-ograniczenieczyszansa-Wnioski"></a>Wnioski</h3>
<p>Ważne jest, aby podczas podpisywania umowy ograniczyć ilość telefonów docelowych na których zapewniamy poprawność naszej aplikacji. Mnogość modeli na rynku może znacząco wpłynąć na ryzyko przekroczenia budżetu i czasu naszego projektu. Należy testować aplikację na konkretnych telefonach, a nie tylko symulatorach, co również pozwoli skrócić czas wykrycia nieprawidłowości w działaniu aplikacji.<br />
W związku z popularyzacją smartphonów i osłabianiem się pozycji Symbiana na rynku, powinno się w miarę możliwości zrezygnować z supportu dla tej drugiej platformy. Po za tym sprawił on najwięcej problemów w projekcie i zajął najwięcej czasu. W przypadku iPhona powinno się zastanowić, na ile nasza aplikacja może być popularna na iStore, gdyż w przypadku napisania pierwszej koszty wejścia na ten rynek, są dość wysoki. Niestety niezbędny jest zakup: iPhone, iMac i licencji developerskiej pozwalającej na publikowanie aplikacji w iStore. Kolejną rzeczą, która wymaga zastanowienia , jest fakt, że w powyższym przedsięwzięciu nie używano praktycznie żadnego współdzielenia kodu między platformami. Rozwiązaniem tego problemu może być użycie jednego z frameworków:</p>
<ul>
<li>LWUIT -  <a rel="nofollow" href="http://lwuit.java.net/">http://lwuit.java.net/</a></li>
</ul>
<ul>
<li>OpenGL &#8211; <a rel="nofollow" href="http://www.khronos.org/opengles/">http://www.khronos.org/opengles/</a></li>
</ul>
<ul>
<li>PhoneGap (HTML5) &#8211; <a rel="nofollow" href="http://www.phonegap.com/home/">http://www.phonegap.com/home/</a></li>
</ul>
<p>Z powyższej listy do prostego interfejsu bez &#8222;fajerwerków&#8221; wybrałbym zdecydowanie PhoneGap. Dzięki użyciu HTML5 i javascript (powszechnie znanych technologi) jest on bardzo prosty w użyciu dla programisty. Zarazem zapewnia API pozwalające na tworzenie dowolnych aplikacji, można odwoływać się również do native API. Gdyby pojawiły się problemy, możemy liczyć na wsparcie rozwijającej się społeczności wokół tego projektu. Natomiast jeśli miałaby to być gra lub inna aplikacja wymagająca więcej od telefonu, warto rozważyć użycie OpenGL. Projekt ten jest wiodącym pod względem renderingu 3D. Więcej informacji o frameworkach można znaleźć na stronach podanych powyżej. Dodatkowe wiadomości można również zaczerpnąć z prezentacji Łukasz Korzeniowskiego dostępnej <a title="Prezentacja" rel="nofollow" href="http://www.slideshare.net/infosharepl/infoshare-2011-ukasz-korzeniowski-rnorodno-mobilnych-systemw-operacyjnych-ograniczenie-czy-szansa">tutaj</a>.</p>
<p>﻿</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.atena.pl/roznorodnosc-mobilnych-systemow-operacyjnych-ograniczenie-czy-szansa/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Czy Clojure da się lubić?</title>
		<link>http://blog.atena.pl/czy-clojure-da-sie-lubic</link>
		<comments>http://blog.atena.pl/czy-clojure-da-sie-lubic#comments</comments>
		<pubDate>Tue, 07 Jun 2011 11:37:37 +0000</pubDate>
		<dc:creator>Marcin Garniewski</dc:creator>
				<category><![CDATA[Bez kategorii]]></category>
		<category><![CDATA[InfoShare]]></category>

		<guid isPermaLink="false">http://blog.atena.pl/?p=1281</guid>
		<description><![CDATA[Po prezentacji Jacka Laskowskiego „Programowanie funkcjonalne funkcyjnie z Clojure praktycznie” na Infoshare 2011 wychodziliśmy z mieszanymi uczuciami. Powtarzał się pogląd o niedosycie informacji o tym nowym (dla mnie) języku. Korzystając z rozbudzonej ciekawości poznawczej, postanowiłem przyjrzeć się bliżej temu nawiasowemu językowi . Powtarzając za Wikipedią, głównymi cechami języka są: kompilowany do kodu bajtowego JVM (ang. [...]]]></description>
			<content:encoded><![CDATA[<p>Po prezentacji Jacka Laskowskiego „Programowanie funkcjonalne funkcyjnie z Clojure praktycznie” na Infoshare 2011 wychodziliśmy z mieszanymi  uczuciami. Powtarzał się pogląd o niedosycie informacji o tym nowym (dla mnie) języku. Korzystając z rozbudzonej ciekawości poznawczej,  postanowiłem przyjrzeć się bliżej temu nawiasowemu językowi <img title="wink" src="http://blog.atena.pl/wp-content/uploads/2011/06/wink.gif" alt="" width="20" height="20" />.<br />
<span id="more-1281"></span><br />
Powtarzając za Wikipedią, głównymi cechami języka są:</p>
<ul>
<li>kompilowany do kodu bajtowego JVM (ang. Java Virtual Machine, wirtualna maszyna Javy);</li>
<li>pełna kompatybilność z Javą: Clojure natywnie wywołuje metody Javy i na odwrót;</li>
<li>możliwość pracy w trybie interaktywnym REPL (ang. read-eval-print loop, pętla wczytaj-wykonaj-wypisz);</li>
<li>domknięcia z naciskiem na rekurencję;</li>
<li>bogata biblioteka stałych struktur danych;</li>
<li>silne wsparcie dla współbieżności w postaci transakcyjnej pamięci (ang. Software Transactional Memory &#8211; STM) i systemu agentów.</li>
</ul>
<h3><a name="Czyclojuredasięlubić?-Środowiskodeveloperskie"></a>Środowisko deweloperskie</h3>
<p>Zacznijmy od instalacji środowiska pracy. Istnieją odpowiednie pluginy do  większości popularnych IDE. Osobiście preferuję środowisko Eclipse, a więc  do niego zainstalowałem plugin <a rel="nofollow" href="http://code.google.com/p/counterclockwise/">Counterclock</a>.  Po instalacji pluginu mamy między innymi funkcjonalność podpowiadania  składni oraz okno REPL. REPL służy do dynamicznego programowania (o tym  za chwilę).<br />
Dodatkowo proponuję zainstalować środowisko <a rel="nofollow" href="https://github.com/technomancy/leiningen">Leiningen</a>.  Jest to środowisko uruchomieniowe Clojure — odpowiednik Maven w Javie.  Sposób instalacji opisany jest na stronie projektu. Sprowadza się do pobrania aplikacji, rozpakowania pliku w katalogu docelowym i dodania ścieżki do zmiennej systemowej PATH. Następnie wydajemy polecenie lein self-install i to już wszystko. Lein automatycznie ściąga wszystkie niezbędne pakiety. Mała uwaga dotycząca sytuacji, w której jesteśmy za proxy. W pliku lein.bat dodajemy wiersze:</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">set</span> <span style="color: #007800;">http_proxy</span>=http:<span style="color: #000000; font-weight: bold;">//</span>server_proxy:port<br />
<span style="color: #000000; font-weight: bold;">set</span> <span style="color: #007800;">https_proxy</span>=http:<span style="color: #000000; font-weight: bold;">//</span>server_proxy:port</div></td></tr></tbody></table></div>
<p>oraz modyfikujemy poniższy wiersz z:</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">set</span> <span style="color: #007800;">HTTP_CLIENT</span>=<span style="color: #c20cb9; font-weight: bold;">wget</span> <span style="color: #660033;">--no-check-certificate</span> <span style="color: #660033;">-O</span></div></td></tr></tbody></table></div>
<p>na:</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">set</span> <span style="color: #007800;">HTTP_CLIENT</span>=<span style="color: #c20cb9; font-weight: bold;">wget</span> <span style="color: #660033;">--proxy-user</span>=domena+<span style="color: #c20cb9; font-weight: bold;">login</span> <span style="color: #660033;">--proxy-password</span>=hasło <span style="color: #660033;">--no-check-certificate</span> <span style="color: #660033;">-O</span></div></td></tr></tbody></table></div>
<p>Rozwiązuje nam to problem proxy.</p>
<p>Po instalacji otrzymujemy dostęp do interfejsu shellowego, w którym dostępnych jest wiele przydatnych akcji:</p>
<p><a href="http://blog.atena.pl/wp-content/uploads/2011/06/lein.png"><img class="alignnone size-full wp-image-1297" title="lein" src="http://blog.atena.pl/wp-content/uploads/2011/06/lein.png" alt="" width="670" height="402" /></a></p>
<p>Dostępne są opcje rozwiązujące zależności (deps), kompilujące  (compile) oraz oczywiście budujące (jar). Jednak jedną z najciekawszych  funkcji jest możliwość rozszerzania funkcjonalności lein przez system  pluginów. Jeden z nich to plugin generujący strukturę plików dla  edytora Eclipse.<br />
A więc po kolei:</p>
<ul>
<li>tworzymy nowy projekt Clojure, wpisując polecenie lein new HelloWorldProject:<a href="http://blog.atena.pl/wp-content/uploads/2011/06/lein_new_project.png"><img class="alignnone size-full wp-image-1299" title="lein_new_project" src="http://blog.atena.pl/wp-content/uploads/2011/06/lein_new_project.png" alt="" width="411" height="39" /></a></li>
<li>edytujemy wygenerowany plik D:\temp\HelloWorldProject\project\core.clj:
<div class="codecolorer-container lisp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="lisp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span>defproject HelloWorldProject <span style="color: #ff0000;">&quot;1.0.0-SNAPSHOT&quot;</span><br />
<span style="color: #66cc66;">:</span><span style="color: #555;">description</span> <span style="color: #ff0000;">&quot;FIXME: write description&quot;</span><br />
<span style="color: #66cc66;">:</span><span style="color: #555;">dependencies</span> <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#91;</span>org<span style="color: #66cc66;">.</span>clojure/clojure <span style="color: #ff0000;">&quot;1.2.1&quot;</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#93;</span><br />
<span style="color: #66cc66;">:</span><span style="color: #555;">dev-dependencies</span> <span style="color: #66cc66;">&#91;</span><br />
<span style="color: #66cc66;">&#91;</span>lein-eclipse <span style="color: #ff0000;">&quot;1.0.0&quot;</span><span style="color: #66cc66;">|</span>lein-eclipse <span style="color: #ff0000;">&quot;1.0.0&quot;</span><span style="color: #66cc66;">&#93;</span><br />
<span style="color: #66cc66;">&#93;</span><br />
<span style="color: #66cc66;">&#41;</span></div></td></tr></tbody></table></div>
</li>
<li>wydajemy polecenie lein deps — zostanie automagiczne ściągnięty plugin</li>
<li>wydajemy polecenie lein eclipse — zostają wygenerowane pliki .classpath i .project:<a href="http://blog.atena.pl/wp-content/uploads/2011/06/lein_eclipse.png"><img class="alignnone size-full wp-image-1300" title="lein_eclipse" src="http://blog.atena.pl/wp-content/uploads/2011/06/lein_eclipse.png" alt="" width="392" height="54" /></a></li>
<li>w Eclipsie importujemy project: File-&gt;Import&#8230;I gotowe! Projekt jest przygotowany do edycji w Eclipsie. Możemy rozpocząć programowanie.<br />
<h3><a name="Czyclojuredasięlubić?-Składniajęzyka"></a>Składnia języka</h3>
</li>
</ul>
<p>Nie da się ukryć, że pierwszy kontakt ze składnią języka jest małym szokiem dla deweloperów Javy czy też C#. Za to programiści Lispa będą się czuć jak ryby w wodzie. Z tego właśnie języka pochodzi składnia  języka. Najprościej rzecz ujmując, szablon wygląda następująco:</p>
<div class="codecolorer-container lisp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="lisp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span>polecenie argument argument<span style="color: #66cc66;">&#41;</span></div></td></tr></tbody></table></div>
<p>Garść przykładów:</p>
<div class="codecolorer-container lisp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="lisp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span>println <span style="color: #ff0000;">&quot;Hello World&quot;</span><span style="color: #66cc66;">&#41;</span><span style="color: #808080; font-style: italic;">; — bez komentarza</span><br />
<span style="color: #66cc66;">&#40;</span>* <span style="color: #cc66cc;">3</span> <span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span><span style="color: #808080; font-style: italic;">; — wynik 9</span><br />
<span style="color: #66cc66;">&#40;</span>def zmienna <span style="color: #66cc66;">&#40;</span>+ <span style="color: #cc66cc;">2</span> <span style="color: #66cc66;">&#40;</span>* <span style="color: #cc66cc;">4</span> <span style="color: #cc66cc;">5</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> — definicja zmiennej</div></td></tr></tbody></table></div>
<p>Myślę, że nie ma sensu mnożyć tutaj przykładów, gdyż składnia  jest bardzo szeroka, a jeszcze szersza jest baza tutoriali, przykładów oraz blogów na sieci. Ciekawsze propozycje zamieściłem na końcu tego artykułu w sekcji „Zasoby w sieci”.</p>
<h3><a name="Czyclojuredasięlubić?-Uruchomienieskryptu"></a>Uruchomienie skryptu</h3>
<p>Jest kilka możliwości uruchomienia skryptu. Wszystkie opierają się na  rozwiązaniu REPL, czyli dynamicznym programowaniu. Daje ona np.  możliwość ingerowania w kod działającej (nawet produkcyjnie) aplikacji.  Potencjalnie możliwości są ogromne. Technicznie najprościej jest z  poziomu Eclipsa wybrać edytowany skrypt *.clj i wydać komendę &#8222;Run&#8221;.  Zostanie uruchomiona konsola REPL, kod skryptu zostanie załadowany i  uruchomiony. Od tego momentu mamy dostęp do konsoli, w której możemy  kontynuować kodowanie. Dynamiczność takiego programowania najłatwiej  przedstawić na aplikacji swingowej. Poniższy kod uruchomi aplikację okienkową, w której podczas działania zmienimy rozmiar okna. To naprawdę działa, proszę sprawdzić!</p>
<ul>
<li>import klasy JFrame
<div class="codecolorer-container lisp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="lisp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span>import <span style="color: #66cc66;">&#40;</span>javax<span style="color: #66cc66;">.</span>swing JFrame<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></div></td></tr></tbody></table></div>
</li>
<li>przypisanie do zmiennej f nowego obiektu klasy JFrame
<div class="codecolorer-container lisp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="lisp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span>def f <span style="color: #66cc66;">&#40;</span>JFrame<span style="color: #66cc66;">.</span> <span style="color: #ff0000;">&quot;Mój frame&quot;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #808080; font-style: italic;">;</span></div></td></tr></tbody></table></div>
</li>
<li>uruchomienie metod pack i show na obiekcie f:
<div class="codecolorer-container lisp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="lisp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span>doto f <span style="color: #66cc66;">.</span>pack <span style="color: #66cc66;">.</span>show<span style="color: #66cc66;">&#41;</span></div></td></tr></tbody></table></div>
<p>Efekt:</p>
<p><a href="http://blog.atena.pl/wp-content/uploads/2011/06/panel.png"><img class="alignnone size-full wp-image-1301" title="panel" src="http://blog.atena.pl/wp-content/uploads/2011/06/panel.png" alt="" width="148" height="49" /></a></p>
<p>A teraz uwaga! Program działa, a my w tym czasie zmienimy rozmiar okna:</p>
<div class="codecolorer-container lisp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="lisp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">.</span>setSize f <span style="color: #cc66cc;">100</span> <span style="color: #cc66cc;">100</span><span style="color: #66cc66;">&#41;</span></div></td></tr></tbody></table></div>
<p>I oto wynik:</p>
<p><a href="http://blog.atena.pl/wp-content/uploads/2011/06/duzy_panel.png"><img class="alignnone size-full wp-image-1302" title="duzy_panel" src="http://blog.atena.pl/wp-content/uploads/2011/06/duzy_panel.png" alt="" width="161" height="113" /></a></p>
<p>Mała rzecz, a cieszy <img src='http://blog.atena.pl/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<h3><a name="Czyclojuredasięlubić?-Podsumowanie"></a>Podsumowanie</h3>
</li>
</ul>
<p>Siłą języka Clojure jest kompilacja do bajtkodu Javy. Dzięki temu może być wykorzystany w istniejących systemach jako zewnętrzna biblioteka.  Inaczej mówiąc, Clojure nie oferuje nic więcej niż daje język Java. Za to udostępnia rozwiązania, których napisanie „ręcznie” w Javie zajęłoby wiele czasu i sprawiłoby niemały kłopot. Nie wspomniałem tu nic o wielowątkowości, która jest najsilniejszą stroną tego języka. Jest to podobno idealny język do pisania wielowątkowych aplikacji. Temat jest na tyle szeroki, że w celu jego omówienia można by napisać kolejny artykuł.</p>
<h3><a name="Czyclojuredasięlubić?-Zasobywsieci"></a>Zasoby w sieci</h3>
<p><a rel="nofollow" href="http://clojure.org/" target="_NEW">http://clojure.org/</a> — strona domowa<br />
<a rel="nofollow" href="http://clojure.pl/" target="_NEW">http://clojure.pl</a> — polska strona domowa<br />
<a rel="nofollow" href="http://java.ociweb.com/mark/clojure/article.html" target="_NEW">http://java.ociweb.com/mark/clojure/article.html</a> — świetny opis języka<br />
<a rel="nofollow" href="http://clojars.org/" target="_NEW">http://clojars.org/</a> — baza danych o bibliotekach w Clojure<br />
<a rel="nofollow" href="http://en.wikibooks.org/wiki/Clojure_Programming" target="_NEW">http://en.wikibooks.org/wiki/Clojure_Programming</a> — wikibook o Clojure<br />
<a rel="nofollow" href="http://www.learningclojure.com/" target="_NEW">http://www.learningclojure.com/</a><br />
<a rel="nofollow" href="http://pramode.net/clojure/" target="_NEW">http://pramode.net/clojure/</a><br />
<a rel="nofollow" href="http://www.clojureblog.pl/" target="_NEW">http://www.clojureblog.pl/</a><br />
<a rel="nofollow" href="http://loufranco.com/blog/files/category-20-days-of-clojure.html" target="_NEW">http://loufranco.com/blog/files/category-20-days-of-clojure.html</a> — 20 dni z Clojure</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.atena.pl/czy-clojure-da-sie-lubic/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>PRAKTYCZNY ENVERS</title>
		<link>http://blog.atena.pl/praktyczny-envers</link>
		<comments>http://blog.atena.pl/praktyczny-envers#comments</comments>
		<pubDate>Fri, 20 Aug 2010 07:00:10 +0000</pubDate>
		<dc:creator>Mateusz Mrozewski</dc:creator>
				<category><![CDATA[Bez kategorii]]></category>
		<category><![CDATA[JBoss]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JavaEE]]></category>

		<guid isPermaLink="false">http://blog.atena.pl/?p=1028</guid>
		<description><![CDATA[Envers jest dodatkiem do Hibernate’a pozwalającym na automatyczne zapisywanie historii zmian encji (audytu). Envers używa pojęcia rewizji – co oznacza, że każda zmiana dowolnej (audytowalnej) encji tworzy nową rewizję. Nowy rekord jest zapisany do tabeli, a na podstawie starego zostaje utworzona rewizja i zapisana do dodatkowej tabeli wraz z poprzednimi wartościami. Konfiguracja W ramach podstawowej [...]]]></description>
			<content:encoded><![CDATA[<p>Envers jest dodatkiem do Hibernate’a pozwalającym na automatyczne zapisywanie historii zmian encji (audytu). Envers używa pojęcia rewizji – co oznacza, że każda zmiana dowolnej (audytowalnej) encji tworzy nową rewizję. Nowy rekord jest zapisany do tabeli, a na podstawie starego zostaje utworzona rewizja i zapisana do dodatkowej tabeli wraz z poprzednimi wartościami.</p>
<p><span id="more-1028"></span></p>
<p><strong>Konfiguracja</strong></p>
<p>W ramach podstawowej niezbędnej konfiguracji należy dodać następujące właściwości do pliku persistence.xml lub hibernate.cfg.xml:</p>
<p style="text-align: left">&lt;property name=&#8221;hibernate.ejb.event.post-insert&#8221; value=&#8221;org.hibernate.ejb.event.EJB3PostInsertEventListener,org.hibernate.envers.event.AuditEventListener&#8221; /&gt;<br />
&lt;property name=&#8221;hibernate.ejb.event.post-update&#8221; value=&#8221;org.hibernate.ejb.event.EJB3PostUpdateEventListener,org.hibernate.envers.event.AuditEventListener&#8221; /&gt;<br />
&lt;property name=&#8221;hibernate.ejb.event.post-delete&#8221; value=&#8221;org.hibernate.ejb.event.EJB3PostDeleteEventListener,org.hibernate.envers.event.AuditEventListener&#8221; /&gt;<br />
&lt;property name=&#8221;hibernate.ejb.event.pre-collection-update&#8221; value=&#8221;org.hibernate.envers.event.AuditEventListener&#8221; /&gt;<br />
&lt;property name=&#8221;hibernate.ejb.event.pre-collection-remove&#8221; value=&#8221;org.hibernate.envers.event.AuditEventListener&#8221; /&gt;<br />
&lt;property name=&#8221;hibernate.ejb.event.post-collection-recreate&#8221; value=&#8221;org.hibernate.envers.event.AuditEventListener&#8221; /&gt;</p>
<p>Konfigurujemy w ten sposób listenery , które sprawdzają, czy zmieniły się jakieś audytowalne encje i czy należy zachować historię zmian tych encji.</p>
<p>Kolejnym krokiem jest już oznaczenie encji adnotacją @Audited. Jeśli adnotację umieścimy na poziomie klasy, wszystkie pola będą wersjonowane. Możemy również adnotację umieścić na poziomie pól klasy, aby wersjonować tylko wybrane.</p>
<p><strong>Przykład użycia</strong></p>
<p>Po umieszczeniu konfiguracji opisanej w kroku wyżej użycie Envers’a sprowadza się do dodania odpowiednich adnotacji.</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">@Entity<br />
@Audited<br />
public class Item {<br />
&nbsp; &nbsp; @Id<br />
&nbsp; &nbsp; private int id;<br />
<br />
&nbsp; &nbsp; private String name;<br />
<br />
&nbsp; &nbsp; public int getId() {<br />
&nbsp; &nbsp; &nbsp; &nbsp; return id;<br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; public void setId(int id) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; this.id = id;<br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; public String getName() {<br />
&nbsp; &nbsp; &nbsp; &nbsp; return name;<br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; public void setName(String name) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; this.name = name;<br />
&nbsp; &nbsp; }<br />
}</div></td></tr></tbody></table></div>
<p>I to tak naprawdę wszystko z rzeczy specyficznych dla Envers. Użycie encji w innym zakresie jest tak standardowe, jak w przypadku JPA lub Hibernate i w zasadzie niczym się od nich nie różni.</p>
<p><strong>Przechowywanie rewizji</strong></p>
<p>Dla każdej adnotowanej encji zostanie utworzona dodatkowa tabela przechowująca audyt. Dla naszej encji z podanego przykładu powstanie podstawowa tabela:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">CREATE TABLE ITEM<br />
(<br />
ID decimal(10) PRIMARY KEY NOT NULL,<br />
NAME varchar2(1020)<br />
);</div></td></tr></tbody></table></div>
<p>Oraz dodatkowa tabela do przechowywania audytu:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">CREATE TABLE ITEM_AUD<br />
(<br />
ID decimal(10) NOT NULL,<br />
REV decimal(10) NOT NULL,<br />
REVTYPE decimal(3),<br />
NAME varchar2(1020),<br />
CONSTRAINT SYS_C006187 PRIMARY KEY (ID,REV)<br />
);</div></td></tr></tbody></table></div>
<p>Dodatkowo doszły nam następujące pola:</p>
<ul>
<li>REV – oznacza numer rewizji;</li>
<li>REVTYPE – typ zmiany; możliwe wartości: 0 – wstawienie rekordu, 1 – modyfikacja rekordu, 2 – usunięcie rekordu.</li>
</ul>
<p>Najnowszy rekord w tabeli audytu będzie miał wartości o jedną wersję wstecz względem wartości w aktualnej tabeli. Jeśli natomiast rekord zostanie usunięty, nie znajdziemy go już w tabeli podstawowej, a najświeższy wpis będzie miał wartości ustawione na &lt;null&gt; i typ rewizji 2.</p>
<p>Numery rewizji są wspólne dla wszystkich encji. Oznacza to, że jeśli najpierw zmienimy encję A, otrzyma ona rewizję 1, dopiero potem zmienimy encję B, która otrzyma rewizję 2 (oczywiście obie będą posiadały oddzielne tabele audytu).</p>
<p><strong>Encja rewizji i zapis dodatkowych danych</strong></p>
<p>Oprócz zapisywania historii zmian danej encji możemy dla każdej rewizji zapisać dodatkowe informacje. Służy do tego encja rewizji – jest to standardowa encja z dodatkową adnotacją oraz dodatkowymi polami, jakie chcemy zapisać. Przykładowo:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">@Entity<br />
@RevisionEntity(MyRevisionListener.class)<br />
public class MyRevisionEntity extends DefaultRevisionEntity {<br />
&nbsp; &nbsp; private static final long serialVersionUID = -78999006241889798L;<br />
&nbsp; &nbsp; private String username;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; public String getUsername() {<br />
&nbsp; &nbsp; &nbsp; &nbsp; return username;<br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; public void setUsername(String username) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; this.username = username;<br />
&nbsp; &nbsp; }<br />
}</div></td></tr></tbody></table></div>
<p>Klasa DefaultRevisionEntity jest dostarczana wraz z Envers i deklaruje dwa podstawowe pola: id oraz timestamp. Do tego możemy dołożyć dodatkowe informacje, które chcemy zapisać, np. nazwę użytkownika. Wykonuje się to w listenerze wskazanym przez adnotację @RevisionEntity:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public class MyRevisionListener implements RevisionListener {<br />
<br />
&nbsp; &nbsp; public void newRevision(Object revisionEntity) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; MyRevisionEntity entity = (MyRevisionEntity) revisionEntity;<br />
&nbsp; &nbsp; &nbsp; &nbsp; entity.setUsername(&quot;NAZWA UŻYTKOWNIKA&quot;);<br />
&nbsp; &nbsp; }<br />
<br />
}</div></td></tr></tbody></table></div>
<p>Dla przykładowej encji rewizji zostanie utworzona następująca tabela:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">CREATE TABLE MYREVISIONENTITY<br />
(<br />
ID decimal(10) PRIMARY KEY NOT NULL,<br />
TIMESTAMP decimal(19) NOT NULL,<br />
USERNAME varchar2(1020)<br />
);</div></td></tr></tbody></table></div>
<p>Teraz przy utworzeniu nowej rewizji dowolnej audytowanej encji zostanie utworzony nowy wpis w tej tabeli z danymi uzupełnionymi według naszego listenera.</p>
<p><strong>Odpytywanie o rewizje</strong></p>
<p>Envers dostarcza klasy użytkowe pozwalające na odpytywanie o stan rewizji poszczególnych encji. Klasa AuditReaderFactory pozwala nam na pobranie instancji AuditReader w zależności od tego, czy operujemy na EntityManager z JPA czy też na Session z Hibernate.</p>
<p>AuditReader pozwala na budowanie zapytań implementujących interfejs AuditReader. Służy on do budowania zapytań w sposób podobny jak w przypadku Hibernate Criteria. Pytać możemy na dwa sposoby:</p>
<ul>
<li>o encję w konkretnej rewizji,</li>
<li>o rewizje, w których encje się zmieniły.</li>
</ul>
<p>Przykład zapytania o konkretną rewizję:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">int revision = 1;<br />
AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(Item.class, revision);<br />
<br />
List items = query.addOrder(AuditEntity.property(&quot;name&quot;).desc())<br />
&nbsp; &nbsp; .setFirstResult(4)<br />
&nbsp; &nbsp; .setMaxResults(2)<br />
&nbsp; &nbsp; .getResultList();</div></td></tr></tbody></table></div>
<p>Przykład zapytania o rewizje, w których zmieniała się encja:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">int revision = 1;<br />
Number revision = (Number) getAuditReader().createQuery()<br />
&nbsp; &nbsp; .forRevisionsOfEntity(Item.class, false, true)<br />
&nbsp; &nbsp; .setProjection(AuditEntity.revisionNumber().min())<br />
&nbsp; &nbsp; .add(AuditEntity.id().eq(entityId))<br />
&nbsp; &nbsp; .getSingleResult();</div></td></tr></tbody></table></div>
<p><strong>Wnioski</strong></p>
<p>Jak widać, Envers pozwala na łatwe wdrożenie historii zmian bez specjalnego nakładu pracy i praktycznie transparentnie dla istniejącego modelu. Warto też wspomnieć, że Envers stał się już częścią dystrybucji Hibernate’a (od wersji 3.5), co dodatkowo świadczy o jego użyteczności i jakości.</p>
<p><strong>Źródła</strong></p>
<p>Strona główna projektu: <a href="http://jboss.org/envers">http://jboss.org/envers</a><br />
Dokumentacja: <a href="http://docs.jboss.org/envers/docs/index.html">http://docs.jboss.org/envers/docs/index.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.atena.pl/praktyczny-envers/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SUMI jako metoda badania jakości oprogramowania</title>
		<link>http://blog.atena.pl/sumi-jako-metoda-badania-jakosci-oprogramowania</link>
		<comments>http://blog.atena.pl/sumi-jako-metoda-badania-jakosci-oprogramowania#comments</comments>
		<pubDate>Fri, 09 Oct 2009 09:58:43 +0000</pubDate>
		<dc:creator>Bartosz Żukowski</dc:creator>
				<category><![CDATA[Bez kategorii]]></category>

		<guid isPermaLink="false">http://blog.atena.pl/?p=781</guid>
		<description><![CDATA[Wdrażanie systemów informatycznych w przedsiębiorstwach powinno przyczyniać się do zwiększenia ich zysków. Nie kupuje się nowych technologii w pogoni za nowoczesnością, lecz traktuje je jak inwestycje w biznes. Menedżerowie liczą, że poniesione nakłady zwrócą się, wpływając na wzrost efektywności pracy firmy. Pozytywny efekt wdrożenia systemu powinien być widoczny w wynikach finansowych, a tę informację otrzymamy [...]]]></description>
			<content:encoded><![CDATA[<p>Wdrażanie systemów informatycznych w przedsiębiorstwach powinno przyczyniać się do zwiększenia ich zysków. Nie kupuje się nowych technologii w pogoni za nowoczesnością, lecz traktuje je jak inwestycje w biznes. Menedżerowie liczą, że poniesione nakłady zwrócą się, wpływając na wzrost efektywności pracy firmy. Pozytywny efekt wdrożenia systemu powinien być widoczny w wynikach finansowych, a tę informację otrzymamy dopiero po pewnym czasie. Ważne jest zatem monitorowanie wydajności, rozpoznawanie trendów i reagowanie z wyprzedzeniem. Jednym z elementów pozwalających ocenić efektywność jest satysfakcja użytkowników końcowych. Właśnie w celu jej pomiaru opracowano metodę SUMI (<em>Software Usability Measurement Inventory</em>).</p>
<p><span id="more-781"></span></p>
<p>SUMI powstało na uniwersytecie Cork w Irlandii. Grupa ekspertów w dziedzinie oprogramowania stale rozwija tę metodę od ponad 15 lat. Jej celem jest badanie głównych czynników wpływających na użyteczność oprogramowania, mierzenie wydajności w połączeniu z satysfakcją z pracy. Metoda ta zdobyła popularność i jest powszechnie stosowana. Dzięki niej możemy mierzyć zadowolenie pracowników z używania nowego systemu.</p>
<p>SUMI opiera się na badaniu ankietowym w sześciu obszarach mających decydujący wpływ na wydajność pracy. Badane obszary to:</p>
<ol>
<li>współpraca &#8211; łatwości      współpracy i komunikacji pomiędzy użytkownikami;</li>
<li>dostęp do danych &#8211; tworzenie      zestawień, raportów, wyszukiwanie informacji, wymiana informacji;</li>
<li>elastyczność &#8211; obsługa      nietypowych problemów i zadań, możliwości wprowadzania modyfikacji;</li>
<li>użyteczność &#8211; łatwość      obsługi, komfort pracy;</li>
<li>znajomość &#8211; nauka obsługi,      intuicyjność rozwiązań;</li>
<li>wydajność transakcyjna &#8211; szybkość      i niezawodność, wykonywanie powtarzalnych zadań.</li>
</ol>
<p>Badanie polega na wypełnieniu ankiet przez użytkowników systemu. Pytania w poszczególnych obszarach tworzone są w oparciu o scenariusze użycia, które odzwierciedlają realną pracę z systemem. Muszą one odpowiadać uprawnieniom i zakresom obowiązków użytkowników.</p>
<p>Przykład pytań ze znajomości obsługi:</p>
<ol>
<li>Czy do pracy z systemem X      konieczne jest przeszkolenie?</li>
</ol>
<p>a)      zdecydowanie tak</p>
<p>b)      tak</p>
<p>c)      raczej tak</p>
<p>d)      raczej nie</p>
<p>e)      nie</p>
<p>f)        zdecydowanie nie</p>
<ol>
<li>Czy podczas pracy zdarza      się, że nie wiesz, który przycisk należy nacisnąć?</li>
</ol>
<p>a)      zdecydowanie nie</p>
<p>b)      nie</p>
<p>c)      raczej nie</p>
<p>d)      raczej tak</p>
<p>e)      tak</p>
<p>f)        zdecydowanie tak</p>
<p>Wszystkie pytania są oceniane w tej samej kilkupunktowej skali, np. od 1 do 6. Dla każdego obszaru wyciągamy średnią ocenę. Konieczne jest przyjęcie dla wszystkich pytań jednakowych warunków, w których zawsze 6 to najlepsza odpowiedź. Ocena całego produktu powstaje przez średnią ważoną ze wszystkich obszarów.</p>
<p>Wyniki z badania pokazują, które obszary wymagają ulepszeń, a z których użytkownicy są zadowoleni.</p>
<p>Przykładowe wyniki dla obszarów:</p>
<p>- współpraca 4,5</p>
<p>- dostęp do danych 4,8</p>
<p>- elastyczność 5,2</p>
<p>- użyteczność 3,8</p>
<p>- znajomość 2,8</p>
<p>- wydajność transakcyjna 3,9</p>
<p>Z przykładu można wyciągnąć wniosek, że aplikacja ma pewnie duże możliwości, lecz jest trudna w użyciu i użytkownicy potrzebują dużo czasu, aby móc z niej korzystać. Może to uniemożliwić zbieranie korzyści z wdrożenia, mimo że wszystkie funkcjonalności zostały zaimplementowane.</p>
<p>Przykład ten, choć uproszczony, ma za zadanie przedstawić ogólną zasadę. Badanie to jest o tyle interesujące, że w określonym zakresie można je przeprowadzać na prototypach i reprezentatywnej grupie użytkowników już w trakcie procesu wytwarzania. Metoda SUMI jest idealnym uzupełnieniem testów funkcjonalnych.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.atena.pl/sumi-jako-metoda-badania-jakosci-oprogramowania/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

