问题
I try to create a ListView which showes my Pojos called "Baustelle". I wrote a Adapter and a ViewHolder as I learned it in school but the difference is that we only did it for the MainActivity in my school. Now i tried to use a Fragment for it but I always get this Error:
- "Attempt to invoke virtual method 'android.view.View android.view.View.findViewById(int)' on a null object reference"
This is my Fragment("Baustellenverwaltung") which also contains the Adapter and the ViewHolder
public class Bautellenverwaltung extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
List<Baustelle> list = new LinkedList<>();
list.add(new Baustelle(1,"Town 1",false, 0));
list.add(new Baustelle(2,"City 1234",false, 0));
ListView lv = (ListView)getView().findViewById(R.id.baustellenverwaltung_listview);
lv.setAdapter(new MyListAdapter(getActivity(),R.layout.list_item,list));
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_bautellenverwaltung, container, false);
}
private class MyListAdapter extends ArrayAdapter<Baustelle> {
private int layout;
public MyListAdapter( Context context, int resource, List<Baustelle> objects) {
super(context, resource, objects);
layout = resource;
}
@NonNull
@Override
public View getView(final int position, @Nullable View convertView, @NonNull ViewGroup parent) {
if(convertView == null){
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(layout,parent,false);
ViewHolder viewHolder = new ViewHolder();
viewHolder.detail.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(getContext(),"Detail Button from" + getItem(position).getName()+" pressed",Toast.LENGTH_SHORT).show();
}
});
viewHolder.loschen.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(getContext(),"Loschen Button from" + getItem(position).getName()+" pressed",Toast.LENGTH_SHORT).show();
}
});
viewHolder.mangel_detail.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(getContext(),"Mängel Button from" + getItem(position).getName()+" pressed",Toast.LENGTH_SHORT).show();
}
});
convertView.setTag(viewHolder);
}
else{
ViewHolder viewHolder = (ViewHolder)convertView.getTag();
viewHolder.id.setText(getItem(position).getId());
viewHolder.name.setText(getItem(position).getName());
viewHolder.mangel.setText(getItem(position).getAnzMangel());
}
return convertView;
}
}
public class ViewHolder{
private TextView id;
private TextView name;
private TextView mangel;
private Button detail;
private Button loschen;
private Button mangel_detail;
public ViewHolder(){
id = (TextView)getView().findViewById(R.id.baustellenverwaltung_textview_id);
name = (TextView)getView().findViewById(R.id.baustellenverwaltung_textview_name);
mangel = (TextView)getView().findViewById(R.id.baustellenverwaltung_textview_mangel);
detail = (Button)getView().findViewById(R.id.baustellenverwaltung_button_deatil);
loschen = (Button)getView().findViewById(R.id.baustellenverwaltung_button_loschen);
mangel_detail = (Button)getView().findViewById(R.id.baustellenverwaltung_button_mangel);
}
}
}
This is the .xml File which is inflated by the Fragment
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".presentation.Bautellenverwaltung">
<!-- TODO: Update blank fragment layout -->
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:id="@+id/baustellenverwaltung_listview"/>
</RelativeLayout>
That is the list_item.xml which ist the layout for one list item
<?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="match_parent">
<TextView
android:id="@+id/baustellenverwaltung_textview_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="20sp"
android:layout_marginTop="10sp"
android:text="TextView" />
<TextView
android:id="@+id/baustellenverwaltung_textview_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/baustellenverwaltung_textview_id"
android:layout_alignParentTop="true"
android:layout_marginLeft="20sp"
android:layout_marginTop="10sp"
android:text="TextView" />
<TextView
android:id="@+id/baustellenverwaltung_textview_mangel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/baustellenverwaltung_textview_name"
android:layout_alignParentTop="true"
android:layout_marginLeft="20sp"
android:layout_marginTop="10sp"
android:text="TextView" />
<CheckBox
android:id="@+id/baustellenverwaltung_checkbox_abgenommen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toRightOf="@+id/baustellenverwaltung_textview_mangel"
android:layout_marginLeft="20sp"
android:layout_marginTop="5sp"
android:text="CheckBox" />
<Button
android:id="@+id/baustellenverwaltung_button_deatil"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toRightOf="@+id/baustellenverwaltung_checkbox_abgenommen"
android:layout_marginLeft="20sp"
android:text="Detail" />
<Button
android:id="@+id/baustellenverwaltung_button_loschen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toRightOf="@+id/baustellenverwaltung_button_deatil"
android:layout_marginLeft="20sp"
android:text="Löschen" />
<Button
android:id="@+id/baustellenverwaltung_button_mangel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toRightOf="@+id/baustellenverwaltung_button_loschen"
android:layout_marginLeft="20sp"
android:text="Mängel" />
</RelativeLayout>
My Pojo "Baustelle"
public class Baustelle {
private int id;
private String name;
private boolean checked;
private int anzMangel;
public Baustelle(int id, String name, boolean checked, int anzMangel) {
this.id = id;
this.name = name;
this.checked = checked;
this.anzMangel = anzMangel;
}
public int getAnzMangel() {
return anzMangel;
}
public void setAnzMangel(int anzMangel) {
this.anzMangel = anzMangel;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isChecked() {
return checked;
}
public void setChecked(boolean checked) {
this.checked = checked;
}
}
StacktTrace
java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.view.View.findViewById(int)' on a null object reference
at at.htlpinkafeld.pfeifferdipl.presentation.Bautellenverwaltung.onCreateView(Bautellenverwaltung.java:84)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2354)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1419)
at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1740)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1809)
at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:799)
at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2580)
at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2367)
at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2322)
at android.support.v4.app.FragmentManagerImpl.execSingleAction(FragmentManager.java:2199)
at android.support.v4.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:651)
at android.support.v4.app.FragmentStatePagerAdapter.finishUpdate(FragmentStatePagerAdapter.java:167)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1236)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1084)
at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1614)
at android.view.View.measure(View.java:19734)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6120)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1464)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:758)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:640)
at android.view.View.measure(View.java:19734)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6120)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
at android.support.v7.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:139)
at android.view.View.measure(View.java:19734)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6120)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1464)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:758)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:640)
at android.view.View.measure(View.java:19734)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6120)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
at android.view.View.measure(View.java:19734)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6120)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1464)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:758)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:640)
at android.view.View.measure(View.java:19734)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6120)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
at com.android.internal.policy.DecorView.onMeasure(DecorView.java:687)
at android.view.View.measure(View.java:19734)
at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2271)
at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1358)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1607)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1246)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6301)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:871)
at android.view.Choreographer.doCallbacks(Choreographer.java:683)
at android.view.Choreographer.doFrame(Choreographer.java:619)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:857)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
回答1:
Your view hasn't been inflated yet in onCreate
on Fragments, try to move your code to onCreateView
:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_bautellenverwaltung, container, false);
List<Baustelle> list = new LinkedList<>();
list.add(new Baustelle(1,"Town 1",false, 0));
list.add(new Baustelle(2,"City 1234",false, 0));
ListView lv = view.findViewById(R.id.baustellenverwaltung_listview);
lv.setAdapter(new MyListAdapter(getActivity(),R.layout.list_item,list));
return view;
}
You also need to change your view holder to receive the inflated view:
ViewHolder viewHolder = new ViewHolder(convertView);
public class ViewHolder{
private TextView id;
private TextView name;
private TextView mangel;
private Button detail;
private Button loschen;
private Button mangel_detail;
public ViewHolder(View view){
id = (TextView)view.findViewById(R.id.baustellenverwaltung_textview_id);
name = (TextView)view.findViewById(R.id.baustellenverwaltung_textview_name);
mangel = (TextView)view.findViewById(R.id.baustellenverwaltung_textview_mangel);
detail = (Button)view.findViewById(R.id.baustellenverwaltung_button_deatil);
loschen = (Button)view.findViewById(R.id.baustellenverwaltung_button_loschen);
mangel_detail = (Button)view.findViewById(R.id.baustellenverwaltung_button_mangel);
}
Finally, you're not setting the data according to your pojos for when the view holder is recently created, only when it is recycled:
public View getView(final int position, @Nullable View convertView, @NonNull ViewGroup parent) {
ViewHolder viewHolder;
if(convertView == null){
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(layout,parent,false);
viewHolder = new ViewHolder(convertView);
viewHolder.detail.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(getContext(),"Detail Button from" + getItem(position).getName()+" pressed",Toast.LENGTH_SHORT).show();
}
});
viewHolder.loschen.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(getContext(),"Loschen Button from" + getItem(position).getName()+" pressed",Toast.LENGTH_SHORT).show();
}
});
viewHolder.mangel_detail.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(getContext(),"Mängel Button from" + getItem(position).getName()+" pressed",Toast.LENGTH_SHORT).show();
}
});
convertView.setTag(viewHolder);
}
else{
viewHolder = (ViewHolder)convertView.getTag();
}
viewHolder.id.setText(getItem(position).getId());
viewHolder.name.setText(getItem(position).getName());
viewHolder.mangel.setText(getItem(position).getAnzMangel());
return convertView;
}
回答2:
onCreate() will be invoked before onCreateView() So View will be null in that time
Move this lines to onCreateView()
ListView lv = (ListView)YourView.findViewById(R.id.baustellenverwaltung_listview);
lv.setAdapter(new MyListAdapter(getActivity(),R.layout.list_item,list));
回答3:
Pass your View in this change this-:
public ViewHolder(){
id = (TextView)getView().findViewById(R.id.baustellenverwaltung_textview_id);
name = (TextView)getView().findViewById(R.id.baustellenverwaltung_textview_name);
mangel = (TextView)getView().findViewById(R.id.baustellenverwaltung_textview_mangel);
detail = (Button)getView().findViewById(R.id.baustellenverwaltung_button_deatil);
loschen = (Button)getView().findViewById(R.id.baustellenverwaltung_button_loschen);
mangel_detail = (Button)getView().findViewById(R.id.baustellenverwaltung_button_mangel);
}
To-:
public ViewHolder(View view){
super(view);
id = (TextView)view.findViewById(R.id.baustellenverwaltung_textview_id);
name = (TextView)view.findViewById(R.id.baustellenverwaltung_textview_name);
mangel = (TextView)view.findViewById(R.id.baustellenverwaltung_textview_mangel);
detail = (Button)view.findViewById(R.id.baustellenverwaltung_button_deatil);
loschen = (Button)view.findViewById(R.id.baustellenverwaltung_button_loschen);
mangel_detail = (Button)view.findViewById(R.id.baustellenverwaltung_button_mangel);
}
来源:https://stackoverflow.com/questions/50583639/error-in-my-fragment-attempt-to-invoke-virtual-method-android-view-view-androi