*Tutorial e exemplos de Androide

Este é nosso tutorial de enfiamento de andróides. Exploramos o que é um "thread" e fornecemos várias abstrações para a classe "Thread".

O que é um "Thread"?

Uma "thread" é um caminho de execução que existe dentro de um processo.

Um processo pode ter um ou mais "threads".

Um processo "único" tem uma "thread" enquanto um processo "múltiplo" tem mais de uma "thread".

No processo de "rosca única", temos apenas um fluxo de execução de instruções enquanto que no processo de "rosca múltipla", temos vários conjuntos de instruções executados simultaneamente.

Um processo "multi-tarefa" tem peças executando simultaneamente e cada peça pode fazer uma determinada tarefa de forma independente.

Portanto, a multi-threading é um mecanismo que nos permite escrever programas de forma que múltiplas atividades possam prosseguir concomitantemente no mesmo programa.

E especialmente no ambiente multicore-dispositivo atual, os desenvolvedores devem ser capazes de criar linhas de execução simultâneas que combinam e agregam dados de múltiplos recursos.

Mas, também é importante observar que na realidade, um sistema que tem apenas um único núcleo de execução pode criar a ilusão de execução concorrente. Ele o faz executando os vários "fios" de uma forma intercalada.
Mas ele o faz de forma tão rápida que pensamos que está realmente realizando tarefas concomitantemente.

O 'Thread' principal

Normalmente, quando você executa seu projeto, seu processo de aplicação será iniciado. Em primeiro lugar, haverá 'threads' para a máquina virtual do Android Runtime ou Dalvik.

Além daqueles que o sistema Android criará um "fio" de execução chamado "principal". Este será o principal thread para sua aplicação.

Esse "tópico" também é às vezes chamado de "tópico da UI".

Sua aplicação pode ter muitos outros "threads", normalmente chamados de background "threads". No entanto, o "tópico" principal é o mais crucial. É esta "thread" que é responsável por interagir com os componentes e visualizações do Android. Ele os torna e também atualiza seus estados.

Este "tópico" é muito crucial, especialmente dado o fato, como já dissemos, de que é onde todos os componentes andróides (Atividade, Serviços, Receptor de Broadcast) são executados por padrão.

Este "tópico" é o responsável pelo tratamento e escuta dos eventos de entrada do usuário. Devido à sua importância, é sempre aconselhado a mantê-lo responsivo por:

  1. Não fazer nenhum tipo de tarefa que possa levar muito tempo como "entrada/saída" (I/O) neste "tópico". Essas tarefas podem bloquear o "tópico" principal por um período de tempo indefinido e, portanto, têm de ser carregadas para um "tópico" de fundo.
  2. Não fazer tarefas com uso intensivo de CPU neste "tópico". Se você tiver alguns cálculos caros ou tarefas como codificação de vídeo, você precisa descarregá-los também para um "thread" de fundo.

Este thread normalmente tem uma facilidade ligada a ele chamada Looper. O "looper" terá uma MessageQueue. Uma MessageQueue é apenas uma fila de mensagens com alguma unidade de trabalho que deve ser executada sequencialmente.

Assim, quando uma mensagem estiver pronta para ser processada na fila, o **Looper Thread*** irá estourar essa mensagem da fila. Essa mensagem será encaminhada de forma síncrona (seqüencialmente) para o manipulador alvo. Esse manipulador já está especificado na mensagem.

Então o "Manipulador" iniciará seu trabalho e o fará. Quando terminar esse trabalho, então o 'Looper' começará a processar a próxima mensagem disponível na fila e a transmitirá para que ela também seja executada.

Você pode ver que este processo é seqüencial. Portanto, suponha que nosso "Handler" não termine seu trabalho rapidamente, o "Looper" estará lá apenas esperando para processar outras mensagens pendentes na fila.

Nesse caso, o sistema mostrará a "Aplicação Não Respondendo (ANR)", "Diálogo". Você já deve ter visto isso em alguns aplicativos. Isso significa que a aplicação não está respondendo às entradas do usuário. No entanto, está ocupado fazendo trabalho.

O diálogo ANR será mostrado aos usuários se um aplicativo não responder à entrada do usuário dentro de cinco segundos. O sistema então oferecerá aos usuários a opção de abandonar a aplicação.

Você se deparará com este tipo de cenário quando tentar fazer tarefas intensivas em seu thread' principal. Isso significa, por exemplo, quando você tenta fazer o seguinte em seu thread` principal:

  1. Acessar a Rede/Serviços Web/Internet
  2. Acessar recursos do sistema de arquivos.
  3. Tente processar grandes quantidades de dados ou fazer cálculos matemáticos complexos, etc.

A maioria do código que você escreve, como em suas atividades, fragmentos, serviços normalmente são executados no "tópico" principal por padrão, a menos que você crie explicitamente um "tópico" de fundo.

O Android SDK é baseado em um subconjunto do Java SDK. Java SDK é derivado do projeto 'Apache Harmony' e fornece acesso a construções de baixo nível de concorrência, como por exemplo:

  1. "java.lang.Thread".
  2. "java.lang.runnable".
  3. Palavras-chave synchronized e volatile.

