再次向上滚动后,带有 Glide 的 RecyclerView 导致 NullPointer

Posted

技术标签:

【中文标题】再次向上滚动后,带有 Glide 的 RecyclerView 导致 NullPointer【英文标题】:RecyclerView with Glide causing NullPointer after scrolling up again 【发布时间】:2017-01-15 09:13:29 【问题描述】:

这是我的适配器类:

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

        View view = inflater.inflate(R.layout.container_accommodation,parent,false);
        MyHolder holder = new MyHolder(view);
        holder.setIsRecyclable(false);
        return holder;
    

 @Override
 public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) 

        MyHolder myHolder= (MyHolder) holder;
        Accommodation current = data.get(position);
        Picasso.with(context).load("http://10.0.2.2:18180/AAFS/Accommodations/"+current.AccommoID+"/Accomm_Images/"+current.AccommoMainImage.ImageName)
               .error(R.drawable.error)
                .into(myHolder.imageView);

    

这是我尝试再次向上滚动时遇到的错误,向下滚动可以正常工作。

致命异常:主要 java.lang.NullPointerException 在 com.example.phuluso.aafs.AdapterAccommodation.onBindViewHolder(AdapterAccommodation.java:73) 在 android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:5471) 在 android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:5504) 在 android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4741) 在 android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4617) 在 android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1994) 在 android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1390) 在 android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1353) 在 android.support.v7.widget.LinearLayoutManager.scrollBy(LinearLayoutManager.java:1180) 在 android.support.v7.widget.LinearLayoutManager.scrollVerticallyBy(LinearLayoutManager.java:1031) 在 android.support.v7.widget.RecyclerView$ViewFlinger.run(RecyclerView.java:4061) 在 android.view.Choreographer$CallbackRecord.run(Choreographer.java:725) 在 android.view.Choreographer.doCallbacks(Choreographer.java:555) 在 android.view.Choreographer.doFrame(Choreographer.java:524) 在 android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711) 在 android.os.Handler.handleCallback(Handler.java:615) 在 android.os.Handler.dispatchMessage(Handler.java:92) 在 android.os.Looper.loop(Looper.java:137) 在 android.app.ActivityThread.main(ActivityThread.java:4944) 在 java.lang.reflect.Method.invokeNative(Native Method) 在 java.lang.reflect.Method.invoke(Method.java:511) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805) 在 dalvik.system.NativeStart.main(Native Method)

任何帮助都会很棒。

谢谢。

【问题讨论】:

