Ver mensagens sem resposta | Ver tópicos ativos Hoje é 08 Dez 2019, 19:58



Responder Tópico  [ 5 Mensagens ] 
 Implementando o padrão MVC no Android, usando a API Fragment 
Autor Mensagem
Google employee
Google employee

Data de registro: 17 Jul 2011, 11:55
Mensagens: 2657
Localização: São Paulo
Mensagem Implementando o padrão MVC no Android, usando a API Fragment
Imagem

Comecei este tutorial com o objetivo de mostrar um exemplo de uso da API Fragments, algo simples sem grandes pretensões.

Depois acrescentei um exemplo de uso de um Singleton. Como essa classe poderia mais tarde ser usada concorrentemente (com Threads ou AsyncTasks) usei um modelo de Singleton thread-safe.

Para demonstrar a comunicação fragment-activity, adotei o modelo implementado via interface, conhecido como "listener". Coloquei as três formas mais comuns de usar esse padrão: Passar dados para a activity-host, consultar uma informação da activity-host e informar um evento ocorrido no fragment para que a activity-host possa tratá-lo.

Só estava faltando a comunicação activity-fragment, então incluí isso também no exemplo.

No final, acabei com um exemplo do padrão MVC em uma app android. Onde o M ficou por conta do Singleton, o C por conta das activities e o V com os fragments.

Também estou testando o uso da biblioteca de compatibilidade, o agora conhecido por Android Support Library.

Como não vou comentar o código por ser bem simples, vou dar uma visão geral do projeto.

O projeto ficou bem simples, apesar de implementar tudo que disse aí em cima, chamei-o de ListaDe, por pura falta de inspiração, mas dá uma verificada quantas listas você tem contato no dia a dia. É composto de duas telas, uma para entrar com os dados e outra um ListView.

Para mostrar o poder da possibilidade de reutilização de código usando fragments, coloquei três situações de uso do aplicativo:
-Large retrato - com dois fragments na vertical;
-Large paisagem - com dois fragments na horizontal;
-outros casos - um fragment por tela.

Observem que da maneira como foi implementado, toda a coordenação é exclusiva das activities (Controller), ela que atualiza os dados, ela que avisa que os dados foram alterados e ela que chama outra activity para trocar de tela.
Por outro lado, os fragments foram implementados de tal forma que ficassem desacoplados das activities, permitindo reutilização de código.

Aviso que só coloquei o básico, o essencial para facilitar o entendimento e deixar outros detalhes para quem desejar implementar.

Seguem os códigos:


string.xml


<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">ListaDe</string>
    <string name="action_settings">Settings</string>
    <string name="listaDe">ListaDe</string>
    <string name="digite">Digite</string>
    <string name="limpar">Limpar</string>
    <string name="salvar">Salvar</string>
    <string name="verlista">Ver lista</string>
    <string name="digite_dados">Por favor, informe os dados</string>
</resources>
 



layout\fragment.xml


<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >


    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" android:gravity="right|center_vertical"
        android:orientation="vertical" >


         <TextView
            android:id="@+id/listaDe"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:padding="10dp"
                android:textSize="48sp"
                android:text="@string/listaDe"
                android:gravity="center|center_vertical"
                 />

        <View
            android:layout_width="match_parent"
            android:layout_height="20dp"
             />

          <EditText
                android:id="@+id/linha"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:hint="@string/digite"
                android:imeOptions="actionDone" android:gravity="left"
                android:inputType="text"
                android:paddingRight="15dp" android:paddingTop="5dp" android:paddingBottom="5dp" />

         
        <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                 >

                <Button
                    android:id="@+id/verlista"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:text="@string/verlista" />

                <Button
                    android:id="@+id/limpar"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:text="@string/limpar" />

                <Button
                    android:id="@+id/salvar"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:text="@string/salvar" />


            </LinearLayout>

     </LinearLayout>

</ScrollView>
 



layout\activity1.xml


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:baselineAligned="false"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#ffffff"
    android:id="@+id/fragment_container1"
