首页 > 解决方案 > java.lang.NullPointerException:尝试从空对象引用上的字段 RecyclerView$ViewHolder.itemView' 读取

问题描述

我有可扩展的卡片视图,我想在 15 秒后在位置 0 展开第一个卡片视图 折叠位置 0 在 15 秒后再次展开位置 1 我折叠位置 1 并展开位置 2。我已设法在 15 秒后展开位置 0 并展开位置,现在下一轮 15 秒崩溃并出现错误 java.lang.NullPointerException: Attempt to read from field 'android.view.View android.support.v7.widget.RecyclerView$ViewHolder.itemView' on a null object reference

这是我的适配器

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



private Context context;

private List<com.aw.governor.model.summary.ResponseDatum> mList = new ArrayList<>();
public static  ViewHolder viewHolder;

public SummeryAdapter(Context context , List<com.aw.governor.model.summary.ResponseDatum> mList){
    this.context = context;
    this.mList = mList;

}

public  class ViewHolder extends RecyclerView.ViewHolder{

    TextView average_header,tVheader,value;
    LinearLayout layout;
    ImageView image;
    FrameLayout frLayout;
   public ExpandableCardView main_profile_card;
    RecyclerView recyclerView;

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

        average_header =(TextView)itemView.findViewById(R.id.average_header);
        value = (TextView) itemView.findViewById(R.id.value);
        main_profile_card =(ExpandableCardView) itemView.findViewById(R.id.main_profile_card);
        recyclerView = (RecyclerView)itemView.findViewById(R.id.recyclerView);



    }
}


@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    View view = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.item_summary,parent , false);

    ViewHolder vh = new ViewHolder(view);

    return vh;
}

@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
    viewHolder = holder;
    final com.aw.governor.model.summary.ResponseDatum list = mList.get(position);
    holder.main_profile_card.setTitle(list.getLabel());
    holder.value.setText("KES "+String.valueOf(list.getAmount()));
    holder.average_header.setText(list.getAverageLabel()+": "+String.valueOf(roundTwoDecimals(list.getAverage())));
    PerformanceAdapter adapter = new PerformanceAdapter(context, list.getPerformance());
    adapter.notifyDataSetChanged();
    holder.recyclerView.setLayoutManager(new LinearLayoutManager(context));
    holder.recyclerView.setAdapter(adapter);
    holder.recyclerView.setHasFixedSize(false);



}



double roundTwoDecimals(double d)
{
    DecimalFormat twoDForm = new DecimalFormat("#.##");
    return Double.valueOf(twoDForm.format(d));
}

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

这是我的 Fragmet,我在哪里进行扩展

  static Handler h = new Handler();
static int delay = 15*1000; //1 second=1000 milisecond, 15*1000=15seconds
static   Runnable runnable;
static int Epxand =0;
static int Collaps =0;


public static void expandCard(int Position){
    Log.i("### expandCard ",String.valueOf(Position));
    ((ExpandableCardView) recyclerView.findViewHolderForAdapterPosition(Position).itemView.findViewById(R.id.main_profile_card)).expand();
}
public static void collapseCard(int Position){
    Log.i("### collapseCard ",String.valueOf(Position));
    ((ExpandableCardView) recyclerView.findViewHolderForAdapterPosition(Position).itemView.findViewById(R.id.main_profile_card)).collapse();
}

单击一个按钮它运行此代码

 expandCard(Epxand);
        h.postDelayed( runnable = new Runnable() {
            public void run() {
                collapseCard(Collaps);
                Epxand++;
                expandCard(Epxand);
                Collaps++;
                Log.i("###","15sec gone\n");
                h.postDelayed(runnable, (delay+1000));

            }
        }, delay);

错误日志

    04-27 11:36:47.769 20504-20504/com.aw.governor I/### expandCard: 0
04-27 11:36:52.772 20504-20504/com.aw.governor I/### collapseCard: 0
04-27 11:36:52.773 20504-20504/com.aw.governor I/### expandCard: 1
04-27 11:36:52.931 20504-20504/com.aw.governor I/###: 15sec gone
04-27 11:36:58.936 20504-20504/com.aw.governor I/### collapseCard: 1
04-27 11:36:58.937 20504-20504/com.aw.governor I/### expandCard: 2

    --------- beginning of crash
04-27 11:36:58.937 20504-20504/com.aw.governor E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.aw.governor, PID: 20504
    java.lang.NullPointerException: Attempt to read from field 'android.view.View android.support.v7.widget.RecyclerView$ViewHolder.itemView' on a null object reference
        at com.aw.governor.fragments.Home.expandCard(Home.java:178)
        at com.aw.governor.fragments.Home$3.run(Home.java:165)
        at android.os.Handler.handleCallback(Handler.java:815)
        at android.os.Handler.dispatchMessage(Handler.java:104)
        at android.os.Looper.loop(Looper.java:207)
        at android.app.ActivityThread.main(ActivityThread.java:5765)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:679)

在此处输入图像描述