粘贴适配器类的完整代码。 发布您的完整适配器代码。错误日志不够 在下面添加了完整的代码 AdapterAccommodation.java 文件中的第 73 行是什么? 【参考方案1】:
public class AdapterAccommodation extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements Filterable 

    private Context context;
    private LayoutInflater inflater;
    List<Accommodation> data = Collections.emptyList();
    List<Accommodation> mStringFilterList;
    ValueFilter valueFilter;


    public AdapterAccommodation(Context context,List<Accommodation>data)
    
        this.context = context;
        inflater = LayoutInflater.from(context);
        this.data = data;
        mStringFilterList = data;

       

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, final int viewType) 

        View view = inflater.inflate(R.layout.container_accommodation,parent,false);
        MyHolder holder = new MyHolder(view);
        holder.setIsRecyclable(false);
        return holder;
    

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder,  int position) 

        MyHolder myHolder= (MyHolder) holder;

        Accommodation current = data.get(position);

        myHolder.textAccommoName.setText(current.AccommoName);
        myHolder.txtAddress.setText("Address: " + current.AccommoAddress.Street + ", " + current.AccommoAddress.Town + ", " + current.AccommoAddress.City);
        myHolder.txtGenderAllowed.setText("Gender Accommodated: " + current.AccommoDetails.GenderAllowed );
        myHolder.txtDistance.setText("Distance from nearest Campus: " + current.Distance + " km");
        myHolder.textCapacity.setText("Capacity: " + current.Capacity);
        myHolder.textNearestCampus.setText("Nearest Campus: "+ current.NearestCampus);


       Picasso.with(context).load("http://192.168.42.197:18180/AAFS/Accommodations/"+current.AccommoID+"/Accomm_Images/"+current.AccommoMainImage.ImageName)
               .error(R.drawable.error)
                .into(myHolder.imageView);

        myHolder.ratingBar.setRating(current.avgAccommoRating);
        myHolder.ratingBar.setIsIndicator(true);

        myHolder.btnAdditionalDetails.setOnClickListener( new View.OnClickListener() 
            @Override
            public void onClick(View v) 

                Intent intent = new Intent(context,AccommodationAdditionalDetails.class);

                intent.putExtra("EXTRA_AccommodationID",data.get(position).AccommoID);
                intent.putExtra("EXTRA_AccommodationName",data.get(position).AccommoName);
                intent.putExtra("EXTRA_AccommodationCapacity",data.get(position).Capacity);
                intent.putExtra("EXTRA_AccommodationNearestCampus",data.get(position).NearestCampus);
                intent.putExtra("EXTRA_AccommodationDistance",data.get(position).Distance);
                intent.putExtra("EXTRA_AccommodationAccreditedStatus",data.get(position).AccredStatus);
                intent.putExtra("EXTRA_AccommodationCity",data.get(position).AccommoAddress.City);
                intent.putExtra("EXTRA_AccommodationPostalAddress",data.get(position).AccommoAddress.PostalCode);
                intent.putExtra("EXTRA_LATITUDE",data.get(position).AccommoAddress.Lattitude);
                intent.putExtra("EXTRA_LONGITUDE",data.get(position).AccommoAddress.Longitude);
                intent.putExtra("EXTRA_NUM_SHARING",data.get( position ).AccommoDetails.NumTwoSharingRooms);
                intent.putExtra("EXTRA_NUM_SINGLE",data.get(position).AccommoDetails.NumSingleRooms);
                intent.putExtra("EXTRA_RENT_SINGLE",data.get(position).AccommoDetails.RentSingle);
                intent.putExtra("EXTRA_RENT_SHARING",data.get(position).AccommoDetails.RentSharing);

                intent.putExtra("EXTRA_WIFI",data.get(position).AccommoDetails.WiFi);
                intent.putExtra("EXTRA_LIBRARY",data.get(position).AccommoDetails.DedicatedStudyArea);
                intent.putExtra("EXTRA_GYM",data.get(position).AccommoDetails.Gym);
                intent.putExtra("EXTRA_SECURITY_LEVEL",data.get(position).AccommoDetails.SecurityLevel);
                intent.putExtra("EXTRA_PARKING_LOT",data.get(position).AccommoDetails.ParkingPort);
                intent.putExtra("EXTRA_GENDER",data.get(position).AccommoDetails.GenderAllowed);
                intent.putExtra("EXTRA_TRANSPORT",data.get(position).AccommoDetails.TransportShuttle);
                intent.putExtra("EXTRA_WASHING_MACHINE",data.get(position).AccommoDetails.WashingMachine);
                intent.putExtra("EXTRA_NUM_BATHROOM",data.get( position ).AccommoDetails.NumBathrooms);
                intent.putExtra("EXTRA_CLEANING_SERVICE",data.get( position ).AccommoDetails.CleaningService);

                context.startActivity(intent);

                SharedPreferences settings = enter code herePreferenceManager.getDefaultSharedPreferences(context);
                SharedPreferences.Editor editor = settings.edit();
                editor.putString("ACCOMMO_LATITUDE",data.get(position).AccommoAddress.Lattitude );
                editor.commit();

                SharedPreferences setting1 = PreferenceManager.getDefaultSharedPreferences(context);
                SharedPreferences.Editor editor1 = settings.edit();
                editor.putString("ACCOMMO_LONGITUDE",data.get(position).AccommoAddress.Longitude );
                editor.commit();


            
         );
    

    @Override

    public int getItemCount() 
        return data.size();
    

    class MyHolder extends RecyclerView.ViewHolder

        TextView textAccommoName;
       // ImageView ivAccommodation;
        TextView textCapacity;
        TextView textNearestCampus;
        TextView txtAddress;
        TextView txtGenderAllowed;
        TextView txtDistance;
        Button btnAdditionalDetails;
        RatingBar ratingBar;
        ImageView imageView ;
        public MyHolder(View itemView) 
            super(itemView);

            textAccommoName = (TextView)itemView.findViewById(R.id.textAccommodationName);
            txtAddress = (TextView)itemView.findViewById(R.id.txtAddress );
            txtGenderAllowed = (TextView)itemView.findViewById( R.id.txtGenderAllowed );
            txtDistance = (TextView)itemView.findViewById( R.id.textDistanceFromNearestCampus );
            imageView = (ImageView)itemView. findViewById(R.id.imageview);
           // ivAccommodation = (ImageView)itemView.findViewById(R.id.img);
            textCapacity = (TextView)itemView.findViewById(R.id.textCapacity);
            textNearestCampus = (TextView)itemView.findViewById(R.id.textNearestCampus);
            btnAdditionalDetails = (Button)itemView.findViewById(R.id.btnAdditionalDetails);
            ratingBar = (RatingBar)itemView.findViewById(R.id.ratingBar);

        

    

    @Override
    public Filter getFilter() 
        if (valueFilter == null) 
            valueFilter = new ValueFilter();
        
        return valueFilter;
    


    private class ValueFilter extends Filter 
        @Override
        protected FilterResults performFiltering(CharSequence constraint) 
            FilterResults results = new FilterResults();

            if (constraint != null && constraint.length() > 0) 
                ArrayList<Accommodation> filterList = new ArrayList<Accommodation>();
                for (int i = 0; i < mStringFilterList.size(); i++) 
                    if ( (mStringFilterList.get(i).AccommoName.toUpperCase() )
                            .contains(constraint.toString().toUpperCase())) 

                        Accommodation accommodation = new Accommodation();
                        accommodation.AccommoName = mStringFilterList.get(i).AccommoName;
                        accommodation.AccommoDetails.GenderAllowed  = mStringFilterList.get(i).AccommoDetails.GenderAllowed;
                        accommodation.AccommoAddress.Town  = mStringFilterList.get(i).AccommoAddress.Town;
                        accommodation.AccommoAddress.City =  mStringFilterList.get(i).AccommoAddress.City;
                        accommodation.Capacity =  mStringFilterList.get(i).Capacity;
                        accommodation.Distance =  mStringFilterList.get(i).Distance;
                        accommodation.AccommoAddress.Street   =  mStringFilterList.get(i).AccommoAddress.Street;
                        accommodation.NearestCampus =  mStringFilterList.get(i).NearestCampus;
                        accommodation.avgAccommoRating = mStringFilterList.get(i).avgAccommoRating;

                        filterList.add(accommodation);
                    
                
                results.count = filterList.size();
                results.values = filterList;
             else 
                results.count = mStringFilterList.size();
                results.values = mStringFilterList;
            
            return results;

        

        @Override
        protected void publishResults(CharSequence constraint,
                                      FilterResults results) 
            data = (ArrayList<Accommodation>) results.values;
            notifyDataSetChanged();
        




