Einfaches GoogleMaps mit Threads - Tutorial
Dieses Tutorial basiert auf meinem GoogleMaps mit der Geocoder Klasse Tutorial, wo ich beschrieben habe, wie man Adressen in Longitude und Latitude konvertiert. Liest man allerdings aufmerksam die GeoCoder-API, dann stolpert man über den Hinweis, dass es hilfreich sei, die GeoCoder-Instanz in einem eigenständigen Thread und unabhängig von der GUI auszuführen. Dieses Tutorial zeigt, wie man in Android Threads einsetzt.
Wie die Anwendung aussieht:
Wie die GoogleMaps mit der Geocoder Klasse Anwendung, nur dass zusätzlich ein Ladebalken eingeblendet wird.

Was ist ein Thread?
Lies folgendes Kapitel in der Java Dokumentation um zu verstehen was Threads sind und wie sie funktionieren. Außerdem ist folgendes Kapitel in der Android API interessant.
Alternativ kannst du auch einfach folgende Definition hinnehmen:
Ein Thread erlaubt einen paralleler Prozess - Während wir die Adresse suchen, können wir gleichzeitig noch einen Ladebalken anzeigen.
Wie können wir Threads in Android verwenden?
Wir können ein Runnable Interface einbinden und die run() Funktion aufrufen.
public class simpleGoogleMaps extends MapActivity implements runnable{ public void onCreate(Bundle savedInstanceState) { Thread thread = new Thread(this); thread.start(); } public void run() { //do something } }
Lies dieses Tutorial von helloandroid.com um zu sehen, wie diese Methode funktioniert.
Aber es gibt noch einen alternativen Weg, wie man Threads verwenden kann und der meiner Meinung nach wesentlich sauberer ist.
GeoCoder mit Threads:
1. Wenn man sich den Quellcode des vorherigen Tutorials anschaut, dann sieht man, dass alles Wichtige, wie das Suchen der Adresse, in der OnClickListener Funktion stattfindet. Wenn wir mit Threads arbeiten, ist das Einzige, was wir in der OnClickListener Funktion tun, das Anzeigen des Ladebalkens und der Start eines neuen Threads in dem parallel alle weiteren wichtigen Funktionen ausgeführt werden.
btnSearch.setOnClickListener(new OnClickListener() { public void onClick(View v) { //Show a progress dialog pd = ProgressDialog.show(simpleGoogleMaps.this, "Working..", "Searching your address", true, false); //create a new thread searchAdress = new Thread() { public void run(){ //action of the thread } } } });
2. Während der Ladebalken angezeigt wird, müssen wir nach einer Adresse suchen. Also fügen wir unserem Thread die Suchfunktion hinzu und starten sie.
btnSearch.setOnClickListener(new OnClickListener() { public void onClick(View v) { //Show a progress dialog pd = ProgressDialog.show(simpleGoogleMaps.this, "Working..", "Searching your address", true, false); //create a new thread searchAdress = new Thread() { public void run(){ String addressInput = adress.getText().toString(); // Get input text try { foundAdresses = gc.getFromLocationName(addressInput, 5); // Search addresses } catch (Exception e) { // @todo: Show error message } showAdressResults.sendEmptyMessage(0); } } searchAdress.start(); } });
3. Nun zeigt unsere Anwendung einen hübschen Ladebalken an und sucht im Hintergrund nach einer Adresse. Sehr schön!
Nachdem der Suchvorgang beendet ist (Ende des try-catch-Statement), senden wir eine Benachrichtigung an die neue Funktion showAdressResults, die wir noch erstellen müssen.
private Handler showAdressResults = new Handler() { public void handleMessage(Message msg) { } }
4. showAdressResults ist ein Handler, der die ganze Zeit nichts weiter tut, als darauf zu warten, dass er eine Benachrichtigung bekommt. Wenn er eine bekommt weiß er, dass eine Adresse gefunden wurde. Dann müssen wir den Ladebalken ausblenden und die Karte anzeigen.
private Handler showAdressResults = new Handler() { public void handleMessage(Message msg) { if (foundAdresses.size() == 0) { // if no address found, // display an error Dialog locationError = new AlertDialog.Builder(simpleGoogleMaps.this) .setIcon(0) .setTitle("Error") .setPositiveButton(R.string.ok, null) .setMessage("Sorry, your address doesn't exist.") .create(); locationError.show(); } else { // else display address on map for (int i = 0; i < foundAdresses.size(); ++i) { // Save results as Longitude and Latitude Address x = foundAdresses.get(i); lat = x.getLatitude(); lon = x.getLongitude(); } navigateToLocation((lat * 1000000), (lon * 1000000),myMap); // display the found address } }
Fertig ist unsere erste Android-Anwendung mit Threads :-)
Kompletter Quellcode:
//lots of imports.. see attached source public class simpleGoogleMaps extends MapActivity { protected boolean isRouteDisplayed() { return false; } //lots of variables here @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); myMap = (MapView) findViewById(R.id.simpleGM_map); // Get map from XML btnSearch = (Button) findViewById(R.id.simpleGM_btn_search); // Get button from xml adress = (EditText) findViewById(R.id.simpleGM_adress); // Get address from XML gc = new Geocoder(this); // create new geocoder instance btnSearch.setOnClickListener(new OnClickListener() { public void onClick(View v) { pd = ProgressDialog.show(simpleGoogleMaps.this, "Working..", "Searching your address", true, false); //Show a progress dialog searchAdress = new Thread() { public void run(){ String addressInput = adress.getText().toString(); // Get input text try { foundAdresses = gc.getFromLocationName(addressInput, 5); // Search addresses Thread.sleep(1500); //just to show you that it works } catch (Exception e) { // @todo: Show error message } showAdressResults.sendEmptyMessage(0); } }; searchAdress.start(); } }); } private Handler showAdressResults = new Handler() { @Override public void handleMessage(Message msg) { pd.dismiss(); if (foundAdresses.size() == 0) { // if no address found, // display an error Dialog locationError = new AlertDialog.Builder( simpleGoogleMaps.this).setIcon(0).setTitle( "Error").setPositiveButton(R.string.ok, null) .setMessage("Sorry, your address doesn't exist.") .create(); locationError.show(); } else { // else display address on map for (int i = 0; i < foundAdresses.size(); ++i) { // Save results as Longitude and Latitude // @todo: if more than one result, then show a // select-list Address x = foundAdresses.get(i); lat = x.getLatitude(); lon = x.getLongitude(); } navigateToLocation((lat * 1000000), (lon * 1000000),myMap); // display the found address } } }; /** * Navigates a given MapView to the specified Longitude and Latitude * * @param latitude * @param longitude * @param mv */ public static void navigateToLocation(double latitude, double longitude, MapView mv) { GeoPoint p = new GeoPoint((int) latitude, (int) longitude); // new // GeoPoint mv.displayZoomControls(true); // display Zoom (seems that it doesn't // work yet) MapController mc = mv.getController(); mc.animateTo(p); // move map to the given point int zoomlevel = mv.getMaxZoomLevel(); // detect maximum zoom level mc.setZoom(zoomlevel - 1); // zoom mv.setSatellite(false); // display only "normal" mapview } }
Ich hoffe das Tutorial veranschaulicht etwas die Funktionsweise von Threads.
Dieses Tutorial wurde von mir bereits hier auf englisch im Anddev.org Forum veröffentlicht.
| Anhang | Größe |
|---|---|
| simpleGoogleMaps-withThread.tar | 74.5 KB |














