我的应用程序中有2个回调函数,其中一个需要另一个函数的结果,因此我希望它们异步执行。场景是这样的:
我用FirebaseInstanceId.getInstance().getInstanceId()
获取设备的令牌。这是第一个回调。
当我拥有令牌时,我将其用于访问Firebase Realtime DB以获取用户的数据。这是第二个回调。
在当前解决方案中,我将AsyncTask
与Semaphore
函数中的doInBackground
结合使用,如下所示:
private class AsyncOp extends AsyncTask<Void, Void, String> {
@Override
protected String doInBackground(Void... voids) {
final Semaphore semaphore = new Semaphore(0);
FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(new OnSuccessListener<InstanceIdResult>() {
@Override
public void onSuccess(InstanceIdResult instanceIdResult) {
token = instanceIdResult.getToken();
JSONObject requestObject = new JSONObject();
try {
requestObject.put("token", token);
semaphore.release();
} catch (JSONException e) {
Log.e(TAG_MAINACTIVITY, token);
semaphore.release();
}
JsonObjectRequest req = new JsonObjectRequest(Request.Method.POST, REQUEST_URL + "token",
requestObject, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
Log.i(TAG_MAINACTIVITY, "Token saved successfully");
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG_MAINACTIVITY, "Failed to save token - " + error);
}
});
_queue.add(req);
}
});
try {
semaphore.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
return token;
}
@Override
protected void onPostExecute(String token) {
getUser(token);
}
}
public void getUser(String token) {
db.child("users").child(token).addListenerForSingleValueEvent(new ValueEventListener() {
@SuppressLint("SetTextI18n")
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
if (!dataSnapshot.exists()) {
// Navigate to fragment where new users can sign up:
goToSignup();
} else {
currentUser = dataSnapshot.getValue(User.class);
assert currentUser != null;
updateHeadline(currentUser.getName()); // Update UI to display the user's name
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
Log.d(TAG_MAINACTIVITY, databaseError.getMessage());
}
});
}
并且在我的OnCreate
中,我执行如下操作:
_queue = Volley.newRequestQueue(this);
AsyncOp getToken = new AsyncOp();
getToken.execute();
效果很好,但我忍不住想念这里的要点,并且有一个更好的解决方案可以使用。我已经搜索了处理类似问题的其他StackOverflow问题,并找到了一些建议,但是我却纠结于尝试实施它们,这对整个苦难来说还是很新的(实际上是我的第一个“真实”项目)。我尝试寻找可以像Promise
一样工作的东西,但发现Future
,但是由于它不起作用,我可能做得不好。这是唯一对我有用的解决方案,除了简单地将getUser(token)
嵌套在第一个回调中。因此,如果您有任何对我有用的想法,我将很高兴听到。
合并成:
FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(new OnSuccessListener<InstanceIdResult>() {
@Override
public void onSuccess(InstanceIdResult instanceIdResult) {
token = instanceIdResult.getToken();
JSONObject requestObject = new JSONObject();
requestObject.put("token", token);
JsonObjectRequest req = new JsonObjectRequest(Request.Method.POST, REQUEST_URL + "token",
requestObject, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
Log.i(TAG_MAINACTIVITY, "Token saved successfully");
getUser(token);
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG_MAINACTIVITY, "Failed to save token - " + error);
}
});
_queue.add(req);
}
});