【讨论】:

【参考方案2】:

您是否覆盖了适配器中的 getItemCount 方法?

@Override
public int getItemCount()
    return data.size();

onBindViewHolder(VH holder, int position) 方法似乎提供了无效的位置参数。因此,当您从数据集合中获取住宿时,它会返回 null。您使用什么类型的收藏品来保存住宿?

【讨论】:

住宿作为一种类型【参考方案3】:

好的,现在我看到了您的适配器代码,我认为问题很可能出在您的过滤器实现上。尝试将您的 publishResults 方法更改为:

@Override
protected void publishResults(CharSequence constraint,
                                  FilterResults results) 
    if(results.count > 0)
        data.clear();
        data.addAll(results.values);
        notifyDataSetChanged();
    else
        notifyDataSetInvalidated();
    

已编辑 - NPE 在尝试访问其中一个住宿对象的 AccommoMainImage 属性时发生。

添加了一个空检查来解决问题:

if(current.AccommoMainImage != null)
    Picasso.with(context).load("http://10.0.2.2:18180/AAFS/Accom‌​modations/"+current.‌​AccommoID+"/Accomm_I‌​mages/"+current.Acco‌​mmoMainImage.ImageNa‌​me) .error(R.drawable.error) .into(myHolder.imageView);

【讨论】:

好的,所以当前的住宿为空。我认为您的基础住宿集合(数据)被您的过滤器类的publishResults 方法或permformFiltering 方法弄乱了。您是否将更改应用到 publishResults 方法? 要么,要么其中一个住宿对象有一个空的 AccommoMainImage 属性,你应该添加一个空检查:if(current.AccommoMainImage != null) Picasso.with(context).load("http://10.0.2.2:18180/AAFS/Accommodations/"+current.AccommoID+"/Accomm_Images/"+current.AccommoMainImage.ImageName) .error(R.drawable.error) .into(myHolder.imageView); 谢谢这是正确的,我在列表中的最后一个 AccommoMainImage 是 null 看不到。非常感谢 没有问题的人,如果有机会,请给我的答案投赞成票 当然。我该怎么做?

以上是关于再次向上滚动后,带有 Glide 的 RecyclerView 导致 NullPointer的主要内容,如果未能解决你的问题,请参考以下文章

如果向上滚动,UITableview 标题不会再次显示

UITableView 在 reloadData 上向上滚动

如何修改 Sliverappbar 以便在向上滚动时可以看到带有 FlexibleSpaceBar 的背景图像?

带有滑动手势的运动布局 + SwipeRefreshLayout + RecyclerView 错误错误行为向上滚动

除非用户向上滚动,否则保持溢出 div 滚动到底部

错误 ListBox 使用 DrawItem 向上滚动 - 向下滚动