为什么recycleviewView的findviewbyposition()有时会返回null

时间:2016-05-27 14:42:41

标签: android android-recyclerview

这是我的代码:

public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState)
{

    View rootView =  inflater.inflate(R.layout.fragment_add_aircraft, container, false);

    recyclerView=(RecyclerView)rootView.findViewById(R.id.recyclerAircraftAdd);
    RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getActivity());
    recyclerView.setLayoutManager(layoutManager);
    adapter = new AircraftAdapter(getActivity(),path);
    recyclerView.setAdapter(adapter);
    Button button = (Button)rootView.findViewById(R.id.salvaereo);

    button.setOnClickListener(new View.OnClickListener()
    {
        @Override
        public void onClick(View v)
        {
          adapter = (AircraftAdapter)recyclerView.getAdapter();
          ParseObject aircraft = new ParseObject("Aircrafts");

           for(int i = 0;i<adapter.getItemCount(); i++)
           {
             if (i== 0)  //first card
             {
                View view = recyclerView.getLayoutManager().findViewByPosition(i);
                ImageView image = (ImageView)view.findViewById(R.id.aircfraftImg);
                image.setDrawingCacheEnabled(true);
                image.buildDrawingCache();
                Bitmap bm = image.getDrawingCache();
                ByteArrayOutputStream stream = new ByteArrayOutputStream();
                bm.compress(Bitmap.CompressFormat.PNG, 100, stream);
                byte[] bytes = stream.toByteArray();
                ParseFile file = new ParseFile("Image.jpg",bytes);
                aircraft.put("aircraft_image",file);

                 file.saveInBackground(new SaveCallback() {
                     @Override
                     public void done(ParseException e) {
                         Log.d("sa","tutto ok");
                     }
                 });

             }
             else if (i ==1) //second card
             {
                 View view = recyclerView.getLayoutManager().findViewByPosition(i);
                 EditText immatricolazione =(EditText)view.findViewById(R.id.immatricolazione);
                 EditText modello = (EditText)view.findViewById(R.id.modello);
                 EditText manifacturer = (EditText)view.findViewById(R.id.manifacturer);
                 EditText categoria = (EditText)view.findViewById(R.id.categoria);
                 EditText classe = (EditText)view.findViewById(R.id.classe);
                 EditText velocita = (EditText)view.findViewById(R.id.velocita);
                 EditText autonomia = (EditText)view.findViewById(R.id.autonomia);
                 EditText consumo = (EditText)view.findViewById(R.id.consumo);
                 EditText posti = (EditText)view.findViewById(R.id.postitotali);
                 EditText costo = (EditText)view.findViewById(R.id.costorario);

                 aircraft.put("re",immatricolazione.getEditableText().toString());
                 aircraft.put("ml",modello.getEditableText().toString());
                 aircraft.put("man",manifacturer.getEditableText().toString());
                 aircraft.put("Aircraft_Type",categoria.getEditableText().toString());
                 aircraft.put("ar",classe.getEditableText().toString());
                 aircraft.put("post",Integer.parseInt(posti.getEditableText().toString()));
                 aircraft.put("meter",Integer.parseInt(consumo.getEditableText().toString()));
                 aircraft.put("speed",Integer.parseInt(velocita.getEditableText().toString()));
                 aircraft.put("prezzi",Float.parseFloat(costo.getEditableText().toString()));
                 aircraft.put("fuel",Integer.parseInt(autonomia.getEditableText().toString()));
             }
             else if(i==2) //third card
             {
                 View view = recyclerView.getLayoutManager().findViewByPosition(i);
                 EditText description = (EditText) view.findViewById(R.id.description);
                 aircraft.put("descrizione", description.getEditableText().toString());

                 aircraft.put("User", ParseUser.getCurrentUser());

                 dialog = ProgressDialog.show(getActivity(), "", "Caricamento aereo in corso...", true);

                 aircraft.saveInBackground(new SaveCallback() {

                     public void done(ParseException e) {
                         dialog.dismiss();

                         if (e == null) {
                             new AlertDialog.Builder(getActivity())
                                     .setMessage("Caricamento aereo avvenuto con successo!")
                                     .setCancelable(false)
                                     .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                                         @Override
                                         public void onClick(DialogInterface dialog, int which) {

                                         }
                                     }).create().show();
                         } else {
                             new AlertDialog.Builder(getActivity())
                                     .setMessage("Non è stato possibile caricare l'aereo, riprova più tardi!")
                                     .setCancelable(false)
                                     .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                                         @Override
                                         public void onClick(DialogInterface dialog, int which) {

                                         }
                                     }).create().show();
                         }


                     }
                 });
             }
           }

        }
    });

    return rootView;
}

