使用Retrofit从JSON发出ArrayList问题并填充RecyclerView

时间:2017-10-20 21:16:55

标签: java android json android-recyclerview retrofit

我一直在努力让回收者的观点与改造一起工作。我似乎从getRecipes()方法中提取了JSON,我的日志告诉我有些数据存在。

然而,当我从onCreate()调用我的getRecipes()方法时,似乎出现了问题。当我检查我的recipeList数组是否在onCreate中包含我的JSON结果时,它告诉我它是空的。如果我的getRecipes()方法中的日志显示数据存在,为什么这样做呢?

不确定我的回收站视图是否存在问题,或者我在改造时遇到了什么问题。一直在努力寻找,所以任何建议都会非常感激。

JSON https://d17h27t6h515a5.cloudfront.net/topher/2017/May/59121517_baking/baking.json

public class ItemListActivity extends AppCompatActivity {

private boolean mTwoPane;
public static final String LOG_TAG = "myLogs";
public static List<Recipe> recipeList = new ArrayList<>();


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

    getRecipes();

    //Logging to check that recipeList contains data

    if(recipeList.isEmpty()){
        Log.d(LOG_TAG, "Is empty");
    }else {
        Log.d(LOG_TAG, "Is not empty");
    }

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    toolbar.setTitle(getTitle());

    RecyclerView recyclerView = (RecyclerView) findViewById(R.id.item_list);
    RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
    recyclerView.setLayoutManager(layoutManager);

    SimpleItemRecyclerViewAdapter simpleItemRecyclerViewAdapter = new SimpleItemRecyclerViewAdapter(recipeList);

    recyclerView.setAdapter(simpleItemRecyclerViewAdapter);

    if (findViewById(R.id.item_detail_container) != null) {

        mTwoPane = true;
    }

}


public void getRecipes(){

    String ROOT_URL = "https://d17h27t6h515a5.cloudfront.net/topher/2017/May/59121517_baking/";

    Retrofit RETROFIT = new Retrofit.Builder()
            .baseUrl(ROOT_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .build();

    RecipeService service = RETROFIT.create(RecipeService.class);

    Call<List<Recipe>> call = service.getMyJson();
    call.enqueue(new Callback<List<Recipe>>() {
        @Override
        public void onResponse(Call<List<Recipe>> call, Response<List<Recipe>> response) {
            Log.d(LOG_TAG, "Got here");
            if (!response.isSuccessful()) {
                Log.d(LOG_TAG, "No Success");
            }

            Log.d(LOG_TAG, "Got here");

            recipeList = response.body();

            //Logging to check data is there
            Log.v(LOG_TAG, "LOGS" + recipeList.size());

            for (int i = 0; i < recipeList.size(); i++) {
                String newString = recipeList.get(i).getName();

                Ingredients[] ingredients = recipeList.get(i).getIngredients();
                for(int j = 0; j < ingredients.length; j++){
                    Log.d(LOG_TAG, ingredients[j].getIngredient());
                }

                Steps[] steps = recipeList.get(i).getSteps();
                for(int k = 0; k < steps.length; k++){
                    Log.d(LOG_TAG, steps[k].getDescription());
                }

                Log.d(LOG_TAG, newString);


            }


        }

        @Override
        public void onFailure(Call<List<Recipe>> call, Throwable t) {
            Log.e("getRecipes throwable: ", t.getMessage());
            t.printStackTrace();

        }
    });


}



public class SimpleItemRecyclerViewAdapter
        extends RecyclerView.Adapter<SimpleItemRecyclerViewAdapter.ViewHolder> {

    private final List<Recipe> mValues;

    public SimpleItemRecyclerViewAdapter(List<Recipe> items) {
        mValues = items;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.item_list_content, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(final ViewHolder holder, int position) {

        holder.mItem = mValues.get(position);
        holder.mContentView.setText(mValues.get(position).getName());

        holder.mView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mTwoPane) {
                    Bundle arguments = new Bundle();
                    arguments.putString(ItemDetailFragment.ARG_ITEM_ID, holder.mItem.getId());
                    ItemDetailFragment fragment = new ItemDetailFragment();
                    fragment.setArguments(arguments);
                    getSupportFragmentManager().beginTransaction()
                            .replace(R.id.item_detail_container, fragment)
                            .commit();
                } else {
                    Context context = v.getContext();
                    Intent intent = new Intent(context, ItemDetailActivity.class);
                    intent.putExtra(ItemDetailFragment.ARG_ITEM_ID, holder.mItem.getId());

                    context.startActivity(intent);
                }
            }
        });
    }

    @Override
    public int getItemCount() {
        return mValues.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        public  View mView;
        public  TextView mContentView;
        public Recipe mItem;


        public ViewHolder(View view) {
            super(view);
            mView = view;
            mContentView = (TextView) view.findViewById(R.id.content);

        }

        @Override
        public String toString() {
            return super.toString() + " '" + mContentView.getText() + "'";
        }
    }
}

