{"id":1684,"date":"2018-10-31T23:10:08","date_gmt":"2018-11-01T05:10:08","guid":{"rendered":"http:\/\/naps.com.mx\/blog\/?p=1684"},"modified":"2018-11-08T12:50:54","modified_gmt":"2018-11-08T18:50:54","slug":"agregar-y-mostrar-datos-en-realm-con-android","status":"publish","type":"post","link":"https:\/\/naps.com.mx\/blog\/agregar-y-mostrar-datos-en-realm-con-android\/","title":{"rendered":"Agregar y mostrar datos en Realm con Android"},"content":{"rendered":"<p><em><strong>Creamos una aplicaci\u00f3n que permite agregar y mostrar datos en <a href=\"https:\/\/realm.io\" target=\"_blank\" rel=\"noopener\">Realm<\/a> (base de datos) para Android.<\/strong><\/em><\/p>\n<p><!--more--><\/p>\n<ul>\n<li>Consulta el art\u00edculo anterior que contiene la <a href=\"http:\/\/naps.com.mx\/blog\/crear-un-floating-action-button-en-android\/\">creaci\u00f3n del bot\u00f3n Floating Action Button<\/a>.<\/li>\n<li>Consulta el art\u00edculo que muestra <a href=\"http:\/\/naps.com.mx\/blog\/primeros-pasos-en-realm-con-android\/\">c\u00f3mo se instala Realm<\/a> en la aplicaci\u00f3n.<\/li>\n<\/ul>\n<p>En primer lugar, vamos a crear un cuadro de di\u00e1logo personalizado para pedir el nombre de un \u201ctablero\u201d y posteriormente guardarlo en la base de datos.<\/p>\n<p>Primero, crearemos un Layout con el dise\u00f1o que queremos para el cuadro de di\u00e1logo y luego desde Java usaremos ese layout para inflar una vista que ser\u00e1 pasada al componente <strong>AlertDialog<\/strong> de Android.<\/p>\n<h2>Crear un <em>layout<\/em> para crear un cuadro de di\u00e1logo en Android<\/h2>\n<p>Da clic derecho sobre layout (app-&gt;res-&gt;layout)<\/p>\n<p>Luego en <strong>New-&gt;Layout resource file<\/strong><\/p>\n<p>Como nombre del layout usaremos <em>dialog_create_board.\u00a0<\/em>En \u00e9ste layout colocamos un EditText donde el usuario escribir\u00e1 el nombre del \u00abtablero\u00bb.<\/p>\n<p>El c\u00f3digo de \u00e9ste layout es similar a \u00e9ste:<\/p>\n<pre class=\"lang:xhtml decode:true \">&lt;?xml version=\"1.0\" encoding=\"utf-8\"?&gt;\r\n&lt;android.support.constraint.ConstraintLayout\r\n    xmlns:android=\"http:\/\/schemas.android.com\/apk\/res\/android\" android:layout_width=\"match_parent\"\r\n    android:layout_height=\"match_parent\"&gt;\r\n\r\n    &lt;EditText\r\n        android:id=\"@+id\/editTextNewBoard\"\r\n        android:layout_width=\"match_parent\"\r\n        android:layout_height=\"wrap_content\"\r\n        android:layout_margin=\"15dp\"\r\n        android:hint=\"Board title\"\/&gt;\r\n\r\n&lt;\/android.support.constraint.ConstraintLayout&gt;<\/pre>\n<p>En <strong>MainActivity<\/strong> vamos a crear un m\u00e9todo llamado <em><strong>showAlertForCreatingboard<\/strong><\/em> que nos servir\u00e1 para construir un cuadro de di\u00e1logo personalizado. El c\u00f3digo es el siguiente, y contiene las explicaciones necesarias.<\/p>\n<pre class=\"lang:java decode:true\">    public void showAlertForCreatingboard(String title, String message){\r\n        \/\/Creo un builder para construir un cuadro de dialogo personalizado\r\n        AlertDialog.Builder builder = new AlertDialog.Builder(this);\r\n        \/\/Si los parametros title y message no vienen vac\u00edos, los utilizo para mi cuadro\r\n        if (title != null) builder.setTitle(title);\r\n        if (message != null) builder.setMessage(message);\r\n        \/\/ Creo una vista usando el layout dialog_create_board\r\n        View viewInflated = LayoutInflater.from(this).inflate(R.layout.dialog_create_board, null);\r\n        \/\/ Asigno esa vista al builder\r\n        builder.setView(viewInflated);\r\n        final EditText input = (EditText) viewInflated.findViewById(R.id.editTextNewBoard);\r\n\r\n        \/\/ Tendremos un bot\u00f3n que dice Agregar y que al dale clic...\r\n        builder.setPositiveButton(\"Agregar\", new DialogInterface.OnClickListener() {\r\n            @Override\r\n            public void onClick(DialogInterface dialogInterface, int i) {\r\n                \/\/ ... extrae el texto escrito en el EditText llamado editTextNewboard\r\n                String boardName = input.getText().toString().trim();\r\n                \/\/ Si el usuario escribe algo, se utiliza para crear un tablero, si no, error.\r\n                if (boardName.length() &gt; 0)\r\n                    createNewBoard(boardName);\r\n                else\r\n                    Toast.makeText(getApplicationContext(), \"Debe escribir un nombre\", Toast.LENGTH_LONG).show();\r\n                \r\n            }\r\n        });\r\n        \/\/ Muestro el cuadro de dialogo creado.\r\n        AlertDialog dialog = builder.create();\r\n        dialog.show();\r\n    }\r\n<\/pre>\n<p>Como puedes observar, el c\u00f3digo anterior llama a otro m\u00e9todo llamado <em><strong>createNewBoard<\/strong><\/em> que es el que crear\u00e1 un \u201ctablero\u201d. Veamos a continuaci\u00f3n el c\u00f3digo que lleva \u00e9ste m\u00e9todo que tambi\u00e9n es parte de <strong>MainActivity<\/strong>.<\/p>\n<pre class=\"lang:java decode:true \">    private void createNewBoard(String boardName) {\r\n        realm.beginTransaction();\r\n        Board board = new Board(boardName);\r\n        realm.copyToRealm(board);\r\n        realm.commitTransaction();\r\n    }\r\n<\/pre>\n<p>El c\u00f3digo inicia una transacci\u00f3n (Consulta la secci\u00f3n de base de datos para conocer los aspectos te\u00f3ricos de una transacci\u00f3n). Despu\u00e9s, crea un nuevo tablero con el nombre que el usuario escribi\u00f3 en el EditText y confirma la transacci\u00f3n.<\/p>\n<p><span class=\"Apple-converted-space\">\u00a0<\/span>Ahora debemos lograr que el <strong>Floating Action Button<\/strong> llame a nuestro cuadro de di\u00e1logo personalizado (consulta el art\u00edculo <a href=\"http:\/\/naps.com.mx\/blog\/crear-un-floating-action-button-en-android\/\">C\u00f3mo crear un Floating Action Button<\/a>). Para ello haremos lo siguiente:<\/p>\n<p>Agrega las siguientes variables a la clase <strong>MainActivity<\/strong>:<\/p>\n<pre class=\"lang:java decode:true \">    private Realm realm;\r\n    private FloatingActionButton fab;\r\n    private ListView listview;\r\n    private BoardAdapter adapter;\r\n    private RealmResults&lt;Board&gt; boards;<\/pre>\n<p>\u00c9stas objetos son necesarios para: acceder a Realm, acceder al bot\u00f3n flotante, acceder a la listview. (La clase BoardAdapter la crearemos enseguida y se utiliza para poder mostrar los registros que se van guardando en la Base de Datos).<\/p>\n<p>Agrega el siguiente c\u00f3digo a <strong>onCreate<\/strong><\/p>\n<pre class=\"lang:java decode:true \">        \/\/ Creo una instancia de Realm\r\n        realm = Realm.getDefaultInstance();\r\n        \/\/ Acceder a los datos de la BD\r\n        boards = realm.where(Board.class).findAll();\r\n        \/\/ Creo un adaptador que contiene la lista de boards y el layout dise\u00f1ado\r\n        adapter = new BoardAdapter(this, boards, R.layout.list_view_board_item);\r\n        \/\/ Agrego el adaptador al listview\r\n        listview = (ListView) findViewById(R.id.listView);\r\n        listview.setAdapter(adapter);\r\n        \/\/ Enlazo el Floating Action Button (FAB) del layout\r\n        fab = (FloatingActionButton)findViewById(R.id.fabAddBoard);\r\n        \/\/ Agrego un listener para cuando se haga clic en el FAB\r\n        fab.setOnClickListener(new View.OnClickListener() {\r\n            @Override\r\n            public void onClick(View view) {\r\n                showAlertForCreatingboard(\"Agrega un nuevo tablero\", \"Escribe un nombre para el nuevo tablero\");\r\n            }\r\n        });\r\n<\/pre>\n<p>Para poder mostrar los registros que se van guardando, necesitamos dos cosas: crear un layout para los items \u00abtablero\u00bb y crear un adaptador que <em>infle<\/em>\u00a0el listview.<\/p>\n<h2>Mostrar datos en Realm<\/h2>\n<p>En primer lugar deberemos crear un layout que utilizar\u00e1 cada uno de los items \u00abtablero\u00bb.<\/p>\n<h2>Crear un layout para los items \u201ctablero\u201d<\/h2>\n<p>Crea un nuevo layout con el nombre list_view_board_item.xml.<\/p>\n<p>El c\u00f3digo de este layout ser\u00e1 como el siguiente:<\/p>\n<pre class=\"lang:xhtml decode:true \">&lt;?xml version=\"1.0\" encoding=\"utf-8\"?&gt;\r\n&lt;LinearLayout\r\n    xmlns:android=\"http:\/\/schemas.android.com\/apk\/res\/android\"\r\n    xmlns:tools=\"http:\/\/schemas.android.com\/tools\"\r\n    android:layout_width=\"match_parent\"\r\n    android:background=\"@color\/colorAccent\"\r\n    android:layout_height=\"74dp\"\r\n    android:orientation=\"vertical\"\r\n    android:paddingLeft=\"15dp\"\r\n    android:paddingRight=\"15dp\"&gt;\r\n\r\n\r\n    &lt;LinearLayout\r\n        android:layout_width=\"match_parent\"\r\n        android:layout_height=\"60dp\"\r\n        android:gravity=\"center_vertical\"\r\n        android:orientation=\"horizontal\"\r\n        android:paddingTop=\"8dpb\"\r\n        &gt;\r\n\r\n        &lt;TextView\r\n            android:id=\"@+id\/textViewBoardTitle\"\r\n            android:layout_width=\"0dp\"\r\n            android:layout_height=\"wrap_content\"\r\n            android:layout_weight=\"0.8\"\r\n            android:text=\"TextView\"\r\n            android:textSize=\"18dp\"\/&gt;\r\n\r\n        &lt;TextView\r\n            android:id=\"@+id\/textViewBoardNotes\"\r\n            android:layout_width=\"0dp\"\r\n            android:layout_height=\"wrap_content\"\r\n            android:layout_weight=\"0.2\"\r\n            android:text=\"TextView\"\r\n            android:textSize=\"12dp\"\/&gt;\r\n\r\n\r\n    &lt;\/LinearLayout&gt;\r\n    &lt;TextView\r\n        android:id=\"@+id\/textViewBoardDate\"\r\n        android:layout_width=\"match_parent\"\r\n        android:layout_height=\"wrap_content\"\r\n        android:text=\"TextView\"\r\n        android:textSize=\"10dp\"\r\n        android:textStyle=\"italic\"\r\n        android:gravity=\"right\"\/&gt;\r\n&lt;\/LinearLayout&gt;<\/pre>\n<p>El layout debe tener una apariencia como la siguiente:<\/p>\n<div id=\"attachment_1690\" style=\"width: 728px\" class=\"wp-caption alignnone\"><a href=\"http:\/\/naps.com.mx\/blog\/wp-content\/uploads\/2018\/10\/07-layout-item.jpeg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-1690\" class=\"wp-image-1690 size-full\" title=\"Layout para mostrar datos en Realm\" src=\"http:\/\/naps.com.mx\/blog\/wp-content\/uploads\/2018\/10\/07-layout-item.jpeg\" alt=\"Layout para mostrar datos en Realm\" width=\"718\" height=\"222\" srcset=\"https:\/\/naps.com.mx\/blog\/wp-content\/uploads\/2018\/10\/07-layout-item.jpeg 718w, https:\/\/naps.com.mx\/blog\/wp-content\/uploads\/2018\/10\/07-layout-item-300x93.jpeg 300w\" sizes=\"auto, (max-width: 718px) 100vw, 718px\" \/><\/a><p id=\"caption-attachment-1690\" class=\"wp-caption-text\">Layout para mostrar datos en Realm<\/p><\/div>\n<p>Tendra 3 textview que mostrar\u00e1n: el nombre del tablero, la cantidad de notas que contiene y la fecha en que fue creado.<\/p>\n<p>&nbsp;<\/p>\n<p>Ahora crearemos un adaptador que har\u00e1 uso de un ViewHolder para mostrar los datos de la Base de Datos. (Si deseas saber qu\u00e9 es un ViewHolder consulta el art\u00edculo:\u00a0<a href=\"http:\/\/naps.com.mx\/blog\/optimizar-un-listview-usando-viewholder\/\">Optimizar un ListView usando ViewHolder)<\/a><\/p>\n<h2>Crear un adapter<\/h2>\n<p>Deber\u00e1s crear esta nueva clase de Java dentro de una carpeta <strong>Adapters<\/strong> \u00a0y llevar\u00e1 el nombre de <strong>BoardAdapter.java<\/strong>. El codigo ser\u00e1 como el siguiente:<\/p>\n<pre class=\"lang:java decode:true \">package com.example.gibgarcia.gibdata.adapters;\r\n\r\nimport android.content.Context;\r\nimport android.view.LayoutInflater;\r\nimport android.view.View;\r\nimport android.view.ViewGroup;\r\nimport android.widget.TextView;\r\nimport android.widget.BaseAdapter;\r\n\r\nimport com.example.gibgarcia.gibdata.R;\r\nimport com.example.gibgarcia.gibdata.models.Board;\r\n\r\nimport java.text.DateFormat;\r\nimport java.text.SimpleDateFormat;\r\nimport java.util.List;\r\n\r\n\/**\r\n * Created by gibgarcia on 31\/10\/18.\r\n *\/\r\n\r\npublic class BoardAdapter extends BaseAdapter {\r\n    Context context;\r\n    List&lt;Board&gt; list;\r\n    private int layout;\r\n\r\n    public BoardAdapter (Context context, List&lt;Board&gt; boards, int layout){\r\n        this.context = context;\r\n        this.list = boards;\r\n        this.layout = layout;\r\n    }\r\n\r\n    @Override\r\n    public int getCount(){\r\n        return list.size();\r\n    }\r\n\r\n    @Override\r\n    public Board getItem(int position){\r\n        return list.get(position);\r\n    }\r\n\r\n    @Override\r\n    public long getItemId(int id){\r\n        return id;\r\n    }\r\n    @Override\r\n    public View getView (int position, View convertView, ViewGroup viewGroup){\r\n\r\n        ViewHolder vh;\r\n        if (convertView == null){\r\n            convertView = LayoutInflater.from(context).inflate(layout, null);\r\n            vh = new ViewHolder();\r\n            vh.title = (TextView) convertView.findViewById(R.id.textViewBoardTitle);\r\n            vh.notes = (TextView) convertView.findViewById(R.id.textViewBoardNotes);\r\n            vh.createdAt = (TextView) convertView.findViewById(R.id.textViewBoardDate);\r\n            convertView.setTag(vh);\r\n\r\n        }else{\r\n            vh = (ViewHolder) convertView.getTag();\r\n        }\r\n\r\n        Board board = list.get(position);\r\n        vh.title.setText(board.getTitle());\r\n        int numOfNotes = board.getNotes().size();\r\n        String textforNotes = (numOfNotes==1) ? numOfNotes+ \" Nota\" : numOfNotes+\" Notas\";\r\n        vh.notes.setText(textforNotes);\r\n        DateFormat df = new SimpleDateFormat(\"dd\/MM\/yyyy\");\r\n        String createdAt = df.format(board.getCreatedAt());\r\n        vh.createdAt.setText(createdAt);\r\n        return convertView;\r\n\r\n\r\n    }\r\n    public class ViewHolder{\r\n        TextView title;\r\n        TextView notes;\r\n        TextView createdAt;\r\n\r\n    }\r\n\r\n}\r\n<\/pre>\n<h2>Resultados<\/h2>\n<p>Nuestra aplicaci\u00f3n ya deber\u00eda crear, guardar y mostrar los datos guardados. En apariencia se ve de \u00e9sta forma (desear\u00e1s cambiar ese color, de seguro).<\/p>\n<div id=\"attachment_1692\" style=\"width: 458px\" class=\"wp-caption alignnone\"><a href=\"http:\/\/naps.com.mx\/blog\/wp-content\/uploads\/2018\/10\/08-board-guardado.jpeg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-1692\" class=\"wp-image-1692 size-full\" title=\"App que muestra datos en Realm\" src=\"http:\/\/naps.com.mx\/blog\/wp-content\/uploads\/2018\/10\/08-board-guardado.jpeg\" alt=\"App para mostrar datos en Realm\" width=\"448\" height=\"810\" srcset=\"https:\/\/naps.com.mx\/blog\/wp-content\/uploads\/2018\/10\/08-board-guardado.jpeg 448w, https:\/\/naps.com.mx\/blog\/wp-content\/uploads\/2018\/10\/08-board-guardado-166x300.jpeg 166w\" sizes=\"auto, (max-width: 448px) 100vw, 448px\" \/><\/a><p id=\"caption-attachment-1692\" class=\"wp-caption-text\">App que muestra datos en Realm<\/p><\/div>\n<p>&nbsp;<\/p>\n<p><span class=\"Apple-converted-space\">\u00a0 \u00a0 \u00a0 <\/span><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Creamos una aplicaci\u00f3n que permite agregar y mostrar datos en Realm (base de datos) para Android.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"amp_status":"","footnotes":""},"categories":[234],"tags":[198,235,243],"class_list":["post-1684","post","type-post","status-publish","format-standard","hentry","category-aplicaciones-moviles","tag-android","tag-desarrollo-de-aplicaciones-moviles","tag-realm"],"_links":{"self":[{"href":"https:\/\/naps.com.mx\/blog\/wp-json\/wp\/v2\/posts\/1684","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/naps.com.mx\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/naps.com.mx\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/naps.com.mx\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/naps.com.mx\/blog\/wp-json\/wp\/v2\/comments?post=1684"}],"version-history":[{"count":11,"href":"https:\/\/naps.com.mx\/blog\/wp-json\/wp\/v2\/posts\/1684\/revisions"}],"predecessor-version":[{"id":1716,"href":"https:\/\/naps.com.mx\/blog\/wp-json\/wp\/v2\/posts\/1684\/revisions\/1716"}],"wp:attachment":[{"href":"https:\/\/naps.com.mx\/blog\/wp-json\/wp\/v2\/media?parent=1684"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/naps.com.mx\/blog\/wp-json\/wp\/v2\/categories?post=1684"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/naps.com.mx\/blog\/wp-json\/wp\/v2\/tags?post=1684"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}