Ver mensagens sem resposta | Ver tópicos ativos Hoje é 18 Nov 2017, 07:28



Responder Tópico  [ 13 Mensagens ] 
 Android: acesso SqLite multi-thread 
Autor Mensagem
Google employee
Google employee

Data de registro: 17 Jul 2011, 11:55
Mensagens: 2657
Localização: São Paulo
Mensagem Android: acesso SqLite multi-thread
Estava acompanhando um colega com problemas com acesso concorrente ao banco de dados SqLite, ele conseguiu resolver os problemas com as informações de um artigo que encontrara no blog de um desenvolvedor Android de nome Dmytro Danylyk.
Como, quem me lê, sabem, sou particularmente interessado em processamento concorrente, então fiz algumas pequenas adaptações à solução do Dmytro para fazer alguns testes.
Para fazer acesso concorrente no Android é necessário que se faça com uma única conexão ao db, para isso deve-se usar apenas um objeto SQLiteOpenHelper, fiz a classe DatabaseController, um singleton (olha o padrão aqui novamente!), para controlar o acesso ao banco de dados.
Como é para ser compartilhado por diversas threads todos os métodos são sincronizados. O controle do número de acessos é controlado pelo atributo mOpenCounter, para somente fechar o banco quando for a última solicitação de close, para evitar fechar o banco enquanto uma outra thread ainda esteja em processamento.

Para os meus testes, fiz um pequeno banco de mensagens, os objetos salvos no banco estão no RowTab.java e fiz um TesteDbAdapter.java para usar o DatabaseController. Para obter uma referência ao controlador usa-se: "DatabaseController.getInstance();". E para inicialização do SQLiteOpenHelper coloquei o método "setDatabaseHelper(contexto);". Para ter uma referência ao SQLiteDatabase usa-se o método open().
Notem que a abertura do db somente vai ocorrer no primeiro open, e quando o db for criado, esta operação pode ser demorada, por isso, sempre é recomendado executar o primeiro open (caso seja o caso) numa thread diferente da main thread do Android.
A activity é bem simples e direta, no onCreate chamo o método ativaThread() e nela inicio quatro threads para usar o banco concorrentemente.

Seguem os códigos:

DatabaseController.java
package br.agorandroid.testedb;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

/**
 * @author A H Gusukuma
 *
 *         agorandroid.blogspot.com
 */

public class DatabaseController {
    private static DatabaseController instance;
    private int mOpenCounter = 0;
    private DatabaseHelper mDatabaseHelper;
   
    private DatabaseController() {
        // singleton
    }
   
    public static synchronized DatabaseController getInstance() {
        if (instance == null) {
            instance = new DatabaseController();
        }
        return instance;
    }
   
    public synchronized void setDatabaseHelper(Context context) {
        if (mDatabaseHelper == null) {
            mDatabaseHelper = new DatabaseHelper(context.getApplicationContext());
        }
    }
   
    public synchronized SQLiteDatabase openDatabase() {
        if (mDatabaseHelper == null) {
            throw new IllegalStateException(DatabaseController.class.getSimpleName() +
                    " DatabaseHelper is null.");
        }
        mOpenCounter++;
        return mDatabaseHelper.getWritableDatabase();
    }
   
    public synchronized void closeDatabase() {
        if (mDatabaseHelper == null) {
            throw new IllegalStateException(DatabaseController.class.getSimpleName() +
                    " DatabaseHelper is null.");
        }
        mOpenCounter--;
        if(mOpenCounter == 0) {
            mDatabaseHelper.close();
        }
    }
   
    private class DatabaseHelper extends SQLiteOpenHelper {

        private static final String DATABASE_NAME = "testedb.db";
        public static final String DATABASE_TABLE = "tabteste";
        private static final int DATABASE_VERSION = 2;
       
