miércoles, 23 de febrero de 2011

Manejo de Hilos en Android

Uno de los mayores quebraderos de cabeza en Android es el manejo de hilos.
No es posible acceder a las variables de la UI desde un hilo diferente del principal. Por tanto si después de realizar una operacion pesada(una comunicacion por red, acceso al GPS...) queremos actualizar un textview, debemos de pasar esa operacion dentro de un runnable al handler de la Activity. El handler es un objeto de la clase Handler, que una vez declarado en la clase principal, en nuestro ejemplo una Activity, permite interactuar con sus variables.


public class MyActivity extends Activity {
[ . . . ]
// Need handler for callbacks to the UI thread
final Handler mHandler = new Handler();

// Create runnable for posting
final Runnable mUpdateResults = new Runnable() {
public void run() {
updateResultsInUi
();
}
};

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

[ . . . ]
}

protected void startLongRunningOperation() {

// Fire off a thread to do some work that we shouldn't do directly in the UI thread
Thread t = new Thread() {
public void run() {
mResults
= doSomethingExpensive();
mHandler
.post(mUpdateResults);
}
};
t
.start();
}

private void updateResultsInUi() {

// Back in the UI thread -- update our UI elements based on the data in mResults
[ . . . ]
}
}

Otra forma de abordar el problema es mediante el uso de mensajes de nuevo con la clase handler. Como bien indica el SDK de android:

There are two main uses for a Handler: (1) to schedule messages and runnables to be executed as some point in the future; and (2) to enqueue an action to be performed on a different thread than your own.

En este ejemplo tan sencillo, nos interesa utilizar el handler para pasar el control del programa desde el hilo que realiza la operacion en el background a el hilo principal, para que actualice el UI. Es decir, como ya hemos mencionado, no sería posible modificar el UI desde el hilo secundario, sino que tenemos que llamar al hilo principal(mediante el objeto hanlder)para que se ocupe de ello. El siguiente código NO SERIA CORRECTO:

protected void startLongRunningOperation() {

// Fire off a thread to do some work that we shouldn't do directly in the UI thread
Thread t = new Thread() {
public void run() {
mResults
= doSomethingExpensive();
updateResultsInUi
(); //NO DEBE LLAMARSE AQUI.

}
};
t
.start();
}

private void updateResultsInUi() {

//update our UI elements based on the data in mResults
[ . . . ]
}

Como comentaba antes, otro modo de comunicación con el handler es mediante el uso de mensajes, que equivale a hacer un "post(Runnable r)":

public class MyActivity extends Activity {

[ . . . ]
// Need handler for callbacks to the UI thread
final Handler mHandler = new Handler(){ @override public void handleMessage(Message msg){ if(msg.what == 0) updateResultsInUi(); } };

// Create runnable for posting
final Runnable mUpdateResults = new Runnable() {
public void run() {
updateResultsInUi
();
}
};

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

[ . . . ]
}

protected void startLongRunningOperation() {

// Fire off a thread to do some work that we shouldn't do directly in the UI thread
Thread t = new Thread() {
public void run() {
mResults
= doSomethingExpensive();
//mHandler
.post(mUpdateResults); mHandler.sendMessage(0);
}
};
t
.start();
}
private void updateResultsInUi() {

// Back in the UI thread -- update our UI elements based on the data in mResults
[ . . . ]
}
}

martes, 8 de febrero de 2011

Publicidad y smartphones

La era de la tecnología móvil ya ha comenzado. Las posibilidades para los smartphones empiezan a superar a las de las tecnologías convencionales. Las compañias que sepan aprovechar esta nueva ola digital serán las que consigeran mantenerse.