从内部类中获取变量的值

时间:2016-03-11 06:42:45

标签: java android retrofit

我有一个在其中实现类的方法:

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);

因为我想多次使用该方法的结果,所以我希望它能为我返回一个数据。

4 个答案:

答案 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)

异步调用

onResponseonFailure,因此当您尝试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){

实施onResponseonFailure

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你可以通过在回调界面中使用泛型来进一步改进这一点,就像改造的例子一样