>

        <fragment class="br.com.agorandroid.listade.Fragment1"
            android:id="@+id/frag1"
            android:layout_width="fill_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:layout_margin="5dp"
        />


</LinearLayout>
 



layout\activity2.xml


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:baselineAligned="false"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#ffffff"
    android:id="@+id/fragment_container2"
>

        <fragment class="br.com.agorandroid.listade.Fragment2"
            android:id="@+id/frag2"
            android:layout_width="fill_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:layout_margin="5dp"
        />


</LinearLayout>
 



layout-large-land\activity1.xml


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:baselineAligned="false"
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#ffffff"
    android:id="@+id/fragment_container3"
>

        <fragment class="br.com.agorandroid.listade.Fragment1"
            android:id="@+id/frag1"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:layout_margin="5dp"
        />

        <fragment class="br.com.agorandroid.listade.Fragment2"
            android:id="@+id/frag2"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:layout_margin="5dp"
        />

</LinearLayout>
 



layout-large-port\activity1.xml


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:baselineAligned="false"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#ffffff"
    android:id="@+id/fragment_container5"
>

        <fragment class="br.com.agorandroid.listade.Fragment1"
            android:id="@+id/frag1"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:layout_margin="5dp"
        />

        <fragment class="br.com.agorandroid.listade.Fragment2"
            android:id="@+id/frag2"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:layout_margin="5dp"
        />

</LinearLayout>
 



MySingleton.java


/*
 * -----------------------------------------------------------------------------
 * "THE DONATE LICENSE" (Revision 1):
 * A H Gusukuma escreveu este tutorial.
 * Qualquer material sob essa licença é de uso livre, se for para publicar em
 * qualquer meio basta manter esta notificação.
 * Os exemplos de código não tem garantia de nenhum tipo, o uso é de sua inteira
 * responsabilidade.
 *
 * Se lhe foi útil e se desejar e tiver condições de contribuir, faça uma doação
 * para o Portal Android.
 *
 * -----------------------------------------------------------------------------
 */

package br.com.agorandroid.listade;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public final class MySingleton {
   
     private static MySingleton instance = new MySingleton();
     
        private final ArrayList<String> lista;
        private final List<String> unmodifiableList;
   
        private MySingleton() {
            lista = new ArrayList<String>();
            unmodifiableList = Collections.unmodifiableList(lista);
        }
       
        public static MySingleton getInstance () {
            return instance;
        }

        public synchronized void addItem(String item) {
            lista.add(item);
        }

        public synchronized void clearLista() {
            lista.clear();
        }
        public synchronized List<String> getLista() {
            return unmodifiableList;
        }
    }
 



Fragment1.java


/*
 * -----------------------------------------------------------------------------
 * "THE DONATE LICENSE" (Revision 1):
 * A H Gusukuma escreveu este tutorial.
 * Qualquer material sob essa licença é de uso livre, se for para publicar em
 * qualquer meio basta manter esta notificação.
 * Os exemplos de código não tem garantia de nenhum tipo, o uso é de sua inteira
 * responsabilidade.
 *
 * Se lhe foi útil e se desejar e tiver condições de contribuir, faça uma doação
 * para o Portal Android.
 *
 * -----------------------------------------------------------------------------
 */

package br.com.agorandroid.listade;


