【问题标题】:Android - RecyclerView inside of Fragment - NullPointerExceptionAndroid - 片段内的 RecyclerView - NullPointerException
【发布时间】:2015-03-10 18:40:54
【问题描述】:

我正在尝试在Fragment 中使用RecyclerView(在ViewPager 中使用它),但是当我尝试执行时得到了NullPointerException

 Process: com.yomansk8.birthdaysoundboard, PID: 4448
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.widget.RecyclerView$LayoutManager.onMeasure(android.support.v7.widget.RecyclerView$Recycler, android.support.v7.widget.RecyclerView$State, int, int)' on a null object reference
        at android.support.v7.widget.RecyclerView.onMeasure(RecyclerView.java:1764)
        at android.view.View.measure(View.java:17430)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
        at android.view.View.measure(View.java:17430)
        at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1456)
        at android.view.View.measure(View.java:17430)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
        at android.view.View.measure(View.java:17430)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
        at android.view.View.measure(View.java:17430)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
        at android.view.View.measure(View.java:17430)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463)
        at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1436)
        at android.widget.LinearLayout.measureVertical(LinearLayout.java:722)
        at android.widget.LinearLayout.onMeasure(LinearLayout.java:613)
        at android.view.View.measure(View.java:17430)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
        at android.view.View.measure(View.java:17430)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463)
        at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1436)
        at android.widget.LinearLayout.measureVertical(LinearLayout.java:722)
        at android.widget.LinearLayout.onMeasure(LinearLayout.java:613)
        at android.view.View.measure(View.java:17430)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
        at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2560)
        at android.view.View.measure(View.java:17430)
        at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2001)
        at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1166)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1372)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1054)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5779)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
        at android.view.Choreographer.doCallbacks(Choreographer.java:580)
        at android.view.Choreographer.doFrame(Choreographer.java:550)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5221)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

首先,这是我的片段的布局,它只包含一个RecyclerView

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/recyclerDivers"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="?attr/actionBarSize"
android:clipToPadding="false"/>

这是我的片段:

package com.yomansk8.birthdaysoundboard.Fragments;

import android.app.Activity;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBar;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.yomansk8.birthdaysoundboard.Adapters.RecyclerViewAdapter;
import com.yomansk8.birthdaysoundboard.GenerateDatas;
import com.yomansk8.birthdaysoundboard.MainActivity;
import com.yomansk8.birthdaysoundboard.Models.ViewModel;
import com.yomansk8.birthdaysoundboard.R;
import com.yomansk8.birthdaysoundboard.ScrollManager;

import java.util.List;

/**
 * Created by Yohann on 09/03/2015.
 */
public class DiversFragment extends Fragment implements  RecyclerViewAdapter.OnItemClickListener {

private MediaPlayer mPlayer = null;
private Toolbar toolbar;
private RecyclerView recyclerView;
private GridLayoutManager mLayoutManager;
private RecyclerViewAdapter adapter;
private  List<ViewModel> items;

@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.fragment_divers, container, false);

    toolbar = ((MainActivity)getActivity()).getToolbar();

    recyclerView = (RecyclerView) v.findViewById(R.id.recyclerDivers);
    recyclerView.setHasFixedSize(true);

    items = GenerateDatas.getAmbianceList();


    adapter = new RecyclerViewAdapter(items);


    /*toolbar.post(new Runnable() {
        @Override public void run() {
            ScrollManager manager = new ScrollManager();
            manager.attach(recyclerView);
            manager.addView(toolbar, ScrollManager.Direction.UP);
            manager.setInitialOffset(toolbar.getHeight());
        }
    });*/
    Log.v("TEST", "onCreateView()");
    return v;

}

@Override
public void onViewCreated(View view , Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    Log.v("TEST", "onViewCreated()");
    mLayoutManager = new GridLayoutManager(getActivity(), 3);
    recyclerView.setLayoutManager(mLayoutManager);
    adapter.setOnItemClickListener(this);
    recyclerView.setAdapter(adapter);

}

@Override public void onItemClick(View view, ViewModel viewModel) {
    // Lire le son ici
    Integer sound = getResources().getIdentifier(viewModel.getSound(), "raw", getActivity().getPackageName());
    playSound(sound);
}

private void playSound(int resId) {
    if(mPlayer != null) {
        mPlayer.stop();
        mPlayer.release();
    }
    mPlayer = MediaPlayer.create(getActivity(), resId);
    mPlayer.start();
}

@Override
public void onPause() {
    super.onPause();
    if(mPlayer != null) {
        mPlayer.stop();
        mPlayer.release();
    }
}

}

我还尝试将我的RecyclerView 的初始化放在onCreateViewonViewCreated 中,但没有成功。

有什么想法吗?

编辑:

这是我Adapter的代码:

package com.yomansk8.birthdaysoundboard.Adapters;

import android.os.Handler;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.squareup.picasso.Picasso;
import com.yomansk8.birthdaysoundboard.R;
import com.yomansk8.birthdaysoundboard.Models.ViewModel;

import java.util.List;