        private static final String DATABASE_CREATE =
                "create table " + DATABASE_TABLE +
                " (" + RowTab.Columns._ID + " integer primary key autoincrement, " +
                RowTab.Columns.ENABLED + " integer, " +
                RowTab.Columns.MESSAGE + " text);";
       
        public DatabaseHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL(DATABASE_CREATE);
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE);
            onCreate(db);
        }
    }
   
}
 


RowTab.java
package br.agorandroid.testedb;

import android.database.Cursor;

/**
 * @author A H Gusukuma
 *
 *         agorandroid.blogspot.com
 */

public class RowTab {

    public static class Columns {
   
        public static final String _ID = "_id";
        public static final String ENABLED = "enabled";
        public static final String MESSAGE = "message";

        public static final String WHERE_ENABLED = ENABLED + "=1";
        public static final String WHERE_DISABLED = ENABLED + "=0";
        public static final String SORT_ORDER = MESSAGE + " ASC";
        public static final String[] ROWTAB_COLUNAS = { _ID, ENABLED, MESSAGE };

        public static final int ROWTAB_ID_INDEX = 0;
        public static final int ROWTAB_ENABLED_INDEX = 1;
        public static final int ROWTAB_MESSAGE_INDEX = 2;
    }
   
    private long        id;
    private boolean    enabled;
    private String     message;
   
    public RowTab() {
        id = -1;
        enabled = true;
        message = null;
    }

    public RowTab(Cursor cur) {
        id = cur.getLong(Columns.ROWTAB_ID_INDEX);
        enabled = cur.getInt(Columns.ROWTAB_ENABLED_INDEX) == 1;
        message = cur.getString(Columns.ROWTAB_MESSAGE_INDEX);
    }
   
    public long getId() {
        return id;
    }

    public boolean isEnabled() {
        return enabled;
    }

    public String  getMessage() {
        return message;
    }

    public void setId(long id1) {
        id = id1;
    }

    public void setEnabled(boolean b) {
        enabled = b;
    }

    public void setMessage(String m) {
        message = m;
    }
       
}
 


TesteDbAdapter.java
package br.agorandroid.testedb;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

/**
 * @author A H Gusukuma
 *
 *         agorandroid.blogspot.com
 */

public class TesteDbAdapter {
    private DatabaseController mDatabaseController;
    private SQLiteDatabase mDb;

    public TesteDbAdapter(Context ctx) {
        mDatabaseController = DatabaseController.getInstance();
        mDatabaseController.setDatabaseHelper(ctx);
    }
   
    public void open() {
        mDb = mDatabaseController.openDatabase();
    }
   
    public void close() {
        mDatabaseController.closeDatabase();
    }
   
    public long insertRowTab(RowTab rowTab) {
        ContentValues cv = createContenValues(rowTab);
        return mDb.insert(DatabaseHelper.DATABASE_TABLE, null, cv);
    }
   
    public boolean deleteRowTab(long rowId) {
        return mDb.delete(DatabaseHelper.DATABASE_TABLE, RowTab.Columns._ID + "=" + rowId, null) > 0;
    }
   
    public Cursor selectRowTabAll() {
        return mDb.query(DatabaseHelper.DATABASE_TABLE, RowTab.Columns.ROWTAB_COLUNAS, null, null, null, null, RowTab.Columns.SORT_ORDER);
    }
   
    public boolean updateRowTab(RowTab rowTab) {
        ContentValues cv = createContenValues(rowTab);
        return mDb.update(DatabaseHelper.DATABASE_TABLE, cv, RowTab.Columns._ID + "=" + rowTab.getId(), null)>0;
    }
   
    private static ContentValues createContenValues(RowTab rowTab) {
        ContentValues cv = new ContentValues(2);
        cv.put(RowTab.Columns.ENABLED, rowTab.isEnabled() ? 1 : 0);
        cv.put(RowTab.Columns.MESSAGE, rowTab.getMessage());
       
        return cv;
    }
}
 


MainActivity.java
package br.agorandroid.testedb;

