首页 > 解决方案 > 如何将内部类的返回值分配给外部变量

问题描述

我是 Java 初学者,我一直坚持从匿名内部类分配变量的返回值。

我想捕获从 API 调用返回的字符串列表。

List<String> **strTopics**=null;
Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(url)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();

Call<List<String>> call=retrofit.getSubjects();

call.enqueue(new Callback<List<String>>() {
            @Override
            public void onResponse(Call<List<String>> call, Response<List<String>> response) {
                Log.d("prepareListData","I am success");
                strTopics=response.body();
                for(String str:strTopics)
                 Log.d("Subject Name ",str)
            }

            @Override
            public void onFailure(Call<List<String>> call, Throwable t) {
                Log.d("prepareListData","I am failure");
            }
        });
       //I am having challenges here. After this statement, again "**strTopics**" is becoming null.
      for(String str:strTopics)
                     Log.d("After inner method",str)

我只想提一下,如果我评论上面的 for 循环,那么只有我能够打印内部类方法中的主题名称。

如果取消注释,则不会调用任何 for 循环,也不会打印任何内容。在第二个 for 循环中获取NullPointerException 。不确定这也是Retrofit2的问题。

有人可以帮助我如何克服这个问题。无论从内部类返回什么,我都希望在它之外使用这些值。

请帮忙。

标签: javaretrofit2anonymous-class

解决方案


如果要在通话之外显示结果,则必须等待通话完成。在改造中, call.enqueue 是一个异步任务,这意味着它在不同的线程上执行,可能需要一些时间才能得到结果。

在这里,您的第二个循环,在队列之外,实际上是在调用完成之前执行的。这就是为什么当您尝试访问它时它仍然为空。

要恢复,它实际上是按以下顺序执行的:

  • 首先你创建你的电话Call<List<String>> call=retrofit.getSubjects();
  • 然后你添加一个回调给它。这将启动一个后台任务,该任务将获得所需的信息
  • 当后台任务执行时,主线程将移动到下一条指令,这是您的第二个 for 循环
  • 在某个时刻,后台任务完成,并将调用您在回调中声明的 onResponse 或 onFailure 方法
  • 然后执行对应方法里面的代码

在某些情况下,后台任务可能会在下一条指令在主线程上启动之前完成,但你永远无法确定,所以我不会指望它。

如果您需要在代码的其他地方使用调用的结果,我建议您创建一个将结果作为参数的方法,并在代码的 onResponse 中调用此方法。

void doSomethingWithResult(List<String> result) {
    // do whatever you need with that result
}

// then in your call
call.enqueue(new Callback<List<String>>() {
    @Override
    public void onResponse(Call<List<String>> call, Response<List<String>> response) {
          Log.d("prepareListData","I am success");
          strTopics=response.body();
          for(String str:strTopics)
              Log.d("Subject Name ",str)
          doSomethingWithResult(response.body());
      }

      @Override
      public void onFailure(Call<List<String>> call, Throwable t) {
          Log.d("prepareListData","I am failure");
      }
});

推荐阅读