Bienvenidos sean a este post, hoy continuaremos con el post anterior pero esta vez nos centraremos en la baja de un lugar, como adaptar a mapa a la base de datos y el efecto no visto anteriormente de actualizar nuestros cambios automaticamente, todo sobre la app MisLugares y para ello abramos la app con Android Studio y debemos modificar el metodo borrar() en la clase Lugares con el siguiente codigo:

    public static void borrar(int id){
        SQLiteDatabase db = lugaresDB.getWritableDatabase();
        db.execSQL("DELETE FROM lugares WHERE _id = " + id);
        db.close();
    }

En este metodo primero crearemos el objeto que nos conectara a la base y nos permitira escribirla, despues ejecutamos un query donde borraremos la entrada informada por medio de id y luego cerraremos la conexion a la base, nuesta siguiente modificacion sera a la hora de cancelar el ingreso de un nuevo lugar, para ello vamos a ir a la clase EdicionLugar y dentro del metodo onOptionsItemSelected() modificaremos el siguiente bloque:

        int id = item.getItemId();
        if (id == R.id.accion_cancelar){
            finish();
            return true;
        }

        if (id == R.id.accion_guardar){
            guardar();
        }

De la siguiente forma:

        int idItem = item.getItemId();
        if (idItem == R.id.accion_cancelar){
            if(getIntent().getExtras().getBoolean("nuevo",false)){
                Lugares.borrar((int) id);
            }
            finish();
            return true;
        }

        if (idItem == R.id.accion_guardar){
            guardar();
        }

En este caso primero modificamos al id por idItem porque sino tendremos problema a la hora de borrarlo por medio del metodo borrar(), luego agregamos un condicional donde chequeara si nuevo existe, en caso de ser verdadero llamara al metodo borrar() con el id informado, si se preguntan por el false del condicional es simplemente un valor por defecto en caso de no existir, y despues sigue como de costumbre finaliza la actividad y devuelve un verdadero, nuestra siguiente modificacion sera para adaptar nuestra accion vista de Mapa para utilizar la base de datos, para ello debemos reemplazar el codigo de la clase Mapa por el siguiente:

public class Mapa extends FragmentActivity
        implements GoogleMap.OnInfoWindowClickListener, OnMapReadyCallback {

    private GoogleMap mapa;

    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.mapa);
        ((SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.mapa)).getMapAsync(this);
    }

    @Override
    public void onInfoWindowClick(Marker marcador){
        int id = Lugares.buscarNombre(marcador.getTitle());
        if (id!=-1){
            Intent intento = new Intent(this,VistaLugar.class);
            intento.putExtra("id",(long)id);
            startActivity(intento);
        }
    }

    @Override
    public void onMapReady(GoogleMap map){
        boolean primero = true;
        Cursor c = Lugares.listado();
        
        mapa = map;
        mapa.setMapType(GoogleMap.MAP_TYPE_NORMAL);
        mapa.setMyLocationEnabled(true);
        mapa.getUiSettings().setZoomControlsEnabled(true);
        mapa.getUiSettings().setCompassEnabled(true);
        
        while(c.moveToNext()){
            GeoPunto p = new GeoPunto(c.getDouble(3),c.getDouble(4));
            if (p!=null && p.getLatitud()!=0){
                if(primero){
                    mapa.moveCamera(CameraUpdateFactory.newLatLngZoom(
                            new LatLng(p.getLatitud(),p.getLongitud()),12));
                    primero = false;
                }
                BitmapDrawable iconoDrawable = (BitmapDrawable) 
                        getResources().getDrawable(TipoLugar.values()[c.getInt(5)]
                                .getRecurso());
                Bitmap iGrande = iconoDrawable.getBitmap();
                Bitmap icono = Bitmap.createScaledBitmap(iGrande,
                        iGrande.getWidth()/7,iGrande.getHeight()/7,
                        false);
                mapa.addMarker(new MarkerOptions()
                        .position(new LatLng(p.getLatitud(),p.getLongitud()))
                        .title(c.getString(1))
                        .snippet(c.getString(2))
                        .icon(BitmapDescriptorFactory.fromBitmap(icono)));
            }
        } 
    }
}

