如果按下DietFragment中的按钮,它将在getJson()中运行HttpRequestDietPlan方法。之后,在Json(mealId, title)中使用DietFragment

问题:DietFragment不等待请求完成。

未来不可能,因为最低的Android版本必须为4.4

饮食片段

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class DietFragment extends Fragment {

    Button button;
    TextView mealOne;

    public int mealId;

    public DietPlan dietPlan = new DietPlan();

    HttpRequestDietPlan hrt = new HttpRequestDietPlan();


    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_diet, null);

        ET = rootView.findViewById(R.id.targetCalories_Input);
        Tv1 = rootView.findViewById(R.id.targetCalories_Output);
        button = rootView.findViewById(R.id.testButton);
        mealOne = rootView.findViewById(R.id.meal1);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                hrt.getJson();

                // java.lang.IllegalMonitorStateException: object not locked by thread before wait()

                    mealId = hrt.dietPlan.meals.get(0).mealId;
                    title = hrt.dietPlan.meals.get(0).title;
                    mealOne.setText(title);

            }
        });

        return rootView;
    }
}


HttpRequestDietPlan

import android.os.Build;
import android.support.annotation.RequiresApi;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.util.concurrent.CompletableFuture;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class HttpRequestDietPlan {

    public DietPlan dietPlan = new DietPlan();
    public final CompletableFuture<Response> future = new CompletableFuture<>();

    public void getJson() {

        OkHttpClient client = new OkHttpClient();

        final Request request = new Request.Builder()
                .addHeader("X-RapidAPI-Host", "spoonacular-recipe-food-nutrition-v1.p.rapidapi.com")
                .addHeader("X-RapidAPI-Key", "KEY_KEY_KEY")
                .url("https://spoonacular-recipe-food-nutrition-v1.p.rapidapi.com/recipes/mealplans/generate?timeFrame=day&targetCalories=2000")
                .build();

        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                call.cancel();
                e.printStackTrace();
            }

            @Override
            public void onResponse(Call call, final Response response) throws IOException {
                if (!response.isSuccessful()) {
                    throw new IOException("Unexpected code " + response);
                } else {
                    try {
                        String jsonData = response.body().string();
                        JSONObject json = new JSONObject(jsonData);
                        JSONArray arrayMeals = json.getJSONArray("meals");

                        for (int i = 0; i < arrayMeals.length(); i++) {
                            JSONObject object = arrayMeals.getJSONObject(i);
                            Meal meal = new Meal(
                                    object.getInt("id"),
                                    object.getString("title")
                            );
                            dietPlan.meals.add(meal);
                            System.out.println(meal);
                        }
                        } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }
}

最佳答案

这里有一些建议:


您无需在每次调用时都创建一个新的OkHttpClient,因此我将其移到了方法之外。
然后,您可以传递回调(CallHandler),以便在调用结果可用时得到通知,并在收到结果后更新您的数据。
关于反序列化的另一件事,我建议您使用一个库(https://github.com/google/gson)反序列化对类实例的json响应。


PS:我没有测试此代码,这只是一个实现建议。

分段:

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class DietFragment extends Fragment {

    Button button;
    TextView mealOne;

    public int mealId;

    public DietPlan dietPlan = new DietPlan();

    HttpRequestDietPlan hrt = new HttpRequestDietPlan();


    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_diet, null);

        ET = rootView.findViewById(R.id.targetCalories_Input);
        Tv1 = rootView.findViewById(R.id.targetCalories_Output);
        button = rootView.findViewById(R.id.testButton);
        mealOne = rootView.findViewById(R.id.meal1);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                hrt.getJson(new HttpRequestDietPlan.CallHandler(
                    @Override
                    public void onFailure(Exception e) {
                        e.printStackTrace();
                    }

                    @Override
                    public void onSuccess(DietPlan dietPlan) {
                        mealId = hrt.dietPlan.meals.get(0).mealId;
                        title = hrt.dietPlan.meals.get(0).title;
                        mealOne.setText(title);
                    }
                ));
            }
        });

        return rootView;
    }
}


HttpRequestDietPlan:

import android.os.Build;
import android.support.annotation.RequiresApi;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.util.concurrent.CompletableFuture;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class HttpRequestDietPlan {

    private  OkHttpClient client = new OkHttpClient();

    public interface CallHandler {
        public void onSuccess(DietPlan dietPlan);
        public void onFailure(Exception e);
    }

    public void getJson(CallHandler callHandler) {

        final Request request = new Request.Builder()
                .addHeader("X-RapidAPI-Host", "spoonacular-recipe-food-nutrition-v1.p.rapidapi.com")
                .addHeader("X-RapidAPI-Key", "KEY_KEY_KEY")
                .url("https://spoonacular-recipe-food-nutrition-v1.p.rapidapi.com/recipes/mealplans/generate?timeFrame=day&targetCalories=2000")
                .build();

        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                call.cancel();
                e.printStackTrace();
                callHandler.onFailure(e)
            }

            @Override
            public void onResponse(Call call, final Response response) throws IOException {
                if (!response.isSuccessful()) {
                    IOException e = new IOException("Unexpected code " + response);
                    callHandler.onFailure(e)
                } else {
                    DietPlan dietPlan = new DietPlan();
                    // Deserialize with a library here
                    try {
                        String jsonData = response.body().string();
                        JSONObject json = new JSONObject(jsonData);
                        JSONArray arrayMeals = json.getJSONArray("meals");

                        for (int i = 0; i < arrayMeals.length(); i++) {
                            JSONObject object = arrayMeals.getJSONObject(i);
                            Meal meal = new Meal(
                                object.getInt("id"),
                                object.getString("title")
                            );
                            dietPlan.meals.add(meal);
                            System.out.println(meal);
                        }
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                    callHandler.onSuccess(dietPlan)
                }
            }
        });
    }
}

09-11 09:31