web-dev-qa-db-fra.com

java.lang.NullPointerException sur Android.support.v7.widget.RecyclerView.onMeasure

J'essaie d'utiliser RecyclerView avec RecyclerView.Adapter mais voici quelque chose qui ne va pas. Je poste mon code ci-dessous:

Disposition:

   <Android.support.v7.widget.RecyclerView
    xmlns:tools="http://schemas.Android.com/tools"
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:id="@+id/topic_view"
    Android:scrollbars="vertical"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent" />

topic_tile.xml:

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="@dimen/tile_height">

    <com.makeramen.RoundedImageView
        xmlns:app="http://schemas.Android.com/apk/res-auto"
        Android:id="@+id/avatar"
        Android:padding="16dp"
        app:riv_corner_radius="72dp"
        Android:layout_height="72dp"
        Android:layout_width="72dp"
        />

    <LinearLayout
        Android:id="@+id/text_layout"
        Android:orientation="vertical"
        Android:paddingTop="@dimen/text_padding_top_and_bottom"
        Android:paddingBottom="@dimen/text_padding_top_and_bottom"
        Android:paddingRight="16dp"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent">
        <TextView
            Android:id="@+id/title"
            Android:textSize="@dimen/primary_font"
            Android:paddingLeft="@dimen/text_padding_left"
            Android:textColor="#000000"
            Android:text="Title"
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"/>
        <TextView
            Android:id="@+id/author"
            Android:textSize="@dimen/secondary_font"
            Android:paddingLeft="@dimen/text_padding_left"
            Android:text="author"
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"/>
    </LinearLayout>
</RelativeLayout>

Voici dans onCreate()

public class TitleListActivity extends ActionBarActivity {

    private RecyclerView topic_view;
    private RecyclerView.LayoutManager mLayoutManager;
    private TitlelistAdapter adapter;

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

        .....

        topic_view = (RecyclerView)findViewById(R.id.topic_view);
        adapter = new TitlelistAdapter(topicList);

        topic_view.setHasFixedSize(true);
        mLayoutManager = new LinearLayoutManager(TitleListActivity.this);
        topic_view.setLayoutManager(mLayoutManager);
        topic_view.setItemAnimator(new DefaultItemAnimator());

        topic_view.setAdapter(adapter);

l'adaptateur:

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

    public List<Topic> topicList;

    public static class ViewHolder extends RecyclerView.ViewHolder{

        TextView title;
        TextView author;
        RoundedImageView avatar;

        public ViewHolder(View itemView) {
            super(itemView);

            title = (TextView)itemView.findViewById(R.id.title);
            author = (TextView)itemView.findViewById(R.id.author);
            avatar = (RoundedImageView)itemView.findViewById(R.id.avatar);
        }
    }

