MójDroid.pl

#15 Twórz aplikacje na Androida z Mojdroid.pl – Handler (część druga wątków)

2012-09-30
|
Damian P.

W poprzednim wpisie krótko przedstawiłem wam czym jest Thread. Z jego pomocą możemy dużo zdziałać, jednak od razu pisząc program możemy zauważyć pewną jego wadę - niektóre części aplikacji przed jego uruchomieniem musimy zablokować, tak aby nie zmieniły swojego stanu. Nie możemy również w łatwy sposób dostać się do innych fragmentów programu, co może być dla nas problematyczne, bo Thread często będzie wykonywał jakieś cięższe prace. Aby pozbyć się takich dolegliwości, Android potrafi obsługiwać pewną funkcjonalność jaką są MessageHandlery.
Informacja: Nie radzisz sobie z kodem? Coś Ci nie wychodzi lub nie działa? Zgubiłeś się? W tym miejscu zobaczysz pełen kod aplikacji, a tutaj go pobierzesz na dysk.

1. Handler

Jak pisałem, Handler umożliwia wysyłanie i przetwarzanie wiadomości (jak i obiektów MessageQueue powiązanych z Runnable). Każdy pojedynczy Handler jest połączony z wątkiem (tym, w którym zostaje stworzony) i w nim zostają przetwarzane wiadomości, które w końcu trafiają do naszego Handlera. O co chodzi z tymi wiadomościami? Są to proste komunikaty, w których albo możemy przesyłać całe dane do przetworzenia, albo wybrane identyfikatory. Przykładowo, Handler może czekać na wiadomość z liczbą jeden. Jeżeli taką dostanie (to znaczy odbierze i rozpozna), wykona określoną przez nas czynność. Co ważne, nasze rozpisane zadanie nie zostanie uruchomione wcześniej, tylko dokładnie wtedy kiedy dojdzie wiadomość. Pojedyncze komunikaty możemy wysyłać przez konstruowanie wiadomości typu Message (lub EmptyMessage). Przykład wykorzystania? Nasz Thread może na przykład coś pobierać czy wczytywać. Gdy skończy, wynik (poprzez Message) możemy przesłać do naszego Handlera, który w następnym kroku coś wykona, nawet niekoniecznie w naszym obecnym Activity.

2. Tworzymy Hander z Threadem

Stwórzmy jakiś prosty przykład zastosowania/wykorzystania Handlera w aplikacji. Skopiujmy naszą wczorajszą klasę, zmieńmy jej nazwę oraz wklejmy ponownie do projektu - zróbmy po prostu jej kopię w aplikacji. Nie będziemy tworzyć ponownie szablonów i pisać kodu nowego wątku, tylko skorzystamy z tego co już mamy. Starą-nową klasę nazwijmy View_Handler. Najpierw dodajmy prostego Handlera do programu, nie zmieniając niczego wcześniej w aplikacji:
package com.example.moja.pierwsza.aplikacja;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;

public class View_Handler extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);

	setContentView(R.layout.view_thread);

	final TextView tv1 = (TextView) findViewById(R.id.tV_thread);
	
	Handler handler = new Handler(){

	    @Override
	    public void handleMessage(Message msg) {
		super.handleMessage(msg);	
	    }
	    
	};

	new Thread(new Runnable() {
	    public void run() {
		tv1.setText("Thread został uruchomiony!");
	    }
	}).start();

    }

}
Nic trudnego. Tworzymy naszego Handlera, po czym w nim umieszczamy metodę oczekującą i obsługującą nadchodzące wiadomości. Tutaj możemy stworzyć rozpoznawanie tego co otrzymujemy i wykonać odpowiednie działania. W naszym przykładzie zmienimy jedynie TextView na kolejną liczbę.
package com.example.moja.pierwsza.aplikacja;

import android.R.integer;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;

public class View_Handler extends Activity {

    TextView tv1;
    Handler handler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);

	setContentView(R.layout.view_thread);

	tv1 = (TextView) findViewById(R.id.tV_thread);

	handler = new Handler() {

	    @Override
	    public void handleMessage(Message msg) {
		super.handleMessage(msg);

		tv1.setText(msg.obj.toString());

	    }

	};

	new Thread(new Runnable() {
	    public void run() {

		try {

		    int przesylanaliczba = 0;

		    while (przesylanaliczba < 10) {

			// Próbujemy uśpić thread na dwie sekundy, abyśmy
			// widzieli jego działanie
			Thread.sleep(2000);

			// Tworzymy nową wiadomość
			Message wiadomosc = new Message();
			
			// Dodajemy treść, używamy jednego z dostępnych pól w Message
			wiadomosc.obj = przesylanaliczba;

			// Zwiększamy liczbę o kolejną
			przesylanaliczba++;
			
			// Oczywiście wysyłamy na końcu naszą wiadomość do Handlera
			handler.sendMessage(wiadomosc);
		    }

		} catch (InterruptedException e) {
		    e.printStackTrace();
		}

	    }
	}).start();

    }

}
I oto cała magia. Kolejne kroki opisałem od razu przy kodzie, abyście wiedzieli co się dzieje. Handlery to bardzo przydatna część w aplikacji, i jeżeli dobrze jej użyjemy, to zapewnimy sobie  całą garść ciekawych funkcjonalności.

Ps. Czyta to ktoś? ;) Jeżeli tak, to możecie podawać swoje pomysły i propozycje, spróbuję pomóc!