Bienvenidos sean a este post, hoy hablaremos sobre un tema que deberiamos evitar, el cual es utilizar el hilo principal para la conexion de Internet, en los casos anteriores utilizamos el StrictMode para permitir la coenxion y en estos casos tuvimos la suerte de que la conexion tiene poca latencia pero dependiendo del tipo de conexion podemos tener una con mucha demora y esta puede bloquearnos la aplicacion, para evitar esto debemos usar AsynTask para correrlo en otro proceso, si bien hablamos de ello en este post para estudiar sobre AsyncTask pero vamos a tomar el ejemplo anterior y realizar algunas modificaciones.

Primero modificaremos a MainActivity y agregaremos la siguiente clase:

    class BuscarGoogle extends AsyncTask<String, Void, String>{
        private ProgressDialog progreso;

        @Override
        protected void onPreExecute(){
            progreso = new ProgressDialog(MainActivity.this);
            progreso.setProgressStyle(ProgressDialog.STYLE_SPINNER);
            progreso.setMessage("Accediendo a Google...");
            progreso.setCancelable(false);
            progreso.show();
        }

        @Override
        protected String doInBackground(String... palabras){
            try{
                return resultadoGoogle(palabras[0]);
            } 
            catch (Exception e){
                cancel(true);
                Log.e("HTTP", e.getMessage(), e);
                return null;
            }
        }
        
        @Override
        protected void onPostExecute(String res){
            progreso.dismiss();
            salida.append(res + "\n");
        }
        
        @Override
        protected void onCancelled(){
            progreso.dismiss();
            salida.append("Error al conectarlo.\n");
        }
    }

Esta clase debe ser agregada dentro de MainActivity, esta nueva clase extiende a AsyncTask y como vimos en su momento debemos definir los tres tipos de datos para los metodos a implementar, luego crearemos un objeto de tipo ProgressDialog llamado progreso, el primer metodo que sobreescribiremos es onPreExecute(), este se encargara de crear la ventana de indicacion de progreso, la primera linea definira el contexto la cual es la clase actual, luego definiremos el estilo, despues el mensaje a mostrar en el cuadro y por ultimo setearemos que no sea cancelable, por ultimo mostramos el cuadro creado.

El siguiente metodo es doInBackground(), este recibe a palabras, con el bloque try/catch, en el bloque try devolvera el valor obtenido en resultadoGoogle() de lo contrario cancelara todo y mostrara un mensaje en el log con el error.

El siguiente metodo sera en onPostExecute() que recibira un dato llamado res, luego cerrara el cuadro y por ultima agregara el dato recibido lo agregara a salida.

Por ultimo tenemos el metodo onCancelled() donde tambien cerrara el cuadro pero en lugar de mostrar un dato nos notificara con un mensaje de error en salida, nuestra ultima modificacion sera para el metodo Buscar, debemos cambiarlo con el siguiente codigo:

    public void Buscar(View view){
        String palabras = entrada.getText().toString();
        salida.append(palabras + " -- ");
        new BuscarGoogle().execute(palabras);
    }

Primero crearemos una variable llamada palabras donde le asignaremos los datos ingresados en entrada, despues agregaremos a salida los valores almacenados en palabras y por ultimo llamaremos a la nueva clase que creamos, el codigo final de nuestra clase quedara de la siguiente forma:

package org.example.http;

import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.StrictMode;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;

public class MainActivity extends AppCompatActivity {

    private EditText entrada;
    private TextView salida;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        entrada=(EditText) findViewById(R.id.EditText01);
        salida=(TextView) findViewById(R.id.TextView01);
        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy
                .Builder().permitNetwork().build());
    }

    public void Buscar(View view){
        String palabras = entrada.getText().toString();
        salida.append(palabras + " -- ");
        new BuscarGoogle().execute(palabras);
    }

    String resultadoGoogle(String palabras) throws Exception{
        String pagina = "", devuelve = "";
        URL url = new URL("https://www.google.es/search?hl=en&q=\""
                + URLEncoder.encode(palabras,"UTF-8") + "\"");
        HttpURLConnection conexion = (HttpURLConnection)
                url.openConnection();
        conexion.setRequestProperty("User-Agent","Mozilla/5.0 (Windows NT 10.0;"
                + "Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
                + "Chrome/74.0.3729.169 Safari/537.36");
        if (conexion.getResponseCode()==HttpURLConnection.HTTP_OK) {
            BufferedReader reader = new BufferedReader(new
                    InputStreamReader(conexion.getInputStream()));
            String linea = reader.readLine();
            while (linea!=null){
                pagina+=linea;
                linea=reader.readLine();
            }
            reader.close();
            int ini = pagina.indexOf("About");
            if (ini != -1){
                int fin = pagina.indexOf(" ", ini + 16);
                devuelve = pagina.substring(ini + 6, fin);
            } else {
                devuelve = "no encontrado";
            }
        } else {
            salida.append("Error: " + conexion.getResponseMessage() + "\n");
        }
        conexion.disconnect();
        return devuelve;
    }

    class BuscarGoogle extends AsyncTask<String, Void, String>{
        private ProgressDialog progreso;

        @Override
        protected void onPreExecute(){
            progreso = new ProgressDialog(MainActivity.this);
            progreso.setProgressStyle(ProgressDialog.STYLE_SPINNER);
            progreso.setMessage("Accediendo a Google...");
            progreso.setCancelable(false);
            progreso.show();
        }

        @Override
        protected String doInBackground(String... palabras){
            try{
                return resultadoGoogle(palabras[0]);
            }
            catch (Exception e){
                cancel(true);
                Log.e("HTTP", e.getMessage(), e);
                return null;
            }
        }

        @Override
        protected void onPostExecute(String res){
            progreso.dismiss();
            salida.append(res + "\n");
        }

        @Override
        protected void onCancelled(){
            progreso.dismiss();
            salida.append("Error al conectarlo.\n");
        }
    }
}

Si compilamos y probamos nuestra aplicacion obtendremos un resultado como se ve en la siguiente imagen

Como pueden ver en el video a diferencia del caso anterior en este caso por cada busqueda tendremos un cuadro de progreso lo cual evitara que nuestra app se bloquee ante una eventual lentitud de la red y seamos sinceros quedo mas “monona” 😂

En resumen, hoy hemos hecho una modificacion a nuestra app anterior, hemos evitado el uso de la conexion a internet por medio del hilo principal, hemos repasado AsyncTask, hemos puesto en practica nuestra modificacion, espero les haya sido util sigueme en Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.

Anuncios