import android.os.Bundle;
import android.os.Handler;
import android.app.Activity;
import android.app.ProgressDialog;
import android.database.Cursor;
import android.util.Log;
import android.view.Menu;
import android.widget.Toast;

public class MainActivity extends Activity {
    MyThread mThread1, mThread2, mThread3, mThread4;
    ProgressDialog mDialog;
    Handler mHandler;
   
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ativaThread();

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
    @Override
    public void onDestroy() {
        TesteDbAdapter mDb1 = new TesteDbAdapter(MainActivity.this);
        mDb1.open();
        Cursor mCursor = mDb1.selectRowTabAll();
        Log.i("Teste", "thread name " + Thread.currentThread().getName() + " rows = " + mCursor.getCount());
        mCursor.close();
        mDb1.close();
        super.onDestroy();
    }
   
    private void ativaThread() {
        Log.i("Teste", "thread name " + Thread.currentThread().getName());
        mDialog = ProgressDialog.show(this, "Aguarde", "Processando...", false, false);
        mHandler = new Handler();
        mThread1 = new MyThread(10);
        mThread2 = new MyThread(10);
        mThread3 = new MyThread(10);
        mThread4 = new MyThread(10);
        mThread1.start();
        mThread2.start();
        mThread3.start();
        mThread4.start();
    }
       
 
    private class MyThread extends Thread {
        private int numLoops;
       
        public MyThread(int loops) {
            numLoops = loops;
        }
       
        public void run() {
            fazerAlgoDemorado();
            final String nomeThread = Thread.currentThread().getName();
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    Log.i("Teste", "thread name " + nomeThread);
                    mDialog.dismiss();
                    Toast.makeText(MainActivity.this, "Fim da Thread", Toast.LENGTH_LONG).show();
                }
            });
        }
       
        private void fazerAlgoDemorado() {
            Log.i("Teste", "thread name " + Thread.currentThread().getName());
            int i = 0;
            TesteDbAdapter mDb1 = new TesteDbAdapter(MainActivity.this);
            mDb1.open();
            
            do {
                i++;
                RowTab rowTab = new RowTab();
                rowTab.setMessage("teste de db sqlite");
                long rowId = mDb1.insertRowTab(rowTab);
                Log.i("Teste", Thread.currentThread().getName()+" RowId "+ rowId);
            } while (i<numLoops);
            mDb1.close();
        }
    }
}
 


Para checar, após o fim das threads, aguarde os Toasts terminarem, aperte o back e no onDestroy loga o número de linhas da tabela. Testem aí, funciona!

Abraços.

PS: segue o link do Dmytro https://github.com/dmytrodanylyk/dmytro ... 0Access.md

_________________
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].


28 Jun 2014, 10:43
Perfil
Android application
Android application

Data de registro: 11 Abr 2014, 16:18
Mensagens: 60
Mensagem Re: Android: acesso SqLite multi-thread
Parabéns pelo tópico. Estava procurando algo do tipo.
+1


28 Jun 2014, 14:11
Perfil
Google employee
Google employee

Data de registro: 28 Jun 2012, 19:13
Mensagens: 1308
Localização: Itaperuna-RJ
Mensagem Re: Android: acesso SqLite multi-thread
Boa! Ficou quase um sistema distribuido esse codigo ae hehehe!

_________________
Powell


30 Jun 2014, 23:41
Perfil
Google employee
Google employee

Data de registro: 17 Jul 2011, 11:55
Mensagens: 2657
Localização: São Paulo
Mensagem Re: Android: acesso SqLite multi-thread
fabzon escreveu:
Parabéns pelo tópico. Estava procurando algo do tipo.
+1

raphaelframos escreveu:
Boa! Ficou quase um sistema distribuido esse codigo ae hehehe!

Obrigado!
Considero que a parte da documentação Android mais carente é a sobre banco de dados.

_________________
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].


01 Jul 2014, 12:23
Perfil
Application Life Cycle
Application Life Cycle
Avatar de usuário

