在Fragment中显示RecyclerView

53

我正在尝试在Android Lollipop中使用新的RecyclerView,但遇到了问题。

我想在Fragment中接收一个带有图标和右侧有TextView的列表。

我找到了这个很棒的教程,学习如何设置RecyclerView。 我按照每个步骤进行操作,并仅更改了item_layout.xml以符合我的需求。

该项目没有任何错误,但是当它在我的设备上启动时,我遇到了这个错误:

java.lang.RuntimeException:无法启动活动ComponentInfo {com.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;
    }
}

可能出了什么问题?


5
你的xml布局文件中还有id为list的RecyclerView吗?如果没有,第二步中的recyclerView变量将为空。 - stkent
是的,我的xml中有一个id为“list”的RecyclerView。 - fredthemugwump
应该更清晰一些:在 activity_main.xml 文件中,对吧? - stkent
@stkent 我使用一个导航抽屉,当我点击抽屉中的某个项目时,它会打开一个活动。我的activity_main.xml包含一个带有抽屉的FrameLayout。我的RecyclerView在名为fragment_color.xml的XML文件中。 - fredthemugwump
4个回答

66

虽然这是一段时间之前提出的问题,但根据 @nacho_zona3 给出的答案以及之前处理片段的经验,问题在于视图在你尝试使用 findViewById() 方法在 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()调用中。需要进行一些重构,因为此方法中调用的所有变量和方法都必须是静态的。最终代码应如下:

对于您的片段,需要在onCreateView()的调用中进行一些重构。这是因为该方法中所调用的所有变量和方法都必须是静态的。最终代码应该如下所示:

(Note: The two translations above are equivalent, just worded slightly differently. Choose the one that matches your style guide or personal preference.)
 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()


2
替换为 this.getActivity()。 - swapyonubuntu
你也可以在片段的 'onCreateView' 中返回RecyclerView,因为本质上片段现在是一个RecyclerView。 - pcodex
我在 MyAdapter mAdapter = new MyAdapter(itemsData); 遇到了一个错误,它说 MyAdapter(android.context.Context, List<>) 中的 MyAdapter 不能应用于 (List<>)。 - Learn2Code
1
谢谢,伙计。我刚开始重新学习原生安卓开发,几年前创建了我的第一个应用程序,目标是v2.3.3,现在...让我们说一下事情或两件吧。哦天啊。 - clamum

36

在使用核心View膨胀视图后,在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支持库。 - fredthemugwump
“使用任何活动”是什么意思?反正我已经在使用支持库来实现导航抽屉了。 - fredthemugwump
我必须道歉,我不太擅长像Fragment这样的复杂事物。在“final FragmentActivity c = getActivity();”中,我应该写什么?当我用Activity代替FragmentActivity时,错误消失了,但我仍然有这个错误:http://imgur.com/amSWNWc - fredthemugwump
mLayoutManager = new LinearLayoutManager(getActivity()); - Dionysios Arvanitis
我可以问一下为什么你在一个Runnable中设置适配器吗? - Pointyhat
显示剩余3条评论

0
请确保您的布局正确,并且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); 

0

我遇到了同样的问题。当我使用这段代码调用上下文时,我找到了解决方案。我使用了网格布局。如果你使用其他布局,你可以进行更改。

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

如果你有适配器要设置,那么你可以按照这个步骤进行操作。只需调用getContext函数即可。
  adapter = new Adapter(getContext(), myModelList);

如果您需要显示Toast,请使用上面的相同方法。
   Toast.makeText(getContext(), "Error in "+e, Toast.LENGTH_SHORT).show();

希望这个能够运行。

愉快编程


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接