在 Fragment 中显示 RecyclerView

Posted

技术标签:

【中文标题】在 Fragment 中显示 RecyclerView【英文标题】:Display a RecyclerView in Fragment 【发布时间】:2014-12-24 14:36:54 【问题描述】:

我正在 android Lollipop 中试用新的 RecyclerView,但我卡住了。

我正在尝试接收一个列表,其中包含一个图标和一个 TextView 图标右侧的 Fragment 内。

I found this great tutorial 了解如何设置RecyclerView。我遵循了每一点,只更改了item_layout.xml 以满足我的需要。

项目构建时没有任何错误,但是当它在我的设备上启动时出现此错误:

java.lang.RuntimeException:无法启动活动 ComponentInfocom.fredrikaldgard.materialcolors/com.fredrikaldgard.materialcolors.MainActivity:java.lang.NullPointerException:尝试调用虚拟方法 'void android.support.v7.widget .RecyclerView.setLayoutManager(android.support.v7.widget.RecyclerView$LayoutManager)' 在空对象引用上

我尝试用谷歌搜索这个问题,但我对 Android 开发非常业余。

这是我的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());

还有我的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;


编辑:这是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;
    

可能出了什么问题?

【问题讨论】:

您的 xml 布局文件中是否还有带有 id 列表的 RecyclerView?如果不是,recyclerView 变量将在步骤 2 中为空。 是的,我的 xml 中有一个 RecyclerView,ID 为“list”。 应该更清楚:在activity_main.xml 文件中,对吧? @stkent 好吧,我使用导航抽屉,当我单击抽屉中的一个项目时,它会打开一个活动。我的 activity_main.xml 包含一个 FrameLayout,里面有抽屉。我的 RecyclerView 位于名为 fragment_color.xml 的 XML 文件中。 【参考方案1】:

这是不久前提出的问题,但根据@nacho_zona3 提供的答案以及以前的片段经验,问题是在您尝试使用@987654321 查找视图时尚未创建视图onCreate() 中的 @ 方法来解决这个问题,移动以下代码:

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

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

// this is data from 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()); 

您的片段的onCreateView() 调用。需要进行少量重构,因为从此方法调用的所有变量和方法都必须是静态的。最终代码应如下所示:

 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 from 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;
     
 

所以这里的主要内容是,无论您在哪里调用findViewById(),都需要使用rootView.findViewById()

【讨论】:

用 getActivity() 替换它。 你也可以从片段'onCreateView'返回recyclerview,因为基本上片段现在是一个RecyclerView 我收到MyAdapter mAdapter = new MyAdapter(itemsData); 的错误,它说 MyAdapter 中的 MyAdapter(android.context.Context, List) 无法应用于 (List) 谢谢兄弟。在几年前针对 v2.3.3 创建了我的第一个应用程序之后,我刚刚回到原生 Android 开发,是的……让我们说一两件事发生了变化。哦,劳德【参考方案2】:

您应该在使用该视图膨胀核心视图后在Fragment 中检索RecyclerView。也许它找不到你的 recycler 因为它不是 Activity 的一部分

@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;

【讨论】:

非常感谢!我试图用你的代码替换我的 Fragment 中的代码,但我遇到了“final FragmentActivity c = getActivity();”的问题它给了我一个错误:需要“android.support.v4.app.FragmentActitvity”找到“android.app.Activity”。我已经在我的项目中编译了 v4 支持库。 你可以使用任何activity,如果不需要,你不必使用支持库 “使用任何活动”是什么意思?无论如何,我正在使用支持库作为导航抽屉。 我的意思是活动类的任何子类。抱歉没有说清楚。 对不起,我不太擅长碎片之类的复杂事物。我应该写什么而不是“final FragmentActivity c = getActivity();”?当我用 Activity 替换 FragmentActivity 时,错误消失了,但我仍然有这个错误:imgur.com/amSWNWc【参考方案3】:

确保您有正确的布局,并且 RecyclerView id 在布局内。否则,您将收到此错误。我有同样的问题,然后我注意到布局错误。

    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); 

【讨论】:

【参考方案4】:

我遇到了同样的问题。当我使用此代码调用上下文时得到了解决方案。我使用网格布局。如果你使用另一个,你可以改变。

   recyclerView.setLayoutManager(new GridLayoutManager(getActivity(),1));

如果您有要设置的适配器。所以你可以按照这个。只需调用 getContext

  adapter = new Adapter(getContext(), myModelList);

如果要显示 Toast,请使用上面相同的内容

   Toast.makeText(getContext(), "Error in "+e, Toast.LENGTH_SHORT).show();

希望这会奏效。

快乐编码

【讨论】:

以上是关于在 Fragment 中显示 RecyclerView的主要内容,如果未能解决你的问题,请参考以下文章

在 Fragment 中显示 RecyclerView

fragment中的fragment如何显示出来

渣渣学安卓-----fragment显示

记录Fragment的显示时长

Listview 项目未在 Fragment Android 中显示

如何在 Fragment 实现中显示不同的活动?