En este caso tendremos nuestro metodo llamado OnInfoWindowClick(), en el cual haremos las modificaciones mas grandes porque primero crearemos una variable llamada id donde utilizaremos un metodo que veremos proximamente para obtener el id del lugar en base al nombre del marcador, despues por medio del condicional chequearemos que id sea distinto a -1 y en caso de ser cierto crearemos un intento para nuestra actividad, a esta actividad le enviaremos el valor que obtuvimos para id y llamaremos a la actividad creada, en onMapReady crearemos dos variables una llamada primero de tipo boolean donde la setearemos como true y otra de tipo Cursor llamada c donde obtendremos el listado de nuestros lugares, y por medio de c obtendremos algunos de los valores necesarios para nuestro lugar, en este caso la latitud, la longitud, el icono, el titulo y la direccion, pasemos a corregir el error anterior agregando el metodo buscarNombre() a la clase Lugares:

    public static int buscarNombre(String nombre){
        int id = -1;
        SQLiteDatabase db = lugaresDB.getReadableDatabase();
        Cursor c = db.rawQuery("SELECT * FROM lugares WHERE nombre = '"
                + nombre + "'",null);
        if(c.moveToNext()){
            id = c.getInt(0);
        }
        c.close();
        db.close();
        return id;
    }

En este caso primero crearemos una variable llamada id donde le asignaremos el valor -1, en caso de ocurrir algun error devolvera ese valor y evitara que continue en la clase Mapa, recuerden el condicional que vimos ahi, luego crearemos una conexion a la base de datos y la haremos para leer, luego crearemos un cursor para ejecutar el query de busqueda y por ultimo si se realizo correctamente asignaremos el valor del primer campo a id, despues cerraremos las conexiones y devolveremos el valor de id, nuestra ultima modificacion es para la actualizacion de nuestra primera lista cada vez que hacemos una modificacion en los lugares, para ello debemos hacer algunas modificaciones y deberemos agregar algunos metodos para que esto funcione correctamente, primero deberemos reemplazar la linea:

startActivity(i) o startActivty(intento)

Por esta:

startActivityForResult(i,0) o startActivityForResult(intento,0) 

En los metodos onOptionsItemSelected() y onListItemClick(), estas modificaciones debemos hacerlas para cuando hagamos una modificacion o borremos algunos de los lugares, para nuestro siguiente paso agregaremos los siguiente metodos:

    @Override
    protected void onActivityResult(int requestCode, int resultCode,
                                    Intent data){
        super.onActivityResult(requestCode,resultCode,data);
        actualizaLista();
    }

    public void actualizaLista(){
        ListView listView = (ListView) findViewById(R.id.ListaVista);
        AdaptadorCursorLugares adaptador = (AdaptadorCursorLugares)
                listView.getAdapter();
        adaptador.changeCursor(Lugares.listado());
    }

El primer metodo sera el encargado de monitorear el resultado devuelto por nuestro inicio de actividad, informa tres datos y los cuales envia por medio de super al contructor y despues llama al metodo actualizaLista(), nuestro siguiente metodo es justamente este, el cual primero creara un vinculo entre el elemento del layout y el codigo Java, luego crearemos un objeto de tipo AdaptadorCursorLugares donde le instanciaremos a nuestro anterior vinculo por medio de getAdapter() y por ultimo cambiaremos a este adaptador el cursor (o la conexion a la base) y usaremos el valor devuelto por listado() de la clase Lugares.
Con todo esto podemos compilarlo y probarlo en un emulador como veremos en el siguiente video

Como podemos ver en el video ahora tenemos una app mas optima porque no solamente podemos cancelar una nueva entrada sino tambien a diferencia de nuestro post anterior se actualiza automaticamente todas nuestras modificaciones.

En resumen, hoy hemos agregado mas operaciones para trabajar con nuestras bases, hemos agregado la opcion de actualizar nuestras modificaciones automaticamente, y adaptamos a nuestra clase Mapa para poder obtener todos los datos desde nuestra base de datos, 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