但是有这个问题:如果我给照片(第一张卡片)充电并按下按钮,它会上传照片,但如果我写入EditText,它会崩溃并给我这个错误:

  

进程:com.run.flyproject,PID:10796                                                                                  java.lang.NullPointerException:尝试调用虚方法&#39; android.view.View android.view.View.findViewById(int)&#39;在null对象引用上                                                                                      在com.run.flyproject.Fragments.AddAircraftFragment $ 1.onClick(AddAircraftFragment.java:78)                                                                                      在android.view.View.performClick(View.java:4756)                                                                                      在android.view.View $ PerformClick.run(View.java:19749)                                                                                      在android.os.Handler.handleCallback(Handler.java:739)                                                                                      在android.os.Handler.dispatchMessage(Handler.java:95)                                                                                      在android.os.Looper.loop(Looper.java:135)                                                                                      在android.app.ActivityThread.main(ActivityThread.java:5253)                                                                                      at java.lang.reflect.Method.invoke(Native Method)                                                                                      在java.lang.reflect.Method.invoke(Method.java:372)                                                                                      在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:899)                                                                                      在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

3 个答案:

答案 0 :(得分:2)

并非这是一个明确的答案(明确的答案是&#34;您的适配器数量与适配器的可用视图不一致&#34;),但我的评论可能是有点混乱。你可以这样做......

public class YourAdapter extends RecyclerView.Adapter<YourViewHolder>{

    private boolean mSaveImages = false;
    private SparseArray<Boolean> mImageSavedFlags = new SparseArray<>();

    public void toggleSaveStatus(){
        mSaveImages = !mSaveImages;
    }

    // ... your code

    @Override
    public void onBindViewHolder(YourViewHolder holder, final int position) {
        // Could also manage this in a loop or something
        // in your constructor/when you set your adapter data
        // but this will set our SparseArray
        if(mImageSavedFlags.get(position) == null)
            mImageSavedFlags.put(position, false);

        // ... your code
        if(mSaveImages && !mImageSavedFlags.get(position){
            // ... save your image
            mImageSavedFlags.put(position, true);
        }
    }

    // ... your code
}

这样,无论何时尝试绑定视图,都可以检查是否要保存ImageViews源,如果还没有保存它,如果你还没有保存源和更新SparseArray。

要切换您的状态,请执行以下操作

button.setOnClickListener(new View.OnClickListener()
{
    @Override
    public void onClick(View v){
        adapter.toggleSaveStatus();
    }
}

值得注意的是,这只会在切换保存设置后保存实际滚动到的图像。我想你可以强制滚动你的RecyclerView,但那是另一回事。

同样重要的是要意识到,如果您正在执行某些操作,例如从URL或基于位置或其他内容的绘图加载图像,您实际上不需要使用ImageView加载源,然后才能保存它,有很多方法(包括库)可以保存尚未明确加载到您的应用程序中的图像,这将完全消除在此过程中包含适配器的需要。

我相信这不是唯一的方法,我相信这不是最好的答案,但我的评论再次让人感到有些困惑。

答案 1 :(得分:0)

NullPointerException返回recyclerView.getLayoutManager().find...时,您将获得null,而第二个问题是您无法按位置查看,请recyclerView.getLayoutManager().getChildCount()确认您有任何问题该指数的孩子

答案 2 :(得分:0)

您可以同时使用

recyclerViewInstance.findViewHolderForAdapterPosition(adapterPosition)和 recyclerViewInstance.findViewHolderForLayoutPosition(layoutPosition)。 确保RecyclerView视图使用两种类型的位置

适配器位置:项目在适配器中的位置。这是Adapter的观点。 布局位置:项目在最新布局计算中的位置。这是从LayoutManager的角度来看的位置。 你应该对findViewHolderForLayoutPosition(layoutPosition)使用getAdapterPosition()作为findViewHolderForAdapterPosition(adpterPosition)和getLayoutPosition()。

获取一个成员变量来保存recyclelerview适配器和其他成员变量中先前选择的项目位置,以检查用户是否第一次点击。

附上示例代码和屏幕截图,以获取更多信息。

public class MainActivity extends AppCompatActivity {     

private RecyclerView mRecyclerList = null;    
private RecyclerAdapter adapter = null;    

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

    mRecyclerList = (RecyclerView) findViewById(R.id.recyclerList);    
}    

@Override    
protected void onStart() {    
    RecyclerView.LayoutManager layoutManager = null;    
    String[] daysArray = new String[15];    
    String[] datesArray = new String[15];    

    super.onStart();    
    for (int i = 0; i < daysArray.length; i++){    
        daysArray[i] = "Sunday";    
        datesArray[i] = "12 Feb 2017";    
    }    

    adapter = new RecyclerAdapter(mRecyclerList, daysArray, datesArray);    
    layoutManager = new LinearLayoutManager(MainActivity.this);    
    mRecyclerList.setAdapter(adapter);    
    mRecyclerList.setLayoutManager(layoutManager);    
}    
}    


public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.MyCardViewHolder>{          

private final String TAG = "RecyclerAdapter";        
private Context mContext = null;        
private TextView mDaysTxt = null, mDateTxt = null;    
private LinearLayout mDateContainerLayout = null;    
private String[] daysArray = null, datesArray = null;    
private RecyclerView mRecyclerList = null;    
private int previousPosition = 0;    
private boolean flagFirstItemSelected = false;    

public RecyclerAdapter(RecyclerView mRecyclerList, String[] daysArray, String[] datesArray){    
    this.mRecyclerList = mRecyclerList;    
    this.daysArray = daysArray;    
    this.datesArray = datesArray;    
}    

@Override    
public MyCardViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {    
    LayoutInflater layoutInflater = null;    
    View view = null;    
    MyCardViewHolder cardViewHolder = null;    
    mContext = parent.getContext();    
    layoutInflater = LayoutInflater.from(mContext);    
    view = layoutInflater.inflate(R.layout.date_card_row, parent, false);    
    cardViewHolder = new MyCardViewHolder(view);    
    return cardViewHolder;    
}    

@Override    
public void onBindViewHolder(MyCardViewHolder holder, final int position) {    
    mDaysTxt = holder.mDaysTxt;    
    mDateTxt = holder.mDateTxt;    
    mDateContainerLayout = holder.mDateContainerLayout;    

    mDaysTxt.setText(daysArray[position]);    
    mDateTxt.setText(datesArray[position]);    

    if (!flagFirstItemSelected){    
        mDateContainerLayout.setBackgroundColor(Color.GREEN);    
        flagFirstItemSelected = true;    
    }else {    
        mDateContainerLayout.setBackground(null);    
    }    
}    

@Override    
public int getItemCount() {    
    return daysArray.length;    
}    

class MyCardViewHolder extends RecyclerView.ViewHolder{    
    TextView mDaysTxt = null, mDateTxt = null;    
    LinearLayout mDateContainerLayout = null;    
    LinearLayout linearLayout = null;    
    View view = null;    
    MyCardViewHolder myCardViewHolder = null;    

    public MyCardViewHolder(View itemView) {    
        super(itemView);    
        mDaysTxt = (TextView) itemView.findViewById(R.id.daysTxt);    
        mDateTxt = (TextView) itemView.findViewById(R.id.dateTxt);    
        mDateContainerLayout = (LinearLayout) itemView.findViewById(R.id.dateContainerLayout);    

        mDateContainerLayout.setOnClickListener(new View.OnClickListener() {    
            @Override    
            public void onClick(View v) {    
                LinearLayout linearLayout = null;    
                View view = null;    

                if (getAdapterPosition() == previousPosition){    
                    view = mRecyclerList.findViewHolderForAdapterPosition(previousPosition).itemView;    
                    linearLayout = (LinearLayout) view.findViewById(R.id.dateContainerLayout);    
                    linearLayout.setBackgroundColor(Color.GREEN);    
                    previousPosition = getAdapterPosition();    

                }else {    
                    view = mRecyclerList.findViewHolderForAdapterPosition(previousPosition).itemView;    
                    linearLayout = (LinearLayout) view.findViewById(R.id.dateContainerLayout);    
                    linearLayout.setBackground(null);    

                    view = mRecyclerList.findViewHolderForAdapterPosition(getAdapterPosition()).itemView;    
                    linearLayout = (LinearLayout) view.findViewById(R.id.dateContainerLayout);    
                    linearLayout.setBackgroundColor(Color.GREEN);    
                    previousPosition = getAdapterPosition();    
                }    
            }    
        });    
    }    
}       

} 1

screen shot 1 scrren shot 2