import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class Fragment1 extends Fragment {
   
    OnItemInputtedListener mCallback1;
    public interface OnItemInputtedListener {
        public void onItemInputted(String linha);
     }
    OnFragment2SelectedListener mCallback2;
    public interface OnFragment2SelectedListener {
        public void onFragment2Selected();
        public boolean isSinglePane();
     }
    EditText linha;
    Button btLimpar, btSalvar, btVerlista;
       
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mCallback1 = (OnItemInputtedListener) activity;
        } catch (ClassCastException e) {
                throw new ClassCastException(activity.toString()
                        + " implemente OnItemInputtedListener na Activity-host");
        }
        try {
            mCallback2 = (OnFragment2SelectedListener) activity;
        } catch (ClassCastException e) {
                throw new ClassCastException(activity.toString()
                        + " implemente OnFragment@SelectedListener na Activity-host");
        }
    }
   
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment1, container, false);
       
        linha = (EditText) view.findViewById(R.id.linha);
       
        btVerlista = (Button) view.findViewById(R.id.verlista);
        btVerlista.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
                    verLista();
                }
            });

        btLimpar = (Button) view.findViewById(R.id.limpar);
        btLimpar.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
                    limpar();
                }
            });
       
        btSalvar = (Button) view.findViewById(R.id.salvar);
        btSalvar.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
                    salvar();
                    limpar();
                }
            });
       
        return view;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        if (!mCallback2.isSinglePane()) {
            btVerlista.setVisibility(View.GONE);
        }
    }
   
   
    private void verLista() {

        mCallback2.onFragment2Selected();
       
    }
    private void salvar() {
        String line = linha.getText().toString().trim();
        if (line.equals("")) {
                    Toast.makeText(getActivity(), this.getString(R.string.digite_dados), Toast.LENGTH_LONG).show();
                    return;
        }
        mCallback1.onItemInputted(line);
       
    }
   
    private void limpar() {
        linha.setText("");
        linha.requestFocus();
    }
}

 



Fragment2.java


/*
 * -----------------------------------------------------------------------------
 * "THE DONATE LICENSE" (Revision 1):
 * A H Gusukuma escreveu este tutorial.
 * Qualquer material sob essa licença é de uso livre, se for para publicar em
 * qualquer meio basta manter esta notificação.
 * Os exemplos de código não tem garantia de nenhum tipo, o uso é de sua inteira
 * responsabilidade.
 *
 * Se lhe foi útil e se desejar e tiver condições de contribuir, faça uma doação
 * para o Portal Android.
 *
 * -----------------------------------------------------------------------------
 */

package br.com.agorandroid.listade;

import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.widget.ArrayAdapter;

public class Fragment2 extends ListFragment {


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

         int layout = android.R.layout.simple_list_item_1;
         MySingleton dados = MySingleton.getInstance();
         setListAdapter(new ArrayAdapter<String>(getActivity(), layout, dados.getLista()));
    }

    @SuppressWarnings("unchecked")
    public void dataSetHasChanged() {
        ((ArrayAdapter<String>) getListAdapter()).notifyDataSetChanged();
    }
   
}

 



Activity1.java


/*
 * -----------------------------------------------------------------------------
 * "THE DONATE LICENSE" (Revision 1):
 * A H Gusukuma escreveu este tutorial.
 * Qualquer material sob essa licença é de uso livre, se for para publicar em
 * qualquer meio basta manter esta notificação.
 * Os exemplos de código não tem garantia de nenhum tipo, o uso é de sua inteira
 * responsabilidade.
 *
 * Se lhe foi útil e se desejar e tiver condições de contribuir, faça uma doação
 * para o Portal Android.
 *
 * -----------------------------------------------------------------------------
 */

package br.com.agorandroid.listade;

import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;

public class Activity1 extends FragmentActivity   implements
            Fragment1.OnItemInputtedListener, Fragment1.OnFragment2SelectedListener {
    MySingleton singleton = MySingleton.getInstance();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity1);
    }

    @Override
    public void onItemInputted(String linha) {
        singleton.addItem(linha);
       
        // se for == null, significa que a tela tem 2 fragments
        if (findViewById(R.id.fragment_container1)==null) {    
            Fragment2 frag = (Fragment2) getSupportFragmentManager().findFragmentById(R.id.frag2);
            if (frag != null) {
                frag.dataSetHasChanged();
            }
        }
    }

    @Override
    public void onFragment2Selected() {
        Intent intent = new Intent(this, Activity2.class);
        startActivity(intent);
    }

    @Override
    public boolean isSinglePane() {
        // se for == null, significa que a tela tem 2 fragments
        if (findViewById(R.id.fragment_container1) == null) {
            return false;
        } else {
            return true;
        }
    }

}
 



