wait until firebase retrieves data

后端 未结 9 1089
不思量自难忘°
不思量自难忘° 2020-11-29 08:33

I want to build a method that returns a child value in FireBase. I tried to do something like this:

public String getMessage(){

           


        
相关标签:
9条回答
  • 2020-11-29 08:51

    Firebase usually takes about 1-2 seconds to load the data.

    So keeping that in mind you can add a new thread using Handler, to make the system wait for say, 2 Seconds and then use the value retrieved from the Database.

    Till then you can display a Loading Dialog box to the user which can be closed once the data is retrieved.

     Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    {
                        loadingDialog.dismiss();//dismiss the dialog box once data is retreived
                        Toast.makeText(Act_NewHome.this, "Not enough players online right now!", Toast.LENGTH_SHORT).show();
    tvUserName.setText(u_name);
                    }
                }
            }, 2000);// 2000 milliseconds = 2seconds
    
    0 讨论(0)
  • 2020-11-29 08:52

    Don't use Firebase as functions that return values - it goes against it's asynchronous nature.

    Plan code structure that allows Firebase to perform it's task and then within the closure (block) go to the next step.

    In your code, for example, change the function to not return anything and within the onDataChange, as the last line call the next function to update your UI.

    0 讨论(0)
  • 2020-11-29 08:56

    I'll leave this here to help anyone who faces the same problem as me. @Tirupati Singh code looks nice but I wrote my answer below his why it didn't work for me. Using Atomic type worked -

    public AtomicInteger getMessage(){
            final AtomicBoolean done = new AtomicBoolean(false);
            final AtomicInteger message1 = new AtomicInteger(0);
    
            //assuming you have already called firebase initialization code for admin sdk, android etc
           DatabaseReference root = FirebaseDatabase.getInstance().getReference("server");
           root.child("MessagesOnLaunch").child("Message").addListenerForSingleValueEvent(new ValueEventListener() {
    
            public void onDataChange(DataSnapshot dataSnapshot) {
                message1.set((Integer) dataSnapshot.getValue()); 
                done.set(true);
            }
    
            public void onCancelled(DatabaseError error) {
                // TODO Auto-generated method stub
    
            }
        });
        while (!done.get());
    
        return message1;
    }
    

    Note the function can only return message type Integer. I couldn't get it to work for String as no Atomic type for String. Hope this helps!

    0 讨论(0)
  • 2020-11-29 09:01

    Sorry to be a little late to this party but rather than have firebase return a value you could set up an observer / view model, then when you run your async firebase function the onData method is called from this you would update your view models data which then triggers its onDataChanged method which you can then update your layout from

    0 讨论(0)
  • 2020-11-29 09:02

    You can use CountDownLatch. This is how you can use it.

    public String getMessage(){
       CountDownLatch done = new CountDownLatch(1);
       final String message[] = {null}; 
       root.child("MessagesOnLaunch").child("Message").addListenerForSingleValueEvent(new ValueEventListener() {
    
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            message[0] = (String) dataSnapshot.getValue();
            System.out.println("worked");
            done.countDown();
        }
    
        @Override
        public void onCancelled(FirebaseError firebaseError) {
            System.out.println("failed"+firebaseError.getMessage());
        }
    });
    
    try {
        done.await(); //it will wait till the response is received from firebase.
    } catch(InterruptedException e) {
        e.printStackTrace();
    }
    return message[0];
    }
    
    0 讨论(0)
  • 2020-11-29 09:03

    You can follow this link https://youtu.be/LVaIArVY52U

    Firebase database is quite slow when retrieving the data so to make the application wait for the process to complete you can follow this

    Create a new class Ex. Firebasedata.java and extent it with Application and add put this code in the OnCreate sections

    public class Firebasedata extends Application {
        @Override
        public void onCreate() {
            FirebaseDatabase.getInstance().setPersistenceEnabled(true);
            super.onCreate();
        }
    }
    

    declare the java class in the manifests

     <application
            android:name=".Firebasedata"  <------
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
         ...
         ...
        </application>
    

    Then go back to the class where you want to get the data and create a dialog with this code

        ProgressDialog TempDialog;
        CountDownTimer mCountDownTimer;
        int i=0;
    
            TempDialog = new ProgressDialog(MainActivity.this);
            TempDialog.setMessage("Please wait...");
            TempDialog.setCancelable(false);
            TempDialog.setProgress(i);
            TempDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
            TempDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.GRAY));
    
     TempDialog.show();
            mCountDownTimer = new CountDownTimer(2000, 1000)
            {
                public void onTick(long millisUntilFinished)
                {
                    TempDialog.setMessage("Please wait..");
                }
    
                public void onFinish()
                {
                    TempDialog.dismiss();
                    //Your action like intents are placed here
    
                }
            }.start();
    

    You can look into the link above and get a better idea

    0 讨论(0)
提交回复
热议问题