iLyas Dev iLyas Dev - 2 months ago 23
Android Question

E/RecyclerView: No adapter attached; skipping layout

I have been reading different answers here on stackoverflow and i tried to implement the solution but I am still getting the same error, I don't know why ! :/



When I debug my application on the API 10, I got the warning : E/RecyclerView: No adapter attached; skipping layout, but when i choose for example API level 16 it's fine, i don't know because what !



This is my Adapter Class :



`
public class RecipesAdapter extends RecyclerView.Adapter {

private List<Recipes> recipesList;
private static Recipes recipe;
private static Intent intent;
private Context context;
private View row;
private RecipeHolder holder;

//Conctructor
public RecipesAdapter(List<Recipes> recipesList)
{
this.recipesList=recipesList;
}

//create holder (view)
@Override
public RecipeHolder onCreateViewHolder(ViewGroup parent, int viewType) {
row= LayoutInflater.from(parent.getContext()).inflate(R.layout.recipe_row, parent,false);
//Call constructor : Holder
holder=new RecipeHolder(row);
return holder;
}

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

recipe= recipesList.get(position);

holder.recipe_title.setText(recipe.getTitle());
Picasso.with(holder.recipe_image.getContext()).load(recipe.getImage_url()).into(holder.recipe_image);
holder.recipe_rank.setText(recipe.getSocial_rank().split("\\.",2)[0]);
holder.recipe_publisher.setText(recipe.getPublisher());
}

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

/*To avoid calling methods findViewById for each view, Android has added a concept called ViewHolder
to change 'the values' of each View => concept of Recycling */
public class RecipeHolder extends RecyclerView.ViewHolder
{

private ImageView recipe_image;
private TextView recipe_title,recipe_rank,recipe_publisher;

public RecipeHolder(View itemView) {
super(itemView);
recipe_image=(ImageView) itemView.findViewById(R.id.recipe_img);
recipe_title=(TextView) itemView.findViewById(R.id.recipe_title);
recipe_rank=(TextView) itemView.findViewById(R.id.recipe_rank);
recipe_publisher=(TextView) itemView.findViewById(R.id.recipe_publisher);

itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
context = v.getContext();
intent = new Intent(context, DetailRecipe.class);
intent.putExtra("url",recipesList.get(getAdapterPosition()).getF2f_url());
intent.putExtra("image",recipesList.get(getAdapterPosition()).getImage_url());
Log.e("log","url is : "+recipe.getF2f_url());
context.startActivity(intent);
}});
}
}
}`


onCreate Method




@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.cookingrecipes);
// Adding Toolbar to Main screen
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
Connection_GetData();
}


onResponse Method : when the connection was successful




I used Retrofit library to get data, I called Display_Recipes() to set Adapter


`@Override
public void onResponse(Call<ResultRecipes> call, Response<ResultRecipes> response) {

recipesList = response.body().getRecipes();
//Recycler View
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
/*Performance*/
recyclerView.setItemViewCacheSize(24);
recyclerView.setDrawingCacheEnabled(true);
recyclerView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);

recyclerView.setLayoutManager(new GridLayoutManager(CookingRecipes.this, 2));

/*Treatment - Display*/
Display_Recipes();
}`


Display_Recipes() Method



`public void Display_Recipes() {
//Setup Adapter
this.recipeAdapter = new RecipesAdapter(recipesList);
recyclerView.setAdapter(recipeAdapter);
}`


Image Log
Many Thanks,

Jai Jai
Answer

It's necessary to set LayoutManager on main thread instead of calling inside any callback.

Update your onCreate method as per below :

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.cookingrecipes);
        // Adding Toolbar to Main screen
        toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);


        //Shifted your recycler view code here

       //Recycler View
       recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
       recyclerView.setHasFixedSize(true);
       /*Performance*/
       recyclerView.setItemViewCacheSize(24);
       recyclerView.setDrawingCacheEnabled(true);
       recyclerView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);

       recyclerView.setLayoutManager(new GridLayoutManager(CookingRecipes.this, 2));

       // Only pass context to your adapter
       recyclerView.setAdapter(new RecipesAdapter(CookingRecipes.this);

        Connection_GetData();
    }

And update your onResponse Callback :

 @Override
 public void onResponse(Call<ResultRecipes> call, Response<ResultRecipes> response) {

         recipesList = response.body().getRecipes();

         /*Treatment - Display*/
         Display_Recipes();
  }

Create method to update list in your adapter whenever you need to pass updated list :

public void udpateList(List<Recipes> recipesList){
    this.recipesList = recipesList;
    notifyDataSetChanged();
}

Now call this method from your Display_Recipes method

public void Display_Recipes() {
        //Update Adapter
        udpateList(recipesList);
    }