Activity2.java


/*
 * -----------------------------------------------------------------------------
 * "THE DONATE LICENSE" (Revision 1):
 * A H Gusukuma escreveu este tutorial.
 * Qualquer material sob essa licença é de uso livre, se for para publicar em
 * qualquer meio basta manter esta notificação.
 * Os exemplos de código não tem garantia de nenhum tipo, o uso é de sua inteira
 * responsabilidade.
 *
 * Se lhe foi útil e se desejar e tiver condições de contribuir, faça uma doação
 * para o Portal Android.
 *
 * -----------------------------------------------------------------------------
 */

package br.com.agorandroid.listade;

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;

public class Activity2 extends FragmentActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity2);
    }
}
 


Rodando num tablet posição retrato:

Imagem

Rodando num tablet posição paisagem:

Imagem

Rodando num celular Fragment1:

Imagem

Rodando num celular Fragment2:

Imagem

Pessoal, não comentei o código mas estejam à vontade para comentar, solicitar uma ou outra explicação.

Bons códigos!

_________________
Abraços
___________
Novo App: CalcMat - Calculadora de materiais para concreto
Blog: Agorandroid - sobre programação Android
Twitter: @Agorandroid
___________
Campanha: Facilite sua vida e a dos outros usuários
Cuide do ciclo de vida do seu tópico:
no onCreate(): seja claro, se necessário poste o código e as mensagens de erro.
no onClick(): responda às sugestões.
no onStop(): evite "ninguém?", "alguém?", etc. Procure acrescentar alguma nova informação.
no onDestroy(): resolvido o assunto, poste imediatamente a solução, e, coloque no título do primeiro post [Resolvido].


21 Abr 2013, 20:00
Perfil
What is a Activity?
What is a Activity?

Data de registro: 11 Fev 2014, 10:38
Mensagens: 12
Mensagem Re: Implementando o padrão MVC no Android, usando a API Frag
A H Gusukuma,

Muito show, cara. Parabéns.
Implementei e deu tudo certo.

Vou implementar no meu app.
Aí sim irá aparecer as dúvidas rss.

^^

_________________
Vida longa e Próspera!


21 Mar 2014, 13:52
Perfil
Google employee
Google employee

Data de registro: 17 Jul 2011, 11:55
Mensagens: 2657
Localização: São Paulo
Mensagem Re: Implementando o padrão MVC no Android, usando a API Frag
raphaRezzi escreveu:
A H Gusukuma,

Muito show, cara. Parabéns.
Implementei e deu tudo certo.

Vou implementar no meu app.
Aí sim irá aparecer as dúvidas rss.

^^


Obrigado, qualquer coisa posta aqui no Portal Android.

_________________
Abraços
___________
Novo App: CalcMat - Calculadora de materiais para concreto
Blog: Agorandroid - sobre programação Android
Twitter: @Agorandroid
___________
Campanha: Facilite sua vida e a dos outros usuários
Cuide do ciclo de vida do seu tópico:
no onCreate(): seja claro, se necessário poste o código e as mensagens de erro.
no onClick(): responda às sugestões.
no onStop(): evite "ninguém?", "alguém?", etc. Procure acrescentar alguma nova informação.
no onDestroy(): resolvido o assunto, poste imediatamente a solução, e, coloque no título do primeiro post [Resolvido].


25 Mar 2014, 09:21
Perfil
What is Android?
What is Android?

Data de registro: 17 Jul 2014, 17:42
Mensagens: 5
Mensagem Re: Implementando o padrão MVC no Android, usando a API Frag
Desculpe, teria como postar o código? A final, você mandou SS do código já implementado..

ou acho que este assunto ficou um pouco extenso ou eu não encontrei ainda códigos iniciais feitos por você ai estou um pouco perdido na explicação. Se puder por tags ou links de referência ajudaria aos "novatos" de plantão no fórum.

Obrigado!


18 Jul 2014, 17:09
Perfil
Google employee
Google employee