    public TitlelistAdapter(List<Topic> topicList){
        this.topicList = topicList;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {

        View itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.topic_tile,viewGroup,false);
        return new ViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(ViewHolder viewHolder, int i) {
        viewHolder.title.setText(topicList.get(i).title);
        viewHolder.author.setText(topicList.get(i).member.username);
    }

    @Override
    public long getItemId(int position) {
        return super.getItemId(position);
    }

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

Voici l'exception:

Java.lang.NullPointerException
        at Android.support.v7.widget.RecyclerView.onMeasure(RecyclerView.Java:1694)
        at Android.view.View.measure(View.Java:16497)
        at Android.view.ViewGroup.measureChildWithMargins(ViewGroup.Java:5125)
        at Android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.Java:1404)
        at Android.widget.LinearLayout.measureVertical(LinearLayout.Java:695)
        at Android.widget.LinearLayout.onMeasure(LinearLayout.Java:588)
        at Android.view.View.measure(View.Java:16497)
        at Android.view.ViewGroup.measureChildWithMargins(ViewGroup.Java:5125)
        at Android.widget.FrameLayout.onMeasure(FrameLayout.Java:310)
        at Android.view.View.measure(View.Java:16497)
        at Android.view.ViewGroup.measureChildWithMargins(ViewGroup.Java:5125)
        at Android.support.v7.internal.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.Java:453)
        at Android.view.View.measure(View.Java:16497)
        at Android.view.ViewGroup.measureChildWithMargins(ViewGroup.Java:5125)
        at Android.widget.FrameLayout.onMeasure(FrameLayout.Java:310)
        at Android.view.View.measure(View.Java:16497)
        at Android.view.ViewGroup.measureChildWithMargins(ViewGroup.Java:5125)
        at Android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.Java:1404)
        at Android.widget.LinearLayout.measureVertical(LinearLayout.Java:695)
        at Android.widget.LinearLayout.onMeasure(LinearLayout.Java:588)
        at Android.view.View.measure(View.Java:16497)
        at Android.view.ViewGroup.measureChildWithMargins(ViewGroup.Java:5125)
        at Android.widget.FrameLayout.onMeasure(FrameLayout.Java:310)
        at com.Android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.Java:2291)
        at Android.view.View.measure(View.Java:16497)
        at Android.view.ViewRootImpl.performMeasure(ViewRootImpl.Java:1912)
        at Android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.Java:1109)
        at Android.view.ViewRootImpl.performTraversals(ViewRootImpl.Java:1291)
        at Android.view.ViewRootImpl.doTraversal(ViewRootImpl.Java:996)
        at Android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.Java:5600)
        at Android.view.Choreographer$CallbackRecord.run(Choreographer.Java:761)
        at Android.view.Choreographer.doCallbacks(Choreographer.Java:574)
        at Android.view.Choreographer.doFrame(Choreographer.Java:544)
        at Android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.Java:747)
        at Android.os.Handler.handleCallback(Handler.Java:733)
        at Android.os.Handler.dispatchMessage(Handler.Java:95)
        at Android.os.Looper.loop(Looper.Java:136)
        at Android.app.ActivityThread.main(ActivityThread.Java:5001)
        at Java.lang.reflect.Method.invokeNative(Native Method)
        at Java.lang.reflect.Method.invoke(Method.Java:515)
        at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:785)
        at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:601)
        at dalvik.system.NativeStart.main(Native Method)

Est-ce quelque chose que je n'ai pas initié ou quelque chose que je devrais écrire davantage?

21
Randy

J'ai eu cette erreur lorsque mon RecyclerView n'avait pas de LayoutManager. L'ajout de ce code a résolu le problème:

recyclerView.setLayoutManager(new LinearLayoutManager(recyclerView.getContext()));
21
Dan Goldstein

Votre XML montre que vous avez deux Android espaces de noms qui devraient réellement vous donner une erreur car dans Android vous êtes autorisé à utiliser l'espace de noms une seule fois. Supprimez le linearLayout à partir de votre mise en page principale, car cela semble inutile. Vérifiez votre mise en page de ligne personnalisée, c'est-à-dire topic_tile ainsi que toute erreur similaire

<Android.support.v7.widget.RecyclerView 
    xmlns:tools="http://schemas.Android.com/tools"
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:id="@+id/topic_view"
    Android:scrollbars="vertical"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent" />

ÉDITER :

dans onCreate()

private RecyclerView.LayoutManager mLayoutManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        .
        . 
        .
        mLayoutManager = new LinearLayoutManager(this);
        recycleView.setLayoutManager(mLayoutManager);
    }
17
Android2390

Si vous rencontrez le même problème pour RecycleView à l'intérieur d'un fragment, essayez d'utiliser ce code.

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View rootView = inflater.inflate(R.layout.fragment_latest, container, false);

    // get recycler view
    mRecyclerView = (RecyclerView) rootView.findViewById(R.id.novel_item_list);

    //mRecyclerView.setHasFixedSize(true);

    // use a linear layout manager
    mLayoutManager = new LinearLayoutManager(getActivity());
    mRecyclerView.setLayoutManager(mLayoutManager);


    String[] abc = {"hi","how are you","this is recycler"};
    // specify an adapter (see also next example)
    mAdapter = new RecyclerViewAdapter(abc);
    mRecyclerView.setAdapter(mAdapter);
    return rootView;
}
11
MewX

Pour ceux qui essaient d'utiliser un ViewPager pour les onglets, et à l'intérieur de leurs onglets ont un RecyclerView qui provoque cette erreur folle, je suggère de reporter le gonflage en créant un autre fragment pour inclure uniquement le RecylerView.

Ce fichier xml est l'un de mes onglets qui contiennent une disposition de cadre au lieu d'un recycleur.

