【问题标题】:"Already executed" error (Retrofit2 and Android)“已执行”错误(Retrofit2 和 Android)
【发布时间】:2017-12-29 23:11:14
【问题描述】:

首先,我有 2 个片段,它们显示不同的 json 值(2 个链接)。如果我更改片段(.replace()),该片段会通过改造获得值并显示它。它工作得很好,但其他片段被删除了值。更改片段后,它会再次下载,因此我更改了结构。我想一次获取 2 个 json 对象,因此我在 mainactivity 中获取 json 对象,片段通过方法获取这些对象。它们在第一次打开时运行良好,但如果我第二次打开片段,则会出现此错误。我该如何解决?

java.lang.IllegalStateException: Already executed.
at retrofit2.OkHttpCall.enqueue(OkHttpCall.java:84)

代码很长,我会展示主要结构。

MainActivity.java

public class MainActivity extends AppCompatActivity
{
    private Call<Restaurant[]> restaurantCall;
    private Call<Dining[]> diningCall;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //Restaurant Json value
        RestaurantInterface restaurantInterface = RetroClient.getClient().create(RestaurantInterface.class);
        restaurantCall = restaurantInterface.getJsonValues();

        //Dininghall Json value
        DiningInterface diningInterface = RetroClient.getClient().create(DiningInterface.class);
        diningCall = diningInterface.getJsonValues();
    }
    public Call<Restaurant[]> RestaurantJson()
    {
        return this.restaurantCall;
    }

    public Call<Dining[]> DiningJson()
    {
        return this.diningCall;
    }
}

RestaurantFragment.java(其他片段结构相同)

public class RestFragment extends Fragment
{

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        View view = inflater.inflate(R.layout.fragment_rest, container, false);

        Call<Restaurant[]> call = ((MainActivity) getActivity()).RestaurantJson();

        call.enqueue(new Callback<Restaurant[]>()
        {
            .
            .

【问题讨论】:

  • 看看这个stackoverflow.com/a/35094488/3172725。您不能两次使用同一个呼叫,您需要克隆您的呼叫。
  • 我检查过了,但是我如何使用 clone() 呢?
  • Call&lt;Restaurant[]&gt; retryCall = call.clone(); retryCall.enqueue(new Callback&lt;Restaurant[]&gt;()... 或public Call&lt;Restaurant[]&gt; RestaurantJson() { return this.restaurantCall.clone(); }
  • 谢谢,它成功了。我确实返回了 this.restaurantCall.clone();并返回 this.diningCall.clone();但是,我认为它会在主要活动中下载 json 对象,但它会以片段的形式下载它们。为什么以及解决方案是什么?
  • 为方便起见,我回复了这个新问题的答案...评论太长了

标签: android android-fragments retrofit retrofit2 android-fragmentactivity


【解决方案1】:

总结一下,为了避免“已经执行”异常,克隆调用:

public Call<Restaurant[]> RestaurantJson()
{
    return this.restaurantCall.clone();
}

public Call<Dining[]> DiningJson()
{
    return this.diningCall.clone();
}

如果你想在活动中而不是在片段中执行调用,那么你需要在活动中调用enqueue(new Callbak(...。 所以你需要这样的东西:

public class RestFragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_rest, container, false);

        ((MainActivity) getActivity()).RestaurantJson(this);
    }

     public void onResponse(Response<T> response) {
         //your fragment code on response
     } 
    ...
}

public class MainActivity extends AppCompatActivity {

    public void RestaurantJson(final RestFragment fragment)
    {
        RestaurantInterface restaurantInterface = RetroClient.getClient().create(RestaurantInterface.class);
        restaurantCall = restaurantInterface.getJsonValues();
        restaurantCall.enqueue(new Callback<Restaurant[]>() {

        @Override
        public void onResponse(Call<T> call, Response<T> response) {
            ...
            fragment.onResponse(response);
        }
    }
    ...
}

您的 DiningFragment 和您的用餐电话也是如此......

【讨论】:

  • 谢谢。第一部分运作良好。我稍后会尝试第二部分。
猜你喜欢
  • 1970-01-01
  • 2018-05-22
  • 2023-04-05
  • 1970-01-01
  • 1970-01-01
  • 2015-07-10
  • 2017-05-09
  • 2016-12-28
  • 1970-01-01
相关资源
最近更新 更多