web-dev-qa-db-fra.com

Afficher un RecyclerView en fragment

J'essaie la nouvelle RecyclerView dans Android Lollipop et je suis coincé.

J'essaie de recevoir une liste, avec une icône et une TextView à la droite de l'icône, à l'intérieur d'une Fragment.

J'ai trouvé ce bon tutoriel sur la façon de configurer une RecyclerView. J'ai suivi chaque point et n'ai modifié que le item_layout.xml pour l'adapter à mes besoins.

Le projet est construit sans erreur, mais lorsqu’il se lance sur mon appareil, j’obtiens cette erreur:

Java.lang.RuntimeException: Impossible de démarrer l'activité ComponentInfo {com.fredrikaldgard.materialcolors/com.fredrikaldgard.materialcolors.MainActivity}: Java.lang.NullPointerException: tentative d'invocation de la méthode virtuelle 'void Android.support.v7.widget.RecyclerView. setLayoutManager (Android.support.v7.widget.RecyclerView $ LayoutManager) 'sur une référence d'objet null

J'ai essayé de google le problème mais je suis un amateur de développement Android.

Voici ma MainActivity:

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

    // 1. get a reference to recyclerView
    RecyclerView recyclerView = (RecyclerView) findViewById(R.id.list);

    // 2. set layoutManger
    recyclerView.setLayoutManager(new LinearLayoutManager(this));

    // this is data fro recycler view
    ItemData itemsData[] = { new ItemData("Indigo",R.drawable.circle),
            new ItemData("Red",R.drawable.color_ic_launcher),
            new ItemData("Blue",R.drawable.Indigo),
            new ItemData("Green",R.drawable.circle),
            new ItemData("Amber",R.drawable.color_ic_launcher),
            new ItemData("Deep Orange",R.drawable.Indigo)};


    // 3. create an adapter
    MyAdapter mAdapter = new MyAdapter(itemsData);
    // 4. set adapter
    recyclerView.setAdapter(mAdapter);
    // 5. set item animator to DefaultAnimator
    recyclerView.setItemAnimator(new DefaultItemAnimator());

Et ma MyAdapter:

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private ItemData[] itemsData;

public MyAdapter(ItemData[] itemsData) {
    this.itemsData = itemsData;
}

// Create new views (invoked by the layout manager)
@Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
                                               int viewType) {
    // create a new view
    View itemLayoutView = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.item_layout, null);

    // create ViewHolder

    ViewHolder viewHolder = new ViewHolder(itemLayoutView);
    return viewHolder;
}

// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {

    // - get data from your itemsData at this position
    // - replace the contents of the view with that itemsData

    viewHolder.txtViewTitle.setText(itemsData[position].getTitle());
    viewHolder.imgViewIcon.setImageResource(itemsData[position].getImageUrl());


}

// inner class to hold a reference to each item of RecyclerView
public static class ViewHolder extends RecyclerView.ViewHolder {

    public TextView txtViewTitle;
    public ImageView imgViewIcon;

    public ViewHolder(View itemLayoutView) {
        super(itemLayoutView);
        txtViewTitle = (TextView) itemLayoutView.findViewById(R.id.item_title);
        imgViewIcon = (ImageView) itemLayoutView.findViewById(R.id.item_icon);
    }
}


// Return the size of your itemsData (invoked by the layout manager)
@Override
public int getItemCount() {
    return itemsData.length;
}
}

Edit: Voici la Fragment

public class ColorsFragment extends Fragment {

    public ColorsFragment(){}

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

        View rootView = inflater.inflate(R.layout.fragment_colors, container, false);

        return rootView;
    }
}

Qu'est-ce qui s'est peut-être mal passé?

28
fredthemugwump

Cette question a été posée il y a quelque temps déjà, mais sur la base de la réponse fournie par @ nacho_zona3 et de l'expérience acquise avec des fragments, le problème est que les vues n'ont pas été créées au moment où vous essayez de les trouver avec la méthode findViewById() dans onCreate(). résoudre ce problème, déplacez le code suivant:

