我需要返回值uId
。我在onResponse()
函数内的第一个log语句中获得了正确的值。但是,对于return语句,它返回 null 。
我认为onResponse()正在另一个线程上运行。如果是这样,我该如何让 getNumber()函数等到 onResponse()函数完成执行。(就像thread.join())
还是有其他解决方案?
代码:
String uId;
public String getNumber() {
ApiInterface apiInterface = ApiClient.getClient().create(ApiInterface.class);
Call<TopLead> call = apiInterface.getTopLead();
call.enqueue(new Callback<TopLead>() {
@Override
public void onResponse(Call<TopLead> call, Response<TopLead> response) {
String phoneNumber;
TopLead topLead = response.body();
if (topLead != null) {
phoneNumber = topLead.getPhoneNumber().toString();
uId = topLead.getUId().toString();
//dispaly the correct value of uId
Log.i("PHONE NUMBER, UID", phoneNumber +", " + uId);
onCallCallback.showToast("Calling " + phoneNumber);
} else {
onCallCallback.showToast("Could not load phone number");
}
}
@Override
public void onFailure(Call<TopLead> call, Throwable t) {
t.printStackTrace();
}
});
//output: Return uid null
Log.i("Return"," uid" + uId);
return uId;
答案 0 :(得分:3)
您的方法执行异步请求。因此,“ return uId;”操作不会等到您的请求完成,因为它们位于不同的线程上。
我可以建议几种解决方案
使用接口回调
public void getNumber(MyCallback callback) {
...
phoneNumber = topLead.getPhoneNumber().toString();
callback.onDataGot(phoneNumber);
}
您的回调界面
public interface MyCallback {
void onDataGot(String number);
}
最后,调用方法
getNumber(new MyCallback() {
@Override
public void onDataGot(String number) {
// response
}
});
使用 Kotlin 时(我认为是时候使用Kotlin代替Java了:))
fun getNumber(onSuccess: (phone: String) -> Unit) {
phoneNumber = topLead.getPhoneNumber().toString()
onSuccess(phoneNumber)
}
调用方法
getNumber {
println("telephone $it")
}
答案 1 :(得分:0)
不返回值。因为AsyncTask是单独运行的,所以不在正常过程中运行。
因此,请使用参数创建一个方法,并将您的值传递给该方法。
答案 2 :(得分:0)
问题似乎是您想要uId而没有得到它。您的函数getNumber()
执行TopDown,但您发出的请求是异步的,在另一个线程上运行。因此,在您返回uId
时,uId
中没有任何值。在call.enqueue
所具有的回调中,我的意思是onResponse()
和onFailure()
,您无法在uId
中获得onFailure
,这很明显,但并不是很明显,您会在onResponse()中得到uId
。
从Javadoc进行改造:
onResponse
void onResponse(Call<T> call, Response<T> response)
为收到的HTTP响应调用。 注意:HTTP响应仍可能指示应用程序级失败,例如404或500。请调用Response.isSuccessful()以确定响应是否指示成功。
因此,在onResponse
中,您仍然需要放置一些代码以确保获得uId
,然后仅将其返回。并且不要直接返回uId
,而是将其设置为某个字符串(全局)并在确保其可用后访问它。
因此,请更改您的代码,例如::
public void getNumber() {
ApiInterface apiInterface = ApiClient.getClient().create(ApiInterface.class);
Call<TopLead> call = apiInterface.getTopLead();
call.enqueue(new Callback<TopLead>() {
@Override
public void onResponse(Call<TopLead> call, Response<TopLead> response) {
if(response.isSuccesful(){
String phoneNumber;
TopLead topLead = response.body();
if (topLead != null) {
phoneNumber = topLead.getPhoneNumber().toString();
uId = topLead.getUId().toString();
//dispaly the correct value of uId
Log.i("PHONE NUMBER, UID", phoneNumber +", " + uId);
onCallCallback.showToast("Calling " + phoneNumber);
//output: Return uid
Log.i("Return"," uid" + uId);
} else {
onCallCallback.showToast("Could not load phone number");
}
} else{
Log.e("in ", " response is not successful" )
}
}
@Override
public void onFailure(Call<TopLead> call, Throwable t) {
t.printStackTrace();
}
});
这仍然在其他线程上运行,因此将在一段时间后设置uId
。设置后即可使用该值。如果要在主线程上运行并使用Synchronous
获取uId
(返回call.execute().body();
对象,然后可以获取{{1}),则也可以使用TopLead
请求},然后使用uId
。
我希望它能对您有所帮助,请在注释中提出疑问。
答案 3 :(得分:0)
由于我无法理解@David 的回答,我不得不自己想出一个解决方案。我必须使用库 OkHttp3
从网络接收数据。为了解决这个问题,我使用了 LiveData
。
fun getText(): LiveData<String> {
val liveData = MutableLiveData<String>()
var result = ""
val client = OkHttpClient()
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
e.printStackTrace()
result = e.toString()
liveData.postValue(result)
}
override fun onResponse(call: Call, response: Response) {
result = response.body.toString()
liveData.postValue(result)
}
})
return liveData
}
一旦你有了 LiveData 对象,我们就可以观察它了:
getText().observe(viewLifecycleOwner) {
Toast.makeText(requireContext(), "Received $it", Toast.LENGTH_SHORT).show()
}