2016-08-19 22 views
0

Neu für Android und Java und Learning by Doing, aber ich vermisse etwas grundlegend beim Detektieren von Element Klicks in einem ListView.Null Pointer Ausnahme beim Aufruf von SetOnItemClickListener

Ich habe eine Aktivität, die ein paar Tasten mit einem ListView unter ihnen ist. Jedes ListView-Element verfügt über ein Symbol, auf das geklickt werden kann, das schließlich zu einer anderen Aktivität wechselt, und einen Zeitstempel (der gerade angibt, dass der Klick über Toast funktioniert hat). Klick-Erkennung auf dem Symbol funktioniert, aber ich versuche, die Auswahl der Elemente in der ListView zu implementieren, und das ist, wo ich Probleme habe.

ich zahlreiche Beispiele wie this prüft haben, und ich denke, dass ich es wie vorgeschrieben tue, aber ich bin offensichtlich etwas fehlt, wie ich eine Laufzeitausnahme erhalte „java.lang.NullPointerException: Der Versuch, virtuelle Methode aufzurufen‚Leere android.widget.ListView.setOnItemClickListener (android.widget.AdapterView $ OnItemClickListener)‘auf einer null-Objekt-Referenz:“

Hier ist das Layout für die Ansicht:

<?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" 
    android:paddingBottom="@dimen/activity_vertical_margin" 
    android:paddingLeft="@dimen/activity_horizontal_margin" 
    android:paddingRight="@dimen/activity_horizontal_margin" 
    android:paddingTop="@dimen/activity_vertical_margin" 
    tools:context="com.example.foo.magma.ViewPassagesActivity"> 

    <LinearLayout 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:id="@+id/linearLayout"> 
     <Button 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:text="Update" 
      android:onClick="update" 
      android:id="@+id/updateButton" 
      android:layout_alignParentTop="true" 
      android:layout_alignParentLeft="true" 
      android:layout_alignParentStart="true" 
      android:layout_weight="1"/> 

     <Button 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:text="Delete" 
      android:onClick="delete" 
      android:id="@+id/deleteButton" 
      android:layout_alignParentTop="true" 
      android:layout_alignParentRight="true" 
      android:layout_alignParentEnd="true" 
      android:layout_weight="1"/> 
    </LinearLayout> 

    <ListView 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:id="@+id/passagesListView" 
     android:layout_alignParentBottom="true" 
     android:layout_centerHorizontal="true" 
     android:layout_below="@+id/linearLayout" /> 
    </RelativeLayout> 

Hier ist das Layout für ein Element in der ListView. Wie bereits erwähnt, ist es mit einem Zeitstempel ein Symbol auf der linken Seite:

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" > 

    <ImageView 
     android:id="@+id/icon" 
     android:layout_width="50dp" 
     android:layout_height="50dp" 
     android:layout_marginLeft="4dp" 
     android:layout_marginRight="10dp" 
     android:layout_marginTop="4dp" 
     android:src="@drawable/curve" > 
    </ImageView> 

    <TextView 
     android:id="@+id/label" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="Timestamp: " 
     android:textStyle="bold" 
     android:textSize="20dp" 
     android:layout_centerVertical="true" 
     android:layout_toRightOf="@+id/icon" 
     android:layout_toEndOf="@+id/icon"> 
     android:layout_toRightOf="@+id/icon" 
    </TextView> 

    <TextView 
     android:id="@+id/time" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="layouttesttime" 
     android:textSize="20dp" 
     android:layout_below="@+id/date" 
     android:layout_alignRight="@+id/date" 
     android:layout_alignEnd="@+id/date" 
     android:layout_alignLeft="@+id/date" 
     android:layout_alignStart="@+id/date"> 
    </TextView> 

    <TextView 
     android:id="@+id/date" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_marginLeft="10dp" 
     android:text="layouttestdate" 
     android:textSize="20dp" 
     android:layout_alignTop="@+id/icon" 
     android:layout_alignParentRight="true" 
     android:layout_alignParentEnd="true" 
     android:layout_toRightOf="@+id/label" 
     android:layout_toEndOf="@+id/label"> 
    </TextView> 
    </RelativeLayout> 

Hier ist er() aus meiner Tätigkeit onCreate, die mein Adapter setzt:

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

    ListView passagesListView = (ListView) findViewById(R.id.passagesListView); 
    assert passagesListView != null; 

    buildPassageList(); 

    PassagesViewAdapter adapter = new PassagesViewAdapter(this, R.layout.passages_row_layout, passages); 
    passagesListView.setAdapter(adapter); 


} 