`classe 'thread'.

A classe java.lang.Thread' é a construção mais básica utilizada para criar threads'.

É também a construção mais comumente utilizada. Esta classe nos cria uma nova linha independente de execução em um programa Java.

Uma maneira de criar uma nova thread é apenas subclassificando ou ampliando a classe java.lang.Thread.

public class MyThread extends Thread {
    public void run() {
        Log.d("Generic", "Our thread is running ...");
    }
}

Podemos então fazer nossa tarefa de fundo dentro do método 'run()run().

No entanto, essa "tarefa" ainda não foi iniciada. Para que isso aconteça, temos que instanciar essa classe e iniciar explicitamente nosso `thread':

    MyThread myThread = new MyThread();
    myTread.start();

O método start() reside na classe Thread. Invocando-o diz ao sistema para criar um thread dentro do processo e executa o
método de "correr()run(). O método run() será executado automaticamente se invocarmos o método start().

Métodos comuns de acionamento.

(a). Thread.currentThread()`**

Este método devolverá a "linha" do chamador, ou seja, a atual "linha".

(b). "Thread.sleep(time)`**.

Este método fará com que o "tópico" que enviou esta mensagem adormeça durante um determinado intervalo de tempo (dado em milissegundos e nanossegundos). A precisão não é garantida - o "thread" pode dormir mais ou menos do que o solicitado.

Basicamente, ela faz uma pausa na execução do "thread" atual para a
determinado período de tempo.

**(c). getContextClassLoader()`***

Este método devolverá o contexto ClassLoader para este "Thread".

**(d). start()***

Este método iniciará a nova "linha" de execução. O método run() do receptor será chamado pelo próprio receptor Thread (e não o Thread chamando start()).

**(e). Thread.getName() e Thread.getId()***.

Estes receberão o nome e o TID respectivamente. Estes são utilizados principalmente para fins de depuração.

**(f) Thread.isAlive()***

isAlive()`verificará se o "tópico" está funcionando atualmente ou não
já terminou seu trabalho.

**(g) Thread.join()***

A "join()juntar()bloqueará a corrente `linha' e esperará até o acesso
rosca termina sua execução ou matrizes.

Como manter a capacidade de resposta do aplicativo

A melhor maneira de manter a capacidade de resposta não é fugindo de operações de longa duração. Ao invés disso, é descarregando-as do
para que possam ser tratados em segundo plano por outro "fio".

O principal "tópico" pode então continuar a processar as atualizações da interface do usuário sem problemas e responder de forma oportuna às interações do usuário.

Normalmente há um conjunto de operações típicas que são comuns em muitas aplicações e consomem não apenas muito tempo, mas também recursos do dispositivo.

Estes incluem:

  • Acesso e comunicação através da rede, especialmente a Internet.
  • Operações de entrada e saída de arquivos. Estas ocorrem no sistema de arquivos local.
  • Processamento de imagem e vídeo.
  • Cálculos matemáticos complexos.
  • Processamento de texto - Tentando processar ou analisar uma grande quantidade de texto.
  • Codificação e decodificação de dados.

*Rápido Treading Exemplos

1. Criação de temporizador simples com a classe "Thread

Esta é uma classe para mostrar como implementar um temporizador simples. Não imprime nada e é apenas uma classe para mostrar como implementar tal idéia.

import java.lang.Thread;

public class TimerClass extends Thread{

    boolean timeExpired;
    double mTime;
    /** Creates a new instance of TimerClass */
    public TimerClass(double time){
        mTime = time;
    }

    public void run(){

        timeExpired = true;
        mTime = mTime * 1000;
        double startTime = System.currentTimeMillis();
        double stopTime = startTime + mTime;
        while(System.currentTimeMillis() < stopTime && timeExpired == false){
              try {
                Thread.sleep(10);
            } catch (InterruptedException e){ }
        }

        timeExpired = true;

    }

    public boolean getTimeExpired(){
        return true;
    }

    public void cancel(){
        timeExpired = true;
    }

}

2. Classe de utilidades Linha Completa Reutilizável

import android.os.Looper;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Threading tools
 * </p>
 */
public class ThreadUtils {

    private final static ExecutorService sThreadPool = Executors.newCachedThreadPool();

    /**
     * Current thread
     */
    public static Thread currentThread() {
        return Thread.currentThread();
    }

    /**
     * Current process ID
     */
    public static long currentThreadId() {
        return Thread.currentThread().getId();
    }

    /**
     * Current process name
     */
    public static String currentThreadName() {
        return Thread.currentThread().getName();
    }

    /**
     * Determine if it is a UI thread
     */
    public static boolean isUiThread() {
        return Looper.myLooper() == Looper.getMainLooper();
    }

    /**
     * Runs on the UI thread
     */
    public static void runOnUiThread(Runnable action) {
        if (action == null) {
            return;
        }
        if (Looper.myLooper() == Looper.getMainLooper()) {
            action.run();
        } else {
            HandlerUtils.uiPost(action);
        }
    }

    /**
     * Runs in the background thread
     */
    public static void runOnBackgroundThread(Runnable action) {
        if(action==null){
            return;
        }
        if (Looper.myLooper() != Looper.getMainLooper()) {
            action.run();
        }else{
            sThreadPool.submit(action);
        }
    }

    /**
     * Run on asynchronous thread
     */
    public static void runOnAsyncThread(Runnable action) {
        if (action == null) {
            return;
        }
        sThreadPool.submit(action);
    }

    /**
     * Runs on the current thread
     */
    public static void runOnPostThread(Runnable action) {
        if(action==null){
            return;
        }
        action.run();
    }

    public static void backgroundToUi ( final Runnable background , final Runnable ui ) {
        runOnBackgroundThread(new Runnable() {
            @Override
            public void run() {
                background.run();
                runOnUiThread ( ui );
            }
        });
    }
}

Categorized in: