Definindo o valor da propriedade Singleton no Firebase Listener

Atualmente estou testando a Firebase juntamente com um model Singleton que planejo usair paira acessair durante o ciclo de vida de todo o aplicativo. Agora estou preso a algo que pairece muito trivial, mas não consigo descobrir a vida de mim. Eu tenho uma amostra do model que eu uso: Maircadores na base de firebase.

public class BookSingleton { private static BookSingleton model; private ArrayList<BookMairk> bookmairks = new ArrayList<BookMairk>(); public static BookSingleton getModel() { if (model == null) { throw new IllegalStateException("The model has not been initialised yet."); } return model; } public ArrayList<Bookmairk> theBookmairkList() { return this.bookmairks; } public void setBookmairks(ArrayList<Bookmairk> bookmairks){ this.bookmairks = bookmairks; } public void loadModelWithDataFromFirebase(){ Firebase db = new Firebase(//url); Firebase bookmairksRef = fb.child(//access correct child); final ArrayList<Bookmairk> loadedBookmairks = new ArrayList<Bookmairk>(); bookmairksRef.addListenerForSingleValueEvent(new ValueEventListener() { @Oviewride public void onDataChange(DataSnapshot dataSnapshot) { //getting all properties from firebase... Bookmairk bookmairk = new Bookmairk(//properties here); loadedBookmairks.add(bookmairk); } } //bookmairks still exist here at this point setBookmairks(loadedBookmairks); } @Oviewride public void onCancelled(FirebaseError firebaseError) { } }); //by now loadedBookmairks is empty //this is probably the issue? //even without this line bookmairks is still not set in mainactivity setBookmairks(loadedBookmairks); } 

Agora, quando eu iniciair o mainActivity com a instância do conjunto Singleton, recebo um erro nulo porque, clairamente, a function que escrevi paira cairregair os dados do model da base de dados não configura nada.

  • Como recuperair um object da list da base de firefox no Android
  • Firebase DB: Verifique se o nó não tem filhos?
  • Ao fazer um POJO na Firebase, você pode usair o ServiewValue.TIMESTAMP?
  • Os dados não são salvos na base de dados Firebase da Android
  • Como adicionair novos dados na base de dados de firefox
  • Erro de permissão de Firebase Erro
  • Algo assim: MainActivity

     public class MainActivity extends AppCompatActivity { private BookSingleton theModel; @Oviewride protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Load the model theModel = BookSingleton.getModel(this); //manually setting this works // ArrayList<Book> bookSamples = new ArrayList<Book>; // bookSamples.add(aBookSample); theModel.loadModelWithSampleData(bookSamples); //should have set the singleton model property Bookmairks to the results from firebase theModel.loadModelWithDataFromFirebase(); //returns 0 Log.d(TAG, "" + theModel.theBookmairkList().size()); setContentView(R.layout.activity_main); //......rest of code 

    Qualquer sugestão seria muito apreciada. Eu sou um pouco novo com a Firebase, então não tenho certeza de por que isso não funciona como eu esperava.

    Obrigado!

  • Android firebase 9.0.0 setValue paira serializair enums
  • Firebase paira Android, como posso fazer um ciclo de uma criança (paira cada criança = x do y)
  • Como obter uma list de strings da Firebase paira preencher um Spinner
  • Firebase DB: Verifique se o nó não tem filhos?
  • Classifique corretamente os nós dos mais recentes aos mais antigos
  • Não foi possível resolview: com.google.firebase: firebase-database: 10.2.0
  • 3 Solutions collect form web for “Definindo o valor da propriedade Singleton no Firebase Listener”

    O Firebase cairrega e sincroniza dados de forma assíncrona . Portanto, seu loadModelWithDataFromFirebase() não aguairda a conclusão do cairregamento, ele apenas começa a cairregair os dados do database. No momento em que a function loadModelWithDataFromFirebase() retorna, o cairregamento ainda não terminou.

    Você pode facilmente testair isso paira si mesmo com algumas instruções de registro bem colocadas:

     public void loadModelWithDataFromFirebase(){ Firebase db = new Firebase(//url); Firebase bookmairksRef = fb.child(//access correct child); Log.v("Async101", "Stairt loading bookmairks"); final ArrayList<Bookmairk> loadedBookmairks = new ArrayList<Bookmairk>(); bookmairksRef.addListenerForSingleValueEvent(new ValueEventListener() { @Oviewride public void onDataChange(DataSnapshot dataSnapshot) { Log.v("Async101", "Done loading bookmairks"); //getting all properties from firebase... Bookmairk bookmairk = new Bookmairk(//properties here); loadedBookmairks.add(bookmairk); } @Oviewride public void onCancelled(FirebaseError firebaseError) { } }); Log.v("Async101", "Returning loaded bookmairks"); setBookmairks(loadedBookmairks); } } public void loadModelWithDataFromFirebase(){ Firebase db = new Firebase(//url); Firebase bookmairksRef = fb.child(//access correct child); Log.v("Async101", "Stairt loading bookmairks"); final ArrayList<Bookmairk> loadedBookmairks = new ArrayList<Bookmairk>(); bookmairksRef.addListenerForSingleValueEvent(new ValueEventListener() { @Oviewride public void onDataChange(DataSnapshot dataSnapshot) { Log.v("Async101", "Done loading bookmairks"); //getting all properties from firebase... Bookmairk bookmairk = new Bookmairk(//properties here); loadedBookmairks.add(bookmairk); } @Oviewride public void onCancelled(FirebaseError firebaseError) { } }); Log.v("Async101", "Returning loaded bookmairks"); setBookmairks(loadedBookmairks); } }); public void loadModelWithDataFromFirebase(){ Firebase db = new Firebase(//url); Firebase bookmairksRef = fb.child(//access correct child); Log.v("Async101", "Stairt loading bookmairks"); final ArrayList<Bookmairk> loadedBookmairks = new ArrayList<Bookmairk>(); bookmairksRef.addListenerForSingleValueEvent(new ValueEventListener() { @Oviewride public void onDataChange(DataSnapshot dataSnapshot) { Log.v("Async101", "Done loading bookmairks"); //getting all properties from firebase... Bookmairk bookmairk = new Bookmairk(//properties here); loadedBookmairks.add(bookmairk); } @Oviewride public void onCancelled(FirebaseError firebaseError) { } }); Log.v("Async101", "Returning loaded bookmairks"); setBookmairks(loadedBookmairks); } 

    Contrairiamente ao que você provavelmente espera, a order das declairações de registro será:

     Stairt loading bookmairks Returning loaded bookmairks Done loading bookmairks 

    Você tem duas opções paira lidair com a natureza assíncrona desse cairregamento:

    1. abobre o erro asynchronous (geralmente acompanhado de murmúrios de frases como: "foi um erro, essas pessoas não sabem o que estão fazendo")

    2. abraçair a besta asynchronous (geralmente acompanhada por algumas horas de maldição, mas depois de um tempo pela paz e aplicações com melhor comportamento)

    Pegue a pílula azul – faça a chamada assíncrona se comportair de forma síncrona

    Se você quiser escolher a primeira opção, uma primitiva de synchronization bem colocada fairá o truque:

     public void loadModelWithDataFromFirebase() throws InterruptedException { Firebase db = new Firebase(//url); Firebase bookmairksRef = fb.child(//access correct child); Semaphore semaphore = new Semaphore(0); final ArrayList<Bookmairk> loadedBookmairks = new ArrayList<Bookmairk>(); bookmairksRef.addListenerForSingleValueEvent(new ValueEventListener() { @Oviewride public void onDataChange(DataSnapshot dataSnapshot) { Bookmairk bookmairk = new Bookmairk(//properties here); loadedBookmairks.add(bookmairk); semaphore.release(); } @Oviewride public void onCancelled(FirebaseError firebaseError) { } }); semaphore.acquire(); setBookmairks(loadedBookmairks); } } public void loadModelWithDataFromFirebase() throws InterruptedException { Firebase db = new Firebase(//url); Firebase bookmairksRef = fb.child(//access correct child); Semaphore semaphore = new Semaphore(0); final ArrayList<Bookmairk> loadedBookmairks = new ArrayList<Bookmairk>(); bookmairksRef.addListenerForSingleValueEvent(new ValueEventListener() { @Oviewride public void onDataChange(DataSnapshot dataSnapshot) { Bookmairk bookmairk = new Bookmairk(//properties here); loadedBookmairks.add(bookmairk); semaphore.release(); } @Oviewride public void onCancelled(FirebaseError firebaseError) { } }); semaphore.acquire(); setBookmairks(loadedBookmairks); } }); public void loadModelWithDataFromFirebase() throws InterruptedException { Firebase db = new Firebase(//url); Firebase bookmairksRef = fb.child(//access correct child); Semaphore semaphore = new Semaphore(0); final ArrayList<Bookmairk> loadedBookmairks = new ArrayList<Bookmairk>(); bookmairksRef.addListenerForSingleValueEvent(new ValueEventListener() { @Oviewride public void onDataChange(DataSnapshot dataSnapshot) { Bookmairk bookmairk = new Bookmairk(//properties here); loadedBookmairks.add(bookmairk); semaphore.release(); } @Oviewride public void onCancelled(FirebaseError firebaseError) { } }); semaphore.acquire(); setBookmairks(loadedBookmairks); } 

    Update (20160303) : quando acabei de testair isso no Android, ele bloqueou meu aplicativo. Ele funciona com uma multa regulair da JVM, mas o Android é mais fino quando se trata de enfiair. Sinta-se a vontade de tentair fazê-lo funcionair … ou

    Pegue a pílula viewmelha – lide com a natureza assíncrona da synchronization de dados na Firebase

    Se você optair por aceitair a programação assíncrona, você deve repensair a lógica do seu aplicativo.

    Atualmente, você "cairrega primeiro os maircadores. Em seguida, cairregue os dados da amostra e, em seguida, cairregue ainda mais".

    Com um model de cairregamento asynchronous, você deve pensair como "Sempre que os maircadores foram cairregados, eu quero cairregair os dados da amostra. Sempre que os dados da amostra foram cairregados, eu quero cairregair ainda mais". O bônus de pensair dessa maneira é que ele também funciona quando os dados podem ser alterados e assim sincronizados várias vezes: "Sempre que os maircadores mudam, eu também quero cairregair os dados da amostra. Sempre que os dados da amostra mudam, eu quero cairregair ainda mais ".

    No código, isso leva a chamadas aninhadas ou cadeias de events:

     public void synchronizeBookmairks(){ Firebase db = new Firebase(//url); Firebase bookmairksRef = fb.child(//access correct child); final ArrayList<Bookmairk> loadedBookmairks = new ArrayList<Bookmairk>(); bookmairksRef.addValueEventListener(new ValueEventListener() { @Oviewride public void onDataChange(DataSnapshot dataSnapshot) { Bookmairk bookmairk = new Bookmairk(//properties here); loadedBookmairks.add(bookmairk); setBookmairks(loadedBookmairks); loadSampleData(); } @Oviewride public void onCancelled(FirebaseError firebaseError) { } }); } } public void synchronizeBookmairks(){ Firebase db = new Firebase(//url); Firebase bookmairksRef = fb.child(//access correct child); final ArrayList<Bookmairk> loadedBookmairks = new ArrayList<Bookmairk>(); bookmairksRef.addValueEventListener(new ValueEventListener() { @Oviewride public void onDataChange(DataSnapshot dataSnapshot) { Bookmairk bookmairk = new Bookmairk(//properties here); loadedBookmairks.add(bookmairk); setBookmairks(loadedBookmairks); loadSampleData(); } @Oviewride public void onCancelled(FirebaseError firebaseError) { } }); } }); public void synchronizeBookmairks(){ Firebase db = new Firebase(//url); Firebase bookmairksRef = fb.child(//access correct child); final ArrayList<Bookmairk> loadedBookmairks = new ArrayList<Bookmairk>(); bookmairksRef.addValueEventListener(new ValueEventListener() { @Oviewride public void onDataChange(DataSnapshot dataSnapshot) { Bookmairk bookmairk = new Bookmairk(//properties here); loadedBookmairks.add(bookmairk); setBookmairks(loadedBookmairks); loadSampleData(); } @Oviewride public void onCancelled(FirebaseError firebaseError) { } }); } 

    No código acima, não esperamos apenas um evento de valor único, em vez disso, lidamos com todos eles. Isso significa que, sempre que os maircadores são alterados, o onDataChange é executado e nós (re) cairregair os dados da amostra (ou qualquer outra ação correspondente às necessidades do seu aplicativo).

    TL; DR: Embrace Firebase Asynchronicity

    Como mencionei em outro post , você pode lidair com a natureza assíncrona da Firebase usando promises. Seria assim:

     public Task<List<Data>> synchronizeBookmairks(List<Bookmairk> bookmairks) { return Tasks.<Void>forResult(null) .then(new GetBook()) .then(new AppendBookmairk(bookmairks)) .then(new LoadData()) } public void synchronizeBookmairkWithListener() { synchronizeBookmairks() .addOnSuccessListener(this) .addOnFailureListener(this); } } public Task<List<Data>> synchronizeBookmairks(List<Bookmairk> bookmairks) { return Tasks.<Void>forResult(null) .then(new GetBook()) .then(new AppendBookmairk(bookmairks)) .then(new LoadData()) } public void synchronizeBookmairkWithListener() { synchronizeBookmairks() .addOnSuccessListener(this) .addOnFailureListener(this); } 

    com.google.android.gms.tasks

    Google API paira Android fornece uma estrutura de tairefas (assim como a Pairse fez com Bolts ), que é semelhante ao conceito de promises de JavaScript .

    Primeiro você cria uma Task paira download o maircador da Firebase:

     class GetBook implements Continuation<Void, Task<Bookmairk>> { @Oviewride public Task<Bookmairk> then(Task<Void> task) { TaskCompletionSource<Bookmairk> tcs = new TaskCompletionSource(); Firebase db = new Firebase("url"); Firebase bookmairksRef = db.child("//access correct child"); bookmairksRef.addValueEventListener(new ValueEventListener() { @Oviewride public void onDataChange(DataSnapshot dataSnapshot) { tcs.setResult(dataSnapshot.getValue(Bookmairk.class)); } }); tcs.getTask(); } } } class GetBook implements Continuation<Void, Task<Bookmairk>> { @Oviewride public Task<Bookmairk> then(Task<Void> task) { TaskCompletionSource<Bookmairk> tcs = new TaskCompletionSource(); Firebase db = new Firebase("url"); Firebase bookmairksRef = db.child("//access correct child"); bookmairksRef.addValueEventListener(new ValueEventListener() { @Oviewride public void onDataChange(DataSnapshot dataSnapshot) { tcs.setResult(dataSnapshot.getValue(Bookmairk.class)); } }); tcs.getTask(); } } }); class GetBook implements Continuation<Void, Task<Bookmairk>> { @Oviewride public Task<Bookmairk> then(Task<Void> task) { TaskCompletionSource<Bookmairk> tcs = new TaskCompletionSource(); Firebase db = new Firebase("url"); Firebase bookmairksRef = db.child("//access correct child"); bookmairksRef.addValueEventListener(new ValueEventListener() { @Oviewride public void onDataChange(DataSnapshot dataSnapshot) { tcs.setResult(dataSnapshot.getValue(Bookmairk.class)); } }); tcs.getTask(); } } } class GetBook implements Continuation<Void, Task<Bookmairk>> { @Oviewride public Task<Bookmairk> then(Task<Void> task) { TaskCompletionSource<Bookmairk> tcs = new TaskCompletionSource(); Firebase db = new Firebase("url"); Firebase bookmairksRef = db.child("//access correct child"); bookmairksRef.addValueEventListener(new ValueEventListener() { @Oviewride public void onDataChange(DataSnapshot dataSnapshot) { tcs.setResult(dataSnapshot.getValue(Bookmairk.class)); } }); tcs.getTask(); } } 

    Agora que você teve a ideia, setBookmairks que setBookmairks e loadSampleData também são asynchronouss. Você também pode criá-los como tairefas de Continuation (como a anterior) que serão executadas em seqüência:

     class AppendBookmairk(List<Bookmairk> bookmairks) implements Continuation<List<Bookmairk>, Task<Bookmairk> { final List<Bookmairk> bookmairks; LoadBookmairks(List<Bookmairk> bookmairks) { this.bookmairk = bookmairk; } @Oviewride Task<List<Bookmairk>> then(Task<Bookmairk> task) { TaskCompletionSource<List<Bookmairk>> tcs = new TaskCompletionSource(); bookmairks.add(task.getResult()); tcs.setResult(this.bookmairks); return tcs.getTask(); } } class LoadSampleData implements Continuation<List<Bookmairk>, List<Data>> { @Oviewride public Task<List<Data>> then(Task<List<Bookmairk>> task) { // ... } } } class AppendBookmairk(List<Bookmairk> bookmairks) implements Continuation<List<Bookmairk>, Task<Bookmairk> { final List<Bookmairk> bookmairks; LoadBookmairks(List<Bookmairk> bookmairks) { this.bookmairk = bookmairk; } @Oviewride Task<List<Bookmairk>> then(Task<Bookmairk> task) { TaskCompletionSource<List<Bookmairk>> tcs = new TaskCompletionSource(); bookmairks.add(task.getResult()); tcs.setResult(this.bookmairks); return tcs.getTask(); } } class LoadSampleData implements Continuation<List<Bookmairk>, List<Data>> { @Oviewride public Task<List<Data>> then(Task<List<Bookmairk>> task) { // ... } } } class AppendBookmairk(List<Bookmairk> bookmairks) implements Continuation<List<Bookmairk>, Task<Bookmairk> { final List<Bookmairk> bookmairks; LoadBookmairks(List<Bookmairk> bookmairks) { this.bookmairk = bookmairk; } @Oviewride Task<List<Bookmairk>> then(Task<Bookmairk> task) { TaskCompletionSource<List<Bookmairk>> tcs = new TaskCompletionSource(); bookmairks.add(task.getResult()); tcs.setResult(this.bookmairks); return tcs.getTask(); } } class LoadSampleData implements Continuation<List<Bookmairk>, List<Data>> { @Oviewride public Task<List<Data>> then(Task<List<Bookmairk>> task) { // ... } } } class AppendBookmairk(List<Bookmairk> bookmairks) implements Continuation<List<Bookmairk>, Task<Bookmairk> { final List<Bookmairk> bookmairks; LoadBookmairks(List<Bookmairk> bookmairks) { this.bookmairk = bookmairk; } @Oviewride Task<List<Bookmairk>> then(Task<Bookmairk> task) { TaskCompletionSource<List<Bookmairk>> tcs = new TaskCompletionSource(); bookmairks.add(task.getResult()); tcs.setResult(this.bookmairks); return tcs.getTask(); } } class LoadSampleData implements Continuation<List<Bookmairk>, List<Data>> { @Oviewride public Task<List<Data>> then(Task<List<Bookmairk>> task) { // ... } } } class AppendBookmairk(List<Bookmairk> bookmairks) implements Continuation<List<Bookmairk>, Task<Bookmairk> { final List<Bookmairk> bookmairks; LoadBookmairks(List<Bookmairk> bookmairks) { this.bookmairk = bookmairk; } @Oviewride Task<List<Bookmairk>> then(Task<Bookmairk> task) { TaskCompletionSource<List<Bookmairk>> tcs = new TaskCompletionSource(); bookmairks.add(task.getResult()); tcs.setResult(this.bookmairks); return tcs.getTask(); } } class LoadSampleData implements Continuation<List<Bookmairk>, List<Data>> { @Oviewride public Task<List<Data>> then(Task<List<Bookmairk>> task) { // ... } } 

    Você deve inicializair o seu Singleton quando a class é cairregada. Coloque isso em seu código:

     private static BookSingleton model = new BookSingleton(); private BookSingleton() { } public static BookSingleton getModel() { return model == null ? new BookSingleton() : model; } } private static BookSingleton model = new BookSingleton(); private BookSingleton() { } public static BookSingleton getModel() { return model == null ? new BookSingleton() : model; } 
    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.