我有一个在其中实现类的方法:
public class RetrofitCallBackUtil {
private ArrayList<Message> messages = new ArrayList<>();
public ArrayList<Message> getLastTenMessageCallBack(int user_id, int sender_id, int offset_number, RESTDatabaseDAO service) {
Call<ArrayList<Message>> call = service.getLastTenMessage(user_id, sender_id, offset_number);
call.enqueue(new Callback<ArrayList<Message>>() {
@Override
public void onResponse(Call<ArrayList<Message>> call, Response<ArrayList<Message>> response) {
if (response.isSuccess()) {
messages = response.body();
Log.i("Success", "Good ten " + response.body().size());
} else {
Log.i("Success", "Not good ten" + response.raw());
}
}
@Override
public void onFailure(Call<ArrayList<Message>> call, Throwable t) {
Log.i("Fail", "Failure ten " + t.toString());
}
});
//Still get NullPointException from here. (messages.size())
Log.i("Success", "Good ten activity" + messages.size());
return messages;
}
}
我希望获得消息变量的值,但不能。我还创建了一个全局变量List<Message> messages
并返回但仍无法从response.body()
获取值。有人有解决方案吗?
更新
我想要这样的事情:
List<Message> testMessages = retrofitCallBackUtil.getLastTenMessageCallBack(AppConfig.USER_ID, userId, 0, service);
因为我想多次使用该方法的结果,所以我希望它能为我返回一个数据。
答案 0 :(得分:2)
首先,你的方法
public ArrayList<Message> getLastTenMessageCallBack(...)
具有同步签名,但实现是异步的。因此,当方法返回messages
时,它们仍为空。
使用异步impl的正确签名将是
public void getLastTenMessageCallBack(...)
只能在回调中获得结果。
如果你想要一个同步方法,你可以使用latch:
public ArrayList<Message> getLastTenMessageCallBack(int user_id, int sender_id, int offset_number, RESTDatabaseDAO service) {
ArrayList<Message> messages = new ArrayList<>();
CountDownLatch latch = new CountDownLatch(1);
Call<ArrayList<Message>> call = service.getLastTenMessage(user_id, sender_id, offset_number);
call.enqueue(new Callback<ArrayList<Message>>() {
@Override
public void onResponse(Call<ArrayList<Message>> call, Response<ArrayList<Message>> response) {
if (response.isSuccess()) {
messages = response.body();
latch.countDown();
}
}
@Override
public void onFailure(Call<ArrayList<Message>> call, Throwable t) {
Log.i("Fail", "Failure ten " + t.toString());
latch.countDown();
}
});
//waiting result ...
latch.await();
return messages;
}
注意,方法范围之外没有变量。
<强> UPD 强>
如果您想要使用异步方法并希望从许多类中使用它,该怎么办?正确的签名将是:
public void getLastTenMessageCallBack(..., Callback<ArrayList<Message>>)
您将在客户端代码中实现此回调。异步方法当然更优选,所以它避免了ui阻塞
答案 1 :(得分:1)
onResponse
和onFailure
,因此当您尝试return messages;
时,它尚未更新。
从回调中返回。
编辑1:
public void getLastTenMessageCallBack(int user_id, int sender_id, int offset_number, RESTDatabaseDAO service) {
Call<ArrayList<Message>> call = service.getLastTenMessage(user_id, sender_id, offset_number);
call.enqueue(new Callback<ArrayList<Message>>() {
@Override
public void onResponse(Call<ArrayList<Message>> call, Response<ArrayList<Message>> response) {
if (response.isSuccess()) {
// THIS IS BEING CALLED AFTER YOUR METHODS RETURNS, SO UPDATE YOUR VIEWS LIKE THIS.
updateViews(response.body());
Log.i("Success", "Good ten " + response.body().size());
} else {
Log.i("Success", "Not good ten" + response.raw());
}
}
@Override
public void onFailure(Call<ArrayList<Message>> call, Throwable t) {
Log.i("Fail", "Failure ten " + t.toString());
}
});
}
public void updateViews(List<Messages> messages){
//use messages to update your views here.
}
编辑2:现在,因为你是从很多地方调用它,传递类似requestCode的内容并检查相同的onResponse来识别调用的来源。
public void getLastTenMessageCallBack(final int requestCode, int user_id, ..
和onResponse
updateViews(requestCode, response.body());
并通过比较请求代码来相应地更新您的视图。
public void updateViews(int requestCode, List<Messages> messages){
if(requestCode==XYZ)
//use messages to update your views here.
}
编辑3:
定义您自己的interface
以接收回调:
public interface NetworkResponseCallback {
void onSuccess(ArrayList<Message>> messages);
void onFailure(); //if you want to pass something else, like cause of failure you can add it.
}
现在,更改您的方法定义:
public void getLastTenMessageCallBack(int user_id, ... , final NetworkResponseCallback networkResponseCallback){
实施onResponse
和onFailure
:
if (response.isSuccess()) {
if(networkResponseCallback!=null)
networkResponseCallback.onSuccess(response.body());
public void onFailure(Call<ArrayList<Message>> call, Throwable t) {
Log.i("Fail", "Failure ten " + t.toString());
networkResponseCallback.onFailure();
}
像这样调用getLastTenMessageCallBack
方法:
getLastTenMessageCallBack(int user_id, int sender_id, int offset_number, RESTDatabaseDAO service, new NetworkResponseCallback() {
@Override
public void onSuccess(List<Messages> messages) {
}
@Override
public void onFailure() {
}
});
答案 2 :(得分:1)
您将在匿名内部类中声明一个名为“messages”的本地范围变量,该变量将隐藏外部类变量。尝试删除该行并将消息成员变量添加回您的类对象。
答案 3 :(得分:1)
你有一个全局变量的正确想法,但你从未为这个变量赋值,你所做的就是在函数onResponse()
中声明一个局部变量,这个变量的SCOPE就在里面函数onResponse()
所以函数之外的任何地方都不存在变量。
因此,通过声明一个范围为封闭类的变量messages
,您现在可以直接将响应主体分配给“class scoped”messages
变量
这应该这样做,
private List<Message> messages;
public ArrayList<Message> getLastTenMessageCallBack(int user_id, int sender_id, int offset_number, RESTDatabaseDAO service) {
Call<ArrayList<Message>> call = service.getLastTenMessage(user_id, sender_id, offset_number);
call.enqueue(new Callback<ArrayList<Message>>() {
@Override
public void onResponse(Call<ArrayList<Message>> call, Response<ArrayList<Message>> response) {
if (response.isSuccess()) {
// This is wrong you are creating a new variable
// messages scoped to this function.
// List<Message> messages = response.body();
// Instead just assign the response body to the class
// scoped variable messages
messages = response.body();
Log.i("Success", "Good ten " + response.body().size());
} else {
Log.i("Success", "Not good ten" + response.raw());
}
}
@Override
public void onFailure(Call<ArrayList<Message>> call, Throwable t) {
Log.i("Fail", "Failure ten " + t.toString());
}
});
Log.i("Success", "Good ten activity" + messages.size());
return messages;
}
修改强>
我们应该用某种方式来回报 getLastTenMessageCallBack()稍后再使用onResponse?
上面的函数getLastTenMessagesCallBack
将始终返回null,因为在您的Retrofit调用成功后调用onResponse
函数,因此您无法从函数getLastTenMessagesCallBack
返回任何内容,因为在调用来自改装调用的回调之前,不会设置messages变量,因此解决方法是,
首先,您创建一个具有一个函数的接口,该函数接收您的Retrofit调用的结果
public interface MyCustomCallback {
void onSuccess(Object result);
void onError(Object errorObject);
}
然后您将此接口的实现传递给getLastTenMessageCallBack
public void getLastTenMessageCallBack(int user_id, int sender_id, int offset_number, RESTDatabaseDAO service, final MyCustomCallback callback) {
Call<ArrayList<Message>> call = service.getLastTenMessage(user_id, sender_id, offset_number);
call.enqueue(new Callback<ArrayList<Message>>() {
@Override
public void onResponse(Call<ArrayList<Message>> call, Response<ArrayList<Message>> response) {
if (response.isSuccess()) {
// This is wrong you are creating a new variable
// messages scoped to this function.
// List<Message> messages = response.body();
// Instead just assign the response body to the class
// scoped variable messages
messages = response.body();
callback.onSuccess(messages);
Log.i("Success", "Good ten " + response.body().size());
} else {
Log.i("Success", "Not good ten" + response.raw());
}
}
@Override
public void onFailure(Call<ArrayList<Message>> call, Throwable t) {
Log.i("Fail", "Failure ten " + t.toString());
}
});
}
所以请记住在调用getLastTenMessageCallback
时需要传递接口的 Implementation ,我刚创建的接口的示例实现看起来像这样
class CallbackImpl implements MyCustomCallback {
@Override
public void onSuccess(Object result) {
List<Message> messages = (List<Message>) result;
}
@Override
public void onError(Object errorObject) {
}
}
P.S你可以通过在回调界面中使用泛型来进一步改进这一点,就像改造的例子一样