Und hier ist, wo ich die habe Problem. Der OnClickListener für das Symbol funktioniert. Meine Absicht ist, die Auswahl eines ListView-Elements zu erkennen, damit es gelöscht werden kann. Wenn ich jedoch den Aufruf von SetOnItemClickListener() hinzufüge, erhalte ich eine Laufzeitausnahme.

import android.content.Context; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.AdapterView; 
import android.widget.ArrayAdapter; 
import android.widget.ImageView; 
import android.widget.ListView; 
import android.widget.TextView; 
import android.widget.Toast; 

import java.util.List; 


public class PassagesViewAdapter extends ArrayAdapter<Passage>{ 

    private int resource; 
    private List<Passage> passages; 

    public PassagesViewAdapter(Context context, int resource, List<Passage> passages) { 
     super(context, resource, passages); 
     this.resource = resource; 
     this.passages = passages; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 

     View view = convertView; 

     if (view == null) { 
      LayoutInflater li = LayoutInflater.from(getContext()); 
      view = li.inflate(resource, null); 
     } 

     Passage passage = this.passages.get(position); 

     TextView time = (TextView) view.findViewById(R.id.time); 
     TextView date = (TextView) view.findViewById(R.id.date); 
     ImageView icon = (ImageView) view.findViewById(R.id.icon); 
     icon.setTag(new Integer(position)); 
     final String positionStr = icon.getTag().toString(); 

     // This works great! 
     icon.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       Toast.makeText(getContext(), "You clicked on " + positionStr, Toast.LENGTH_SHORT).show(); 
      } 
     }); 

     ListView passagesListView = (ListView) view.findViewById(R.id.passagesListView); 
     assert passagesListView != null; 

     // ** This call results in a runtime error for null pointer reference. 
     passagesListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { 
      @Override 
      public void onItemClick(AdapterView<?> adapter, View view, int position,long arg3) { 
       Toast.makeText(getContext(), "Foo", Toast.LENGTH_SHORT).show(); 
      } 
     }); 

     time.setText(passage.getPassageTime()); 
     date.setText(passage.getPassageDate()); 

     return view; 
    } 

} 

Antwort

1

Das weil die View Sie in Ihrem Adapter stellt die View Sie in der Liste sehen, nicht das Layout Ihrer ViewPassagesActivity. Sie haben keine ListView in Ihrem ListView Artikel, so dass es nicht gefunden werden kann und findViewById gibt null zurück. Wenn Sie das Teil bewegen, wo Sie die OnItemClickListener zum onCreate Ihrer ViewPassagesActivity eingestellt haben, sollte alles, diesen Teil fein

Entfernen von Ihrem Adapter arbeiten

// ** This call results in a runtime error for null pointer reference. 
passagesListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { 
    @Override 
    public void onItemClick(AdapterView<?> adapter, View view, int position,long arg3) { 
     Toast.makeText(getContext(), "Foo", Toast.LENGTH_SHORT).show(); 
    } 
}); 

und fügen Sie es Ihrer Aktivität des onCreate wie diese

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

    ListView passagesListView = (ListView) findViewById(R.id.passagesListView); 
    assert passagesListView != null; 

    buildPassageList(); 

    PassagesViewAdapter adapter = new PassagesViewAdapter(this, R.layout.passages_row_layout, passages); 
    passagesListView.setAdapter(adapter); 

    // ** This call results in a runtime error for null pointer reference. 
    passagesListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { 
     @Override 
     public void onItemClick(AdapterView<?> adapter, View view, int position,long arg3) { 
      Toast.makeText(getContext(), "Foo", Toast.LENGTH_SHORT).show(); 
     } 
    }); 
} 
+0

Aha. Ich verstehe es. Danke für die schnelle Antwort. Der Wechsel zu OnCreate() hat funktioniert. – sje

0

Versuchen Sie, Ihren Adapter von BaseAdapter zu erweitern.

Dieses

public class PassagesViewAdapter extends ArrayAdapter<Passage>{ 

diese

public class PassagesViewAdapter extends BaseAdapter { 

Auch Ihre setOnItemClickListener in der onCreate Funktion in Ihrer Tätigkeit sein muss, nicht in dem Adapter.

Verwandte Themen