这是我的片段类

    public class Home extends Fragment{


    public Home() {
        // Required empty public constructor
    }
   public static RecyclerView recyclerView;

    public static   Boolean ShowingEarnings = true;
    public  static Context context ;
   public static EarningsResponse earningsResponse;
   public static SummaryResponse summaryResponse;
  static ScrollView scrollView;

   public static EarningsAdapter adapter;


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

        scrollView =(ScrollView) rootView.findViewById(R.id.scrollView);

        context  = getActivity();

        ExecutiveAppDashboard(getActivity());


        return rootView;
    }

    public static void ExecutiveAppDashboard(final Context context){
        ShowingEarnings = true;
        MainActivity.back_arrow.setVisibility(View.GONE);
        Api.getVolley(context,  Api.ExecutiveAppDashboard, "", new Api.VolleyCallback() {
            @Override
            public void onSuccess(String result) {
                earningsResponse = Api.mGson.fromJson(result,EarningsResponse.class);
                if(earningsResponse.getStatusCode()==200){

                    adapter = new EarningsAdapter(context, earningsResponse.getResponseData());
                    adapter.notifyDataSetChanged();

                    recyclerView.setLayoutManager(new LinearLayoutManager(context));
                    recyclerView.setAdapter(adapter);
                    recyclerView.setHasFixedSize(false);

                }else {

                }
            }
        });
    }
    public static void ExecutiveAppTransactionSummary(final Context context){
        ShowingEarnings = false;
        Api.getVolley(context,  Api.ExecutiveAppTransactionSummary, "", new Api.VolleyCallback() {
            @Override
            public void onSuccess(String result) {
                 summaryResponse = Api.mGson.fromJson(result,SummaryResponse.class);
                if(summaryResponse.getStatusCode()==200){

                    SummeryAdapter adapter = new SummeryAdapter(context, summaryResponse.getResponseData());
                    adapter.notifyDataSetChanged();

                    recyclerView.setLayoutManager(new LinearLayoutManager(context));
                    recyclerView.setAdapter(adapter);
                    recyclerView.setHasFixedSize(false);

                }else {

                }
            }
        });
    }

    static double roundTwoDecimals(double d)
    {
        DecimalFormat twoDForm = new DecimalFormat("#.##");
        return Double.valueOf(twoDForm.format(d));
    }


    public static void voiceReport(){
        if(ShowingEarnings){
            MainActivity.speak(MainActivity.getGreetings()+" your excellency Governor Sonko. I am your personal assistant Samolita");

            for (ResponseDatum responseDatum:  earningsResponse.getResponseData()) {
                MainActivity.speak(responseDatum.getHeader()+" is "+responseDatum.getValue()+" Kenya shillings."+ "Average per hour is "+roundTwoDecimals(responseDatum.getAverage()));
            }

            MainActivity.speak("That's all I have for now."+ MainActivity.getSeeOffMessage());
           //MainActivity.switchOffMic(MainActivity.context);

        }else {

            MainActivity.speak("Your excellency.");

            for (com.aw.governor.model.summary.ResponseDatum responseDatum:  summaryResponse.getResponseData()) {
                MainActivity.speak(responseDatum.getLabel()+" is "+responseDatum.getAmount()+" Kenya shillings."+ "Average per hour is "+roundTwoDecimals(responseDatum.getAverage())+". ");

                for (Performance performance: responseDatum.getPerformance()) {
                    MainActivity.speak(performance.getPerformanceLabel()+" "+String.valueOf(performance.getPerformanceData().size()));

                    for (PerformanceDatum performanceDatum: performance.getPerformanceData()) {
                        MainActivity.speak(performanceDatum.getName()+" "+String.valueOf(performanceDatum.getAmount()+" Kenya Shillings")+" contributing "
                                +String.valueOf(roundTwoDecimals(performanceDatum.getPercentage())+"%")+" of "+responseDatum.getLabel());
                    }
                }
            }

            MainActivity.speak("That's all I have for now."+ MainActivity.getSeeOffMessage());

           // MainActivity.switchOffMic(MainActivity.context);


            expandCard(Epxand);
            h.postDelayed( runnable = new Runnable() {
                public void run() {
                    collapseCard(Collaps);
                    Epxand++;
                    expandCard(Epxand);
                    Collaps++;
                    Log.i("###","15sec gone\n");
                    h.postDelayed(runnable, (delay+1000));

                }
            }, delay);

        }
    }

    static Handler h = new Handler();
    static int delay = 15*1000; //1 second=1000 milisecond, 15*1000=15seconds
    static   Runnable runnable;
    static int Epxand =0;
    static int Collaps =0;


    public static void expandCard(int Position){
        Log.i("### expandCard ",String.valueOf(Position));
        ((ExpandableCardView) recyclerView.findViewHolderForAdapterPosition(Position).itemView.findViewById(R.id.main_profile_card)).expand();
    }
    public static void collapseCard(int Position){
        Log.i("### collapseCard ",String.valueOf(Position));
        ((ExpandableCardView) recyclerView.findViewHolderForAdapterPosition(Position).itemView.findViewById(R.id.main_profile_card)).collapse();
    }

}

这是xml

    <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:id="@+id/scrollView"
    android:layout_height="match_parent"
    tools:context="com.aw.governor.fragments.Home">
    <android.support.v7.widget.RecyclerView
        android:visibility="visible"
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />

</ScrollView>

标签: android

解决方案


Recyclerview 回收不可见的视图。因此,执行展开代码时,可能不会重新创建下一个展开位置。这就是 viewHolder 为空的原因。

您可以尝试某些事情:

  1. 在折叠和展开之间添加延迟。
  2. 使用 LayoutManager 检查扩展位置是否在视图中,然后扩展位置。
  3. 您可以尝试使用 NestedScrollView 而不是 ScrollView 并放入android:nestedScrollingEnabled="false"Recyclerview。它可能适用于您当前的代码,但请注意它是一个糟糕的 hack 并且不利于性能。

推荐阅读