Threads: Programación concurrente en Android

lunes, 17 de diciembre de 2012

¿Por qué Hilos(Threads) - Android?

Es un Sistema Operativo además de una plataforma de Software: 
  • Se basa en el núcleo Linux y fue diseñada inicialmente para dispositivos móviles. 
Permite programar aplicaciones:
  • Pone a nuestra disposición una framework basada en lenguaje de programación Java.
Es una plataforma de código libre: 
  • Cualquier desarrollador puede crear y desarrollar aplicaciones escritas con lenguaje C u otros lenguajes, y compilarlas a código nativo de ARM (Api de Android).

¿Qué es ARM?

Es una arquitectura de 32 bits desarrollada en 1983 por la empresa Acorn Computers Ltd para usarse en ordenadores personales que manejan un sistema de instrucciones realmente simple y esto, permite ejecutar tareas con un mínimo consumo de energía. 
Es la arquitectura de la CPU de prácticamente todos los teléfonos móviles del mercado.




 Android es un sistema multiproceso……

  • Es capaz de ejecutar (o coordinar) varias tareas (o procesos) de forma concurrente.

¿Por qué multiproceso?


Permite optimizar la CPU, aprovechando los tiempos en que está desocupada para ejecutar otras tareas. 
Con este sistema se incrementa la capacidad de procesamiento.

 Android es un sistema multiflujo……

  • Permite ejecutar de forma simultánea dos o más porciones de código del mismo proceso.

¿Por qué es necesario programar Hilos en Android (Threads)?

  • Android es un sistema orientado a la interacción con el usuario a través de eventos. 
  • Cuando el usuario interactúa con la aplicación, todas las tareas se realizan en el mismo hilo de ejecución, el conocido “Hilo Principal”. Aquí, es donde se ejecutan todas las operaciones que gestionan la interfaz de usuario. 
  • Si realizamos una tarea larga (con un coste elevado), mantenemos ocupado al “Hilo Principal”, bloqueamos la ejecución del resto de componentes de la aplicación y el usuario tiene la sensación de lentitud, bloqueo o mal funcionamiento de la aplicación.

ANR

Android controla todas las operaciones que se realizan sobre el “Hilo Principal”, detecta todas aquellas tareas que tengan un coste de más de 5 segundos y las penaliza con el mensaje “Application Not Responding” (ANR). 
Cuando se muestra este mensaje, el usuario puede decidir forzar el cierre de la aplicación. Esta situación se traduce en una mala experiencia de usuario e induce a pensar que la aplicación no funciona correctamente.

  • Estos errores son los que debemos evitar en nuestra aplicación y es por ello, que necesitamos programar “HILOS CONCURRENTES” para no sobrecargar al “Hilo Principal” con tareas costosas de tiempo y avisarle sólo y cuando, ya tengamos todos los datos preparados que hemos estado “cocinando” en un hilo secundario (Thread).

Caso Práctico

Si queremos solicitar datos a un Servidor Web (PHP) y actualizar una lista (ListView) con el número de cursos que estén registrados en una base de datos, necesitamos programar en un hilo secundario la petición de datos al Servidor Web, y después, avisar al “Hilo Principal” de que ya tenemos toda la información preparada para que lo añada a un elemento visual de la interfaz de usuario.


Conclusiones

  1. Android diferencia entre “Hilo Principal” – “Hilo Secundario” (Interfaz de Usuario – Tareas largas) 
  2. Evitar mensajes de tipo ANR - más de 5 segundos.

 

 Programar Hilos (Ejemplo de código)


Pantalla


Diseño xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/LinearLayout1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="10dp"
    tools:context=".Threads_Handler" >

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="200dp"
        android:layout_height="100dp"
        android:layout_gravity="center_horizontal"
        android:src="@drawable/logo_movil" />

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:text="@string/email"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <EditText
        android:id="@+id/edtEmail"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:hint="Indica tu email...."
        android:inputType="textEmailAddress" >

        <requestFocus />
    </EditText>

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:text="@string/pass"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <EditText
        android:id="@+id/edtPass"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:hint="Indica tu password...."
        android:inputType="textPassword" />

    <Button
        android:id="@+id/btnEnviar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:text="@string/Enviar" />

</LinearLayout>

Activity

package com.seas.threads_handler;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;

import com.seas.threads_handler.services.ServiceLogin;

public class Threads_Handler extends Activity {
    /*Singleton*/
        private static Threads_Handler threads_Handler;
        public static Threads_Handler getInstance(){
            return threads_Handler;
        }
    /*Fin Singleton*/
    private EditText edtEmail;
    private EditText edtPass;
    private Button btnEnviar;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_threads__handler);
        /*Singleton*/
            Threads_Handler.threads_Handler = this;
        /*Fin Singleton*/
        edtEmail = (EditText)findViewById(R.id.edtEmail);
        edtPass = (EditText)findViewById(R.id.edtPass);
        btnEnviar = (Button)findViewById(R.id.btnEnviar);
       
        btnEnviar.setOnClickListener(new OnClickListener(){
            @Override
            public void onClick(View arg0) {
                String email = edtEmail.getText().toString();
                String pass = edtPass.getText().toString();
                ServiceLogin.accionLogin(email,pass);
            }
        });
    }


}

ServiceLogin con Hilos (Threads)

package com.seas.threads_handler.services;

import android.app.ProgressDialog;
import android.os.Handler;
import android.widget.Toast;

import com.seas.threads_handler.Threads_Handler;

public class ServiceLogin {
    private final static Handler manejador = new Handler();
    private static String messageUser;
    private static ProgressDialog dialog;
    public static void accionLogin(final String user,final String pass){
        Toast.makeText(Threads_Handler.getInstance().getBaseContext(),
                "Cargando Datos...", Toast.LENGTH_LONG).show();
        Thread threadLogin = new Thread(){
            public void run(){
                try {
                    Thread.sleep(5000);
                } catch (Exception e) {
                    messageUser = "Error al conectar con el servidor. ";
                }
                manejador.post(proceso);
            }
        };
        threadLogin.start();
    }
   
    private final static Runnable proceso = new Runnable(){
        public void run() {
            try{
                Toast.makeText(Threads_Handler.getInstance().getBaseContext(),
                        "Los datos se han cargado correctamente...", Toast.LENGTH_LONG).show();
            }catch(Exception e){
                Toast.makeText(Threads_Handler.getInstance().getBaseContext(),
                        messageUser, Toast.LENGTH_LONG).show();
            }
        }
    };
}

 

By Alberto Hernández Akkari.

2 comentarios:

Juan Molina 18 de diciembre de 2012, 1:08  

Muy aclarativo!!

Gracias Alberto!

Juan Molina 18 de diciembre de 2012, 1:09  

Muy aclarativo!
Gracias Alberto!!

Publicar un comentario

fsvelectronicainformatica agradece tu comentario.

  © Blogger template On The Road by Ourblogtemplates.com 2009

Back to TOP