Data de registro: 08 Ago 2011, 16:21
Mensagens: 226
Localização: Ponta Grossa - PR / Blumenau - SC
Mensagem Re: Android: acesso SqLite multi-thread
Fala Gusukuma beleza??

Tu ja testou acesso multiplo durante uma transacao? Tem que deixar o pessoal avisado sobre isso ehhe, pois com o lifecycle do android + transacao e acesso multiplo precisa de umas configuracoes de acesso WAL no sqlite que possui um comportamento peculiar hheehhe

_________________
Eu te ajudei? Quer agradecer? Não precisa nem postar no tópico agradecendo, você me ajudaria muito entrando em um dos meus blogs, comentando e compartilhando os posts nas redes sociais.
Blog: Cedulio Cezar- Tutoriais e dicas voltados para o desenvolvimento de softwares em Java e Android.
Blog: Pedreiros do Software - Tutoriais sobre Java, Android, Banco de dados, Arquitetura, JSF.

App: ThinkTwice - Aplicativo que auxilia no aprendizado de outros idiomas.
App: InstantGilGomes- Aplicativo de humor com bordões clássicos do ilustre Gil Gomes.


01 Jul 2014, 15:45
Perfil
Google employee
Google employee

Data de registro: 17 Jul 2011, 11:55
Mensagens: 2657
Localização: São Paulo
Mensagem Re: Android: acesso SqLite multi-thread
ByddU escreveu:
Fala Gusukuma beleza??

Tu ja testou acesso multiplo durante uma transacao? Tem que deixar o pessoal avisado sobre isso ehhe, pois com o lifecycle do android + transacao e acesso multiplo precisa de umas configuracoes de acesso WAL no sqlite que possui um comportamento peculiar hheehhe


Tudo bem.
Ainda não testei, não.
Posta alguma coisa aqui no fórum.

_________________
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].


01 Jul 2014, 17:39
Perfil
Google employee
Google employee

Data de registro: 17 Jul 2011, 11:55
Mensagens: 2657
Localização: São Paulo
Mensagem Re: Android: acesso SqLite multi-thread
A H Gusukuma escreveu:
ByddU escreveu:
Fala Gusukuma beleza??

Tu ja testou acesso multiplo durante uma transacao? Tem que deixar o pessoal avisado sobre isso ehhe, pois com o lifecycle do android + transacao e acesso multiplo precisa de umas configuracoes de acesso WAL no sqlite que possui um comportamento peculiar hheehhe


Tudo bem.
Ainda não testei, não.
Posta alguma coisa aqui no fórum.


Testei com transação, e funcionou de acordo com o esperado.
Como eu esperava o comportamento equivalente a um "select ... for update", o tradicional de transação me atendeu. Não funcionaria usando WAL (write-ahead logging) devido à necessidade do bloqueio.

_________________
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].


02 Jul 2014, 13:00
Perfil
Application Life Cycle
Application Life Cycle
Avatar de usuário

Data de registro: 08 Ago 2011, 16:21
Mensagens: 226
Localização: Ponta Grossa - PR / Blumenau - SC
Mensagem Re: Android: acesso SqLite multi-thread
Interessante. Até onde eu tinha visto se você realizasse acesso concorrente durante uma transacao daria problema, disponibiliza o projeto com os sources se possível. To afimde testar a validade desses dados hehehe. Pois se funcionar vai ser muito util hehehe.
Abraço.

_________________
Eu te ajudei? Quer agradecer? Não precisa nem postar no tópico agradecendo, você me ajudaria muito entrando em um dos meus blogs, comentando e compartilhando os posts nas redes sociais.
Blog: Cedulio Cezar- Tutoriais e dicas voltados para o desenvolvimento de softwares em Java e Android.
Blog: Pedreiros do Software - Tutoriais sobre Java, Android, Banco de dados, Arquitetura, JSF.