// 1. get a reference to recyclerView
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.list);

// 2. set layoutManger
recyclerView.setLayoutManager(new LinearLayoutManager(this));

// this is data fro recycler view
ItemData itemsData[] = { new ItemData("Indigo",R.drawable.circle),
        new ItemData("Red",R.drawable.color_ic_launcher),
        new ItemData("Blue",R.drawable.Indigo),
        new ItemData("Green",R.drawable.circle),
        new ItemData("Amber",R.drawable.color_ic_launcher),
        new ItemData("Deep Orange",R.drawable.Indigo)};


// 3. create an adapter
MyAdapter mAdapter = new MyAdapter(itemsData);
// 4. set adapter
recyclerView.setAdapter(mAdapter);
// 5. set item animator to DefaultAnimator
recyclerView.setItemAnimator(new DefaultItemAnimator()); 

à l'appel onCreateView() de votre fragment. Une petite quantité de refactoring est nécessaire car toutes les variables et méthodes appelées à partir de cette méthode doivent être statiques. Le code final devrait ressembler à ceci:

 public class ColorsFragment extends Fragment {

     public ColorsFragment() {}

     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
         Bundle savedInstanceState) {

         View rootView = inflater.inflate(R.layout.fragment_colors, container, false);
         // 1. get a reference to recyclerView
         RecyclerView recyclerView = (RecyclerView) rootView.findViewById(R.id.list);

         // 2. set layoutManger
         recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));

         // this is data fro recycler view
         ItemData itemsData[] = {
             new ItemData("Indigo", R.drawable.circle),
                 new ItemData("Red", R.drawable.color_ic_launcher),
                 new ItemData("Blue", R.drawable.Indigo),
                 new ItemData("Green", R.drawable.circle),
                 new ItemData("Amber", R.drawable.color_ic_launcher),
                 new ItemData("Deep Orange", R.drawable.Indigo)
         };


         // 3. create an adapter
         MyAdapter mAdapter = new MyAdapter(itemsData);
         // 4. set adapter
         recyclerView.setAdapter(mAdapter);
         // 5. set item animator to DefaultAnimator
         recyclerView.setItemAnimator(new DefaultItemAnimator());

         return rootView;
     }
 }

Donc, l’essentiel ici est que partout où vous appelez findViewById(), vous devrez utiliser rootView.findViewById()

41
The Dude

Vous devriez extraire RecyclerView dans une Fragment après avoir gonflé la vue principale à l'aide de cette vue. Peut-être qu'il ne trouve pas votre recycleur parce que cela ne fait pas partie de l'activité

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
    final View view = inflater.inflate(R.layout.fragment_artist_tracks, container, false);
    final FragmentActivity c = getActivity();
    final RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
    LinearLayoutManager layoutManager = new LinearLayoutManager(c);
    recyclerView.setLayoutManager(layoutManager);

    new Thread(new Runnable() {
        @Override
        public void run() {
            final RecyclerAdapter adapter = new RecyclerAdapter(c);
            c.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    recyclerView.setAdapter(adapter);
                }
            });
        }
    }).start();

    return view;
}
24
user4182277

Assurez-vous que vous avez la bonne disposition et que l'identifiant RecyclerView se trouve à l'intérieur de la disposition. Sinon, vous obtiendrez cette erreur. J'ai eu le même problème, puis j'ai remarqué que la mise en page était fausse.

    public class ColorsFragment extends Fragment {

         public ColorsFragment() {}

         @Override
         public View onCreateView(LayoutInflater inflater, ViewGroup container,
             Bundle savedInstanceState) {

==> make sure you are getting the correct layout here. R.layout...

             View rootView = inflater.inflate(R.layout.fragment_colors, container, false); 
0
live-love