Data de registro: 17 Jul 2011, 11:55
Mensagens: 2657
Localização: São Paulo
Mensagem Re: Implementando o padrão MVC no Android, usando a API Frag
carlosgalves escreveu:
Desculpe, teria como postar o código? A final, você mandou SS do código já implementado..

ou acho que este assunto ficou um pouco extenso ou eu não encontrei ainda códigos iniciais feitos por você ai estou um pouco perdido na explicação. Se puder por tags ou links de referência ajudaria aos "novatos" de plantão no fórum.

Obrigado!

Não entendi. Os códigos estão postados.
Mas, esse não é um assunto para iniciantes no Android.

_________________
Abraços
___________
Novo App: CalcMat - Calculadora de materiais para concreto
Blog: Agorandroid - sobre programação Android
Twitter: @Agorandroid
___________
Campanha: Facilite sua vida e a dos outros usuários
Cuide do ciclo de vida do seu tópico:
no onCreate(): seja claro, se necessário poste o código e as mensagens de erro.
no onClick(): responda às sugestões.
no onStop(): evite "ninguém?", "alguém?", etc. Procure acrescentar alguma nova informação.
no onDestroy(): resolvido o assunto, poste imediatamente a solução, e, coloque no título do primeiro post [Resolvido].


18 Jul 2014, 20:21
Perfil
Mostrar mensagens anteriores:  Organizar por  
Responder Tópico   [ 5 Mensagens ] 

Quem está online

Usuários vendo este fórum: Adeja, AdrianoMM, alexandreizumi, alexsander.miranda, allone, Andre, andrelom, andreluzz, andrewort, apoena, Arthas, attomweb, Avelino Mateus Neto, b7web, Bass, baudamix, Berbert, billsombrio, blurkness, BMaia, breko, brpiassa, bruno.abd, capo, Carla Luz, carlos rodrigues, Cassius, Catapan, celson, Chewbacca, Cleiton, Clone Trooper, cyzko, Damiani Oliveira, Danilo Dias, dariosena, Darth Plagueis, Darth Sidious, deborazb, diogeneskelsen, DroidBot, eduzortea, erikopa, erissi, euguns, fabricioLeonard, Felipe, fernando neves, fraga, francismarconcini, frankmendes, free_w3000, freina, Gabriel Laet, glmsistemas, grandebaro, guitarro17, gutem25, gutomilani, hebert, Igor_M, itsN, jacksonst, jairo, Jar Jar Binks, jeanbr07, jmarcos14, JMurray, jorgecardoso, Josinhaz, Jota, juliherms, Juniorvs, klausenner, konos, kusanaguy, leanderdulac, Legiao, lkunta, lucastgomes, luizfilipe, luizneto79, Lúcio Zanette, marcelosv, marcow, martins, MauNunes, maurofjr, maurosilva, Maxtremus, mayahaslinger, MBetioli, mrkensley, MSPRAFAEL, nakahara, navegador, NeruLL, Nice, nivaldo, nullPointer, Nute Gunray, Padawan, paulanegreiros, Paulo, paulovaz, pererinha, pgbatera, pxcx, rafael.cioban, regeriob2br, renanpl, ricardo, robertofonte, robsonoracle, rodrigo_corinthians, rodrigo_mg, romuloff, rotmeil, rsl_master, schiroky, Silvio Vaz, srmoreira, taluna, tiago, tonylock, Topeca, valaszek, vaniuz, Vector, VIEIRIX, Vinicius, viniciusluiz, wil, XPTO, zeantonio, zorieuq e 1 visitante


Você não pode criar novos tópicos neste fórum
Você não pode responder tópicos neste fórum
Você não pode editar suas mensagens neste fórum
Você não pode excluir suas mensagens neste fórum
Você não pode enviar anexos neste fórum

Procurar por:
cron

© 2007 - 2016 Portal Android - Comunidade de Desenvolvedores Android

Estamos no Linkedin    Siga-nos no twitter


Powered by phpBB - Hospedado por Bemobi