App: ThinkTwice - Aplicativo que auxilia no aprendizado de outros idiomas.
App: InstantGilGomes- Aplicativo de humor com bordões clássicos do ilustre Gil Gomes.


02 Jul 2014, 13:17
Perfil
Google employee
Google employee

Data de registro: 17 Jul 2011, 11:55
Mensagens: 2657
Localização: São Paulo
Mensagem Re: Android: acesso SqLite multi-thread
ByddU escreveu:
Interessante. Até onde eu tinha visto se você realizasse acesso concorrente durante uma transacao daria problema, disponibiliza o projeto com os sources se possível. To afimde testar a validade desses dados hehehe. Pois se funcionar vai ser muito util hehehe.
Abraço.

Na verdade, acesso concorrente não é trivial, precisa uma boa análise para implementar.
Usei a forma padrão:
  db.beginTransaction();
   try {
     ... // acesso/update
     db.setTransactionSuccessful();
   } finally {
     db.endTransaction();
   }

_________________
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].


02 Jul 2014, 13:50
Perfil
Application Life Cycle
Application Life Cycle
Avatar de usuário

Data de registro: 08 Ago 2011, 16:21
Mensagens: 226
Localização: Ponta Grossa - PR / Blumenau - SC
Mensagem Re: Android: acesso SqLite multi-thread
Faça o teste com threads separadas.

Por exemplo ao iniciar sua tela crie uma thread (Thread1) e dentro dela crie uma transacao e insira alguns valores, enquanto esta a Thread1 estiver rodando inicie uma segunda thread (Thread2), dentro da Thread2 faça uma busca e veja se os dados inseridos estão contidos no resultado.

O problema em si é ter uma transacao aberta e as outras threads utilizarem essa conexao com transacao. Sei que isso não seria algo muito interessante, visto que a idéia de transacao eh ser algo rapido executando um bloco que nao se mantem em execucao por muito tempo, mas acredito que pessaos vao querer fazer principalmente se não utilizarem algum padrao de arquitetura onde cada fragmento vai buscar os seus dados.

Até onde eu sei isso da problema hehehe.

Abraço.


PS.: Essa parte de tutoriais e dicas é muito chato de postar, vocês precisam aprovar a resposta, enquanto isso eu não posso editar a resposta caso tenha errado alguma coisa kkk

_________________
Eu te ajudei? Quer agradecer? Não precisa nem postar no tópico agradecendo, você me ajudaria muito entrando em um dos meus blogs, comentando e compartilhando os posts nas redes sociais.
Blog: Cedulio Cezar- Tutoriais e dicas voltados para o desenvolvimento de softwares em Java e Android.
Blog: Pedreiros do Software - Tutoriais sobre Java, Android, Banco de dados, Arquitetura, JSF.

App: ThinkTwice - Aplicativo que auxilia no aprendizado de outros idiomas.
App: InstantGilGomes- Aplicativo de humor com bordões clássicos do ilustre Gil Gomes.


02 Jul 2014, 15:56
Perfil
Google employee
Google employee

Data de registro: 17 Jul 2011, 11:55
Mensagens: 2657
Localização: São Paulo
Mensagem Re: Android: acesso SqLite multi-thread
ByddU escreveu:
Faça o teste com threads separadas.

Por exemplo ao iniciar sua tela crie uma thread (Thread1) e dentro dela crie uma transacao e insira alguns valores, enquanto esta a Thread1 estiver rodando inicie uma segunda thread (Thread2), dentro da Thread2 faça uma busca e veja se os dados inseridos estão contidos no resultado.

O problema em si é ter uma transacao aberta e as outras threads utilizarem essa conexao com transacao. Sei que isso não seria algo muito interessante, visto que a idéia de transacao eh ser algo rapido executando um bloco que nao se mantem em execucao por muito tempo, mas acredito que pessaos vao querer fazer principalmente se não utilizarem algum padrao de arquitetura onde cada fragmento vai buscar os seus dados.

Até onde eu sei isso da problema hehehe.