shop_most_views_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:orientation="vertical">

<FrameLayout
    Android:id="@+id/most_view_item_frameLayout"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:background="#f3f3f3" />
</LinearLayout>

sa classe Java

public class MostViews extends Fragment {
private String title;
private int page;
View convertedView;
RecyclerView grids;

public static MostViews newInstance(int page, String title) {
    MostViews fragmentFirst = new MostViews();
    Bundle args = new Bundle();
    args.putInt("someInt", page);
    args.putString("someTitle", title);
    fragmentFirst.setArguments(args);
    return fragmentFirst;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    page = getArguments().getInt("someInt", 0);
    title = getArguments().getString("someTitle");
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    convertedView = inflater.inflate(R.layout.shop_most_views_fragment, container, false);
    transitMasonaryLayoutFragmentIntoFramLayout();
    return convertedView;
}

private void transitMasonaryLayoutFragmentIntoFramLayout() {
    MasanoryLayout masanoryLayout = new MasanoryLayout();
    FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
    fragmentManager.beginTransaction()
            .add(R.id.most_view_item_frameLayout, masanoryLayout).commit();
}
}

nous avons donc une disposition de cadre pour y mettre notre fragment de recylcer.

shop_most_view_masanory_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:orientation="vertical" Android:layout_width="match_parent"
Android:layout_height="match_parent">

<Android.support.v7.widget.RecyclerView
    Android:id="@+id/mostViewsItem"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent" />
</LinearLayout>

sa classe Java

public class MasanoryLayout extends Fragment {
View convertedView;
RecyclerView grids;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    convertedView = inflater.inflate(R.layout.shop_most_view_masanory_fragment, container, false);
    grids = (RecyclerView) convertedView.findViewById(R.id.mostViewsItem);
    setLayoutManagerOnRecyclerView();
    MasonryAdapter adapter = new MasonryAdapter(initializeData());
    grids.setAdapter(adapter);
    return convertedView;
}

private void setLayoutManagerOnRecyclerView() {
    grids.setLayoutManager(new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL));
}

private List<StoreItem> initializeData() {
    List<StoreItem> storeItems = new ArrayList<>();
    storeItems.add(new StoreItem("احسان", "احسان", R.drawable.detailed_index_store));
    storeItems.add(new StoreItem("احسان", "احسان", R.drawable.clothstore));
    storeItems.add(new StoreItem("احسان", "احسان", R.drawable.detailed_index_store));
    storeItems.add(new StoreItem("احسان", "احسان", R.drawable.clothstore));
    storeItems.add(new StoreItem("احسان", "احسان", R.drawable.detailed_index_store));
    storeItems.add(new StoreItem("احسان", "احسان", R.drawable.detailed_index_store));
    storeItems.add(new StoreItem("احسان", "احسان", R.drawable.clothstore));

    return storeItems;
}
}

comme vous le voyez, votre FragmentPagerAdapter appellerait MostViews pour être gonflé et MostViews lui-même appelerait MasanoryLayout pour être gonflé. nous avons donc échappé au contexte FragmentPagerAdapter;)

1
Hassan Gilak

Vous devez définir LayoutManager pour RecycleView:

Actuellement, Android prend en charge 3 types de mises en page.

Si vous le souhaitez, cela semble normal ListView, utilisez LinearLayoutManager.

Si vous voulez que cela ressemble à une grille, utilisez GridLayoutManager.

Si vous voulez qu'il semble décalé, utilisez StaggeredGridLayoutManager

Constructeurs pour 3 types de dispositions ci-dessus

LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());

GridLayoutManager gridLayoutManager = new GridLayoutManager(getActivity(), 2);

StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(spanCount, StaggeredGridLayoutManager.HORIZONTAL);

Ensuite, vous définissez LinearLayout sur RecycleView (dans ce cas, j'ai utilisé LinearLayoutManager

recyclerView = (RecyclerView) view.findViewById(R.id.saved_recycle_view);
recyclerView.setHasFixedSize(true);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(context);
recyclerView.setLayoutManager(linearLayoutManager);

Quoi qu'il en soit, utilisez OttoBus Library pour passer les événements de l'adaptateur à Activity/Fragment contenant le RecycleView. Bonne chance !

1
Son Nguyen Thanh