/**
 * Created by Yohann on 19/02/2015.
 */
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> implements View.OnClickListener {

private List<ViewModel> items;
private OnItemClickListener onItemClickListener;

public RecyclerViewAdapter(List<ViewModel> items) {

    this.items = items;
}

public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
    this.onItemClickListener = onItemClickListener;
}

@Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_recycler, parent, false);
    v.setOnClickListener(this);
    return new ViewHolder(v);
}

@Override public void onBindViewHolder(ViewHolder holder, int position) {
    ViewModel item = items.get(position);
    holder.text.setText(item.getText());
    holder.image.setImageBitmap(null);
    Integer mImage = holder.image.getResources().getIdentifier(item.getImage(), "drawable", holder.image.getContext().getPackageName());
    Picasso.with(holder.image.getContext()).load(mImage).into(holder.image);
    holder.itemView.setTag(item);
}

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

@Override public void onClick(final View v) {
    // Give some time to the ripple to finish the effect
    if (onItemClickListener != null) {
        new Handler().postDelayed(new Runnable() {
            @Override public void run() {
                onItemClickListener.onItemClick(v, (ViewModel) v.getTag());
            }
        }, 200);
    }
}

protected static class ViewHolder extends RecyclerView.ViewHolder {
    public ImageView image;
    public TextView text;

    public ViewHolder(View itemView) {
        super(itemView);
        image = (ImageView) itemView.findViewById(R.id.image);
        text = (TextView) itemView.findViewById(R.id.text);
    }
}

public interface OnItemClickListener {

    void onItemClick(View view, ViewModel viewModel);

}
}

【问题讨论】:

  • 我和你有同样的问题。作为一种临时方法,我将其设置为 GONE,然后在单击 Button 时显示它,但这不是一个好的解决方案,您最终在 1 个月后解决了吗?
  • @Yomansk8 出于好奇,您为什么使用onViewCreated() 方法?您可以在onCreateView() 中做您想做的所有事情。
  • 在写这篇文章的时候,我使用了onViewCreated(),因为我尝试了很多解决方案来使它工作(我在原来的帖子中说过)。但是因为我已经把所有东西都移到了onCreateView()。我的问题现在已经解决了,它只是从另一个项目中复制/粘贴的错误......我感到羞耻...... ^^
  • 我在 onCreateView() 中进行了所有初始化和设置,但错误仍然存​​在:/ 在滑动 TabLayout 下的 ViewPager 下的片段中使用 RV 执行相同操作。
  • @MFaisalHyder 您是否尝试过此线程中提供的所有解决方案?就我而言,这是一个简单的复制/粘贴错误,让我夸大了错误的布局。否则,请向我们展示您的代码,以便我们查看。

标签: java android android-fragments android-recyclerview


【解决方案1】:

我想你和我一样使用过旧版本的 recyclerview。我采用了修订版recyclerview-20.0.0 第一个发布版本,当然出现了异常。所以我升级了我的android sdk,然后将最新版本22.1.1(支持-v4 和recyclerview-v7 jars)复制到我的项目的库中,然后我的项目就可以工作了。

为了防止我团队的后续人员混淆版本,我将这两个 jar 命名为包含修订信息:

我项目的 libs 目录中的 jars :

android-support-v4-22.1.1.jar

android-support-v7-recyclerview-22.1.1.jar




在此之前,我也在修订版 20.0.0 中找到了一个解决方案,我创建了一个名为 MyRecyclerView 的小部件,它从 RecyclerView 扩展而来,然后在构造函数中新建了一个粗略的 LayoutManager。

public class MyRecyclerView extends RecyclerView {
    public MyRecyclerView(Context context) {
        this(context, null);
    }

    public MyRecyclerView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyRecyclerView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        setLayoutManager(new LayoutManager() {
            @Override
            public LayoutParams generateDefaultLayoutParams() {
                return null;
            }
        });
    }
}

它可以工作,但不是完美的方法。



顺便说一句,正如@yigit 在他的answer 中所说,这是缺乏与IDE 的集成未来会有更好的集成

【讨论】:

    【解决方案2】:

    为您的片段尝试这种布局:

    <?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="wrap_content"
       android:orientation="vertical" >
    
       <android.support.v7.widget.RecyclerView 
          xmlns:tools="http://schemas.android.com/tools"
          android:id="@+id/recyclerDivers"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:layout_alignParentTop="true"
          />
    </RelativeLayout>
    

    【讨论】:

    • 感谢您的回答。我试过你的xml,但总是出错。
    • 当我将我的 RecyclerView 直接放在一个 Activity 而不是 Fragment 中时,它可以完美地工作。所以我不认为这是适配器的问题。但如果你愿意,我可以添加适配器的代码 ;-)
    • 您是否尝试将所有代码从onViewCreated 移动到onCreateView
    • 是的,我尝试将其放入 onViewCreatedonCreateViewonAttachonCreatedActivity,但它们似乎都不起作用。
    • 我的 RecyclerView 在片段中,工作正常。我正在使用onViewCreate,我想至少setLayoutManager应该在onCreateView返回视图之前完成。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-14
    • 2012-08-17
    • 1970-01-01
    相关资源
    最近更新 更多