Abraço.


PS.: Essa parte de tutoriais e dicas é muito chato de postar, vocês precisam aprovar a resposta, enquanto isso eu não posso editar a resposta caso tenha errado alguma coisa kkk


É preciso fazer uma definição do comportamento desejado de cada thread, inclusive se é desejável ou possível acesso concorrente. Em algumas situações, quando a precisão da informação é crucial, o melhor é serializar o acesso.

Quanto à dificuldade de postagem, abre um tópico para discussão nos fóruns normais.

_________________
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].


03 Jul 2014, 11:55
Perfil
What is Android?
What is Android?

Data de registro: 15 Set 2014, 13:57
Mensagens: 2
Mensagem Re: Android: acesso SqLite multi-thread
Não teria como fazer o mesmo exemplo com o ormLite não ?
Estou tendo problemas com isso mas no meu caso uso o ormlite.


19 Jan 2015, 12:44
Perfil
Google employee
Google employee

Data de registro: 17 Jul 2011, 11:55
Mensagens: 2657
Localização: São Paulo
Mensagem Re: Android: acesso SqLite multi-thread
robertorp escreveu:
Não teria como fazer o mesmo exemplo com o ormLite não ?
Estou tendo problemas com isso mas no meu caso uso o ormlite.


Olá, Roberto.

Eu não uso o ormLite, mas não deve ser muito complicado fazer o mesmo com ele, não.

_________________
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 Jan 2015, 12:06
Perfil
Mostrar mensagens anteriores:  Organizar por  
Responder Tópico   [ 13 Mensagens ] 

Quem está online

Usuários vendo este fórum: adelar, ademilson, alberto, alexmarcolongo, alsimoes, anaguerra, Anakin Skywalker, Androidthebest, Ask Jeeves, Avelino Mateus Neto, berchielli, Biel, bigr ecreio, BTalhadas, btleandro, Captain Typho, Carla Luz, carlosavasconcelos, Cassius, Chefe Nass, cleber, compto, Corneta, Crazy_Droid, Damiani Oliveira, David, denisfln, Diego Otani, dmd, dobau, Douglas Siviotti, drjunior, e-azuos, edsonel, Eduardo - Brasil, eduardo.ali, EduardoYC, Erik Patekoski, fabielp, felipecomp19, Fernando Cardia, ffardo, Flavio, fmakula, fraga, FVB, geovanebg, glmsistemas, Gnomo, Google Android, Guilherme Cobain, gusrp, hebert, Igor_M, infonlinebr, ismavolk, itsN, j-menezes, jacard, Jalerson, Jar Jar Binks, jasn, julianofischer, juliomar, jwv, klausenner, kristopher, lalaine, Legiao, leofernandesmo, LordElfo, lucasmadeira, LucasNascimento, luciano.sml, lucianoalves, luizcarlosvb, Luke Skywalker, Luna, Lúcio Zanette, mapis, marcelocastellani, MarceloMC, MauNunes, mauriciobreide, maurofjr, mayahaslinger, mcroft, mirelli, mravel, msmdark, mtomazzi, navegador, Newton Barbosa, niloleite, nina.rm, Obi-Wan Kenobi, Padawan, pchofard, pfsmorigo, pgbatera, pgsnit, phpower1, piantino, pmzara, pyrobit, Rafael, rafaelmonoh, raulcca, regeriob2br, renanpl, ricardoogliari, roberto caceres, Robson Florentino, RodReis, romualdo, romuloigor, Roney dos Santos, rubens_olv, Rufino, Samuka, sandro, ScoobyGB, sergio, SERGIO RODRIGUES, Shinigami, SirBagda, skcratch, soulmachine, Stryder, suissa, tchou, tonylock, Vania, vanmars, viniciusgoncalves, viniciusluiz, washington, weber, Webnet, williamcmello, wingdoido, Wookiees, Wryel, YaCy, yeltsinlima, zenden1503, 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