问题
Having figured out how to use the wait() and notify() in Java application to fetch some data from the Internet, I had to migrate that code into my Android application. As it turns out the code that would've worked in Java app would never had worked within my Android app even with attempts to make it multi-threaded (with Runnable and then ASyncTask). The problem seems that the Android app will hang after a call on Object.wait() and will never continue further.
The following is the code of the Java & Android classes:
Java
import java.util.Map;
import com.firebase.client.DataSnapshot;
import com.firebase.client.Firebase;
import com.firebase.client.FirebaseError;
import com.firebase.client.ValueEventListener;
public class Getter {
private String username = "jdk17";
private String userFullname;
private Object userObj = new Object();
public static void main(String[] args) {
System.out.println("Main");
String text;
Getter main = new Getter();
text = main.getString();
System.out.println("Main - Text = " + text);
}
public String getString() {
Firebase firebaseRef = new Firebase(
"https://demoandroid.firebaseio.com/user/username/" + username);
firebaseRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onCancelled(FirebaseError arg0) {
}
@Override
public void onDataChange(DataSnapshot snap) {
System.out.println("***********onDataChange()***********");
Object obj = snap.getValue();
userFullname = (String) ((Map) obj).get("fullname");
System.out.println("********* The text = " + userFullname);
synchronized (userObj) {
userObj.notify();
}
}
});
try {
synchronized (userObj) {
System.out.println("Calling wait()");
userObj.wait();
}
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("getString() returning text = " + userFullname);
return userFullname;
}
}
Android
package com.example.paabooking;
import java.util.Map;
import android.util.Log;
import com.firebase.client.DataSnapshot;
import com.firebase.client.Firebase;
import com.firebase.client.FirebaseError;
import com.firebase.client.ValueEventListener;
public class FirebaseHelper {
private final String TAG = "FirebaseHelper";
private String username = "jdk17";
private String userFullname;
private Object userObj = new Object();
public FirebaseHelper() {}
public String getString() {
Log.d(TAG, "getString()");
Firebase firebaseRef = new Firebase("https://demoandroid.firebaseio.com/user/username/" + username);
firebaseRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onCancelled(FirebaseError arg0) {Log.d(TAG, "cancelled.");}
@Override
public void onDataChange(DataSnapshot snap) {
Log.d(TAG, "***********onDataChange()***********");
// TODO Auto-generated method stub
Object obj = snap.getValue();
userFullname = (String)((Map)obj).get("fullname");
Log.d(TAG, "********* The text = " + userFullname);
synchronized(userObj) {
userObj.notify();
}
}
});
try {
synchronized (userObj) {
Log.d(TAG, "Calling wait()");
userObj.wait();
}
} catch (InterruptedException e1) {
e1.printStackTrace();
}
Log.d(TAG,"getString() returning text = " + userFullname);
return userFullname;
}
}
Console printout:Java
Main
Calling wait()
***********onDataChange()***********
********* The text = Tom Barry
getString() returning text = Tom Barry
Main - Text = Tom Barry
Console printout: Android
getString()
Calling wait()
Java Firebase Library - https://www.firebase.com/docs/java-quickstart.html
回答1:
I don't think that this is due to any differences (real or hypothetical) between wait/notify in Java and Android.
I think that the difference is explained by this quote from the Firebase page you linked to:
"By default, on Android, all callbacks are executed on the main thread. On other JVM targets, callbacks are executed on a new, separate thread. You can configure this behavior by providing your own EventTarget to the default Config used by the library.".
In the Android case, your main thread appears to be instantiating the Firebase object, adding the listener, and then calling wait()
. But wait()
is blocking the main thread ... so, of course the main thread is not in a position to accept the callback that would wake it up. Hence, everything freezes.
The 2nd sentence of the quote seems to suggest the way to solve the problem.
I've never come across Firebase before, let alone tried to use it. This is just based on my superficial reading of the documentation and your code.
来源:https://stackoverflow.com/questions/22784168/java-wait-notify-vs-android-wait-notify