RecipeService

public interface RecipeService {
@GET("baking.json")
Call<List<Recipe>> getMyJson();}

模型

配方

public class Recipe{

private Ingredients[] ingredients;

private String id;

private String servings;

private String name;

private String image;

private Steps[] steps;

public Ingredients[] getIngredients ()
{
    return ingredients;
}

public void setIngredients (Ingredients[] ingredients)
{
    this.ingredients = ingredients;
}

public String getId ()
{
    return id;
}

public void setId (String id)
{
    this.id = id;
}

public String getServings ()
{
    return servings;
}

public void setServings (String servings)
{
    this.servings = servings;
}

public String getName ()
{
    return name;
}

public void setName (String name)
{
    this.name = name;
}

public String getImage ()
{
    return image;
}

public void setImage (String image)
{
    this.image = image;
}

public Steps[] getSteps ()
{
    return steps;
}

public void setSteps (Steps[] steps)
{
    this.steps = steps;
}

@Override
public String toString()
{
    return "[ingredients = "+ingredients+", id = "+id+", servings = "+servings+", name = "+name+", image = "+image+", steps = "+steps+"]";
}}

成分<​​/ P>

public class Ingredients{
private String measure;

private String ingredient;

private String quantity;

public String getMeasure ()
{
    return measure;
}

public void setMeasure (String measure)
{
    this.measure = measure;
}

public String getIngredient ()
{
    return ingredient;
}

public void setIngredient (String ingredient)
{
    this.ingredient = ingredient;
}

public String getQuantity ()
{
    return quantity;
}

public void setQuantity (String quantity)
{
    this.quantity = quantity;
}

@Override
public String toString()
{
    return "[measure = "+measure+", ingredient = "+ingredient+", quantity = "+quantity+"]";
}}

步骤

public class Steps{

private String id;
     private String shortDescription;

    private String description;

    private String videoURL;

    private String thumbnailURL;

    public String getId ()
    {
        return id;
    }

    public void setId (String id)
    {
        this.id = id;
    }

    public String getShortDescription ()
    {
        return shortDescription;
    }

    public void setShortDescription (String shortDescription)
    {
        this.shortDescription = shortDescription;
    }

    public String getDescription ()
    {
        return description;
    }

    public void setDescription (String description)
    {
        this.description = description;
    }

    public String getVideoURL ()
    {
        return videoURL;
    }

    public void setVideoURL (String videoURL)
    {
        this.videoURL = videoURL;
    }

    public String getThumbnailURL ()
    {
        return thumbnailURL;
    }

    public void setThumbnailURL (String thumbnailURL)
    {
        this.thumbnailURL = thumbnailURL;
    }

    @Override
    public String toString()
    {
        return "[id = "+id+", shortDescription = "+shortDescription+", description = "+description+", videoURL = "+videoURL+", thumbnailURL = "+thumbnailURL+"]";
    }}

记录

https://gist.github.com/2triggers/12b6eeb32ed8909ab50bbadd4742d7f7

3 个答案:

答案 0 :(得分:1)

这将始终为空,因为此行将在从服务器获取响应之前执行。

if(recipeList.isEmpty()){
         Log.d(LOG_TAG, "Is empty");
    }else {
        Log.d(LOG_TAG, "Is not empty");
    }

最好在此行之后调用此方法recipeList = response.body();

SimpleItemRecyclerViewAdapter simpleItemRecyclerViewAdapter = new SimpleItemRecyclerViewAdapter(recipeList);

        recyclerView.setAdapter(simpleItemRecyclerViewAdapter);

        if (findViewById(R.id.item_detail_container) != null) {

            mTwoPane = true;
        }

答案 1 :(得分:0)

尝试使用Recipe.class中的所有属性创建构造函数

像:     public Ingredients(字符串小节,字符串成分,字符串数量){     this.measure = measure;     this.ingredients =成分;     this.quantity =数量     }

在构成列表对象的所有类中都这样做。

答案 2 :(得分:0)

这是因为你在将配方列表发送到适配器之前,即使它已被填充,在你将配方列表发送到适配器是空的,你从getRecipes方法填充你的配方列表之后,你可能想知道你已经声明了getRecipes即使你将配方列表分配给适配器之前的方法,所以它怎么会是空的,是的但事实是你的getRecipes在后台线程工作,所以甚至在你的配方列表被填充之前你的适配器赋值发生在主线程上,所以你基本上分配了空列表,您可以做的一件事是当数据发生变化时适配器发出通知,或者当配方表填充了getRecipe方法中的数据时,通知。

在此之后分配recipelist = response.body时,您可以通知适配器

或移动这两行

SimpleItemRecyclerViewAdapter simpleItemRecyclerViewAdapter = new SimpleItemRecyclerViewAdapter(recipeList);
recyclerView.setAdapter(simpleItemRecyclerViewAdapter);

之后

 recipelist = response.body;
getRecipes方法中的