2011-03-01 46 views
0

當我有這樣的Android - getListView和setListAdapter與NullPointerException異常錯誤使用自定義佈局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
     android:orientation="vertical" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:background="#ffffff"> 

    <com.ftni.core.ui.ActionBar 
     android:id="@+id/actionbar" 
     style="@style/ActionBar"/> 

    <TextView android:id="@+id/list_title" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:text="Title" 
     android:textStyle="bold" 
     android:textColor="#000000" 
     android:textSize="18sp" 
     android:padding="3px"/> 

    <ListView android:id="@id/android:list" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:layout_weight="1" 
     android:drawSelectorOnTop="false"/> 
</LinearLayout> 

,並在我的列表視圖(代碼之前,我改變了佈局正在)

private void buildListView() 
{ 
    ListView lv = getListView(); 

    registerForContextMenu(lv); 

    lv.setTextFilterEnabled(true); 

    lv.clearChoices(); 

    setListAdapter(new UserListAdapter(SuspendedUsersActivity.this, R.layout.useritem, users)); 

    lv.setOnItemClickListener(clickListener); 
} 

佈局我試着先將呼叫移至setListAdapter,但我仍然得到NullPointerException。這裏的logcat的

FATAL EXCEPTION: main 
java.lang.NullPointerException 
at android.app.ListActivity.setListAdapter(ListActivity.java:267) 
at com.myapp.backoffice.users.SuspendedUsersActivity.buildListView(SuspendedUsersActivity.java:140) 
at com.myapp.backoffice.users.SuspendedUsersActivity.access$0(SuspendedUsersActivity.java:138) 
at com.myapp.backoffice.users.SuspendedUsersActivity$2.handleMessage(SuspendedUsersActivity.java:194) 
at android.os.Handler.dispatchMessage(Handler.java:99) 

我有一種感覺,正在發生的事情是,我被告知默認ID是正確的(@id/android:list)不是默認的列表視圖正確的。

編輯:

下面是關於我如何設置的更多細節。

首先,我有一個繼承的活動,以確保用戶通過身份驗證。當我直接從這個類繼承時,一切正常。

public class ProtectedListActivity extends ListActivityBase { 
    boolean isAuthenticated = false; 

    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     Thread validationThread = new Thread() 
     { 
      @Override 
      public void run() 
      { 
       try 
       { 
        isAuthenticated = UserService.ValidateToken(); 
       } 
       catch (FTNIServiceException e) 
       { 
        //eat it 
       } 
       finally 
       { 
        if (!isAuthenticated) 
        { 
         startActivity(new Intent(ProtectedListActivity.this, SignInActivity.class)); 
         finish(); 
        } 
       } 
      } 
     }; 

     validationThread.start(); 
    } 
} 

然後,我再擴展一步,將我的默認操作欄設置包裝到基類中。

public class ListWithActionBarActivity extends ProtectedListActivity { 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
    } 

    @Override 
    public void onContentChanged() 
    { 
     ActionBar actionBar = (ActionBar)findViewById(R.id.actionbar); 
     if (actionBar != null) 
     { 
      actionBar.setOnTitleClickListener(new OnClickListener() { 
       public void onClick(View v) { 
        startActivity(new Intent(ListWithActionBarActivity.this, SelectSiteActivity.class)); 
        finish(); 
       } 
      }); 

      SiteModel site = PreferencesHelper.getSite(); 

      actionBar.setTitle(site.Name + " (" + site.Abbreviation + ")"); 
      actionBar.addAction(new IntentAction(ListWithActionBarActivity.this, 
        new Intent(ListWithActionBarActivity.this, MainMenuActivity.class), 
        R.drawable.ic_title_home_default)); 
     } 
    } 

    public static Intent createIntent(Context context) { 
     Intent i = new Intent(context, MainMenuActivity.class); 
     i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
     return i; 
    } 

    protected Intent createShareIntent() { 
     final Intent intent = new Intent(Intent.ACTION_SEND); 
     intent.setType("text/plain"); 
     intent.putExtra(Intent.EXTRA_TEXT, "Shared from the ActionBar widget."); 
     return Intent.createChooser(intent, "Share"); 
    } 
} 

然後,因爲我具有由狀態分隔的用戶2所列出(懸浮或活性)我試圖將包裝一個除了基類操作欄。

public class UserBase extends ListWithActionBarActivity { 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     //setContentView(R.layout.queue); 
     super.onCreate(savedInstanceState); 

     ActionBar actionBar = (ActionBar)findViewById(R.id.actionbar); 

     actionBar.addAction(new UserStatusSelectorAction(UserBase.this)); 

    } 
} 

最後,我們有我的活動。我已經省略了一些代碼,但是我保留了大部分代碼,以便在顯示加載屏幕時查看通過另一個線程檢索數據的方式,然後構建listview。

public class SuspendedUsersActivity extends ListWithActionBarActivity implements Runnable{ 
    ProgressDialog progress; 
    ArrayList<UserModel> users; 
    int position; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     setContentView(R.layout.queue); 
     super.onCreate(savedInstanceState); 

     TextView title = (TextView)findViewById(R.id.list_title); 
     title.setText("Suspended Users"); 

     progress = ProgressDialog.show(SuspendedUsersActivity.this, "", "Loading...", true); 

     Thread thread = new Thread(SuspendedUsersActivity.this); 
     thread.start(); 
    } 

    private void buildListView() 
    { 
     ListView lv = getListView(); 

     //registerForContextMenu(lv); 

     lv.setTextFilterEnabled(true); 

     lv.clearChoices(); 

     setListAdapter(new UserListAdapter(SuspendedUsersActivity.this, R.layout.useritem, users)); 

     lv.setOnItemClickListener(clickListener); 
    } 

    private OnItemClickListener clickListener = new OnItemClickListener() 
    { 
     @Override 
     public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 
      UserModel user = users.get(position); 

      SuspendedUserAction action = new SuspendedUserAction(SuspendedUsersActivity.this, user.UserId); 
      action.performAction(view); 
     } 
    }; 

    @Override 
    public void run() { 
     // TODO Auto-generated method stub 
     SiteModel site = PreferencesHelper.getSite(); 

     try 
     { 
      users = UserService.GetSuspendedUsers(site.SiteId); 
     } 
     catch (FTNIServiceException e) 
     { 
      // TODO Auto-generated catch block 
      Message message = new Message(); 
      message.what = ActivityBase.RESULT_ERROR; 
      message.obj = e.getMessage(); 

      handler.sendMessage(message); 
      return; 
     } 

     handler.sendEmptyMessage(ActivityBase.RESULT_DONE); 
    } 

    private Handler handler = new Handler() { 
     @Override 
     public void handleMessage(Message msg) { 
      switch(msg.what) 
      { 
       case ActivityBase.RESULT_SUCCESS: 
        progress.dismiss(); 
        startActivity(new Intent(SuspendedUsersActivity.this, SelectSiteActivity.class)); 
        finish(); 
        break; 
       case ActivityBase.RESULT_DONE: 
        buildListView(); 
        ApplicationController app = (ApplicationController)getApplication(); 
        app.setSuspendedUsersChanged(false); 
        progress.dismiss(); 
        break; 
       case ActivityBase.RESULT_ERROR: 
        progress.dismiss(); 
        new AlertDialog.Builder(SuspendedUsersActivity.this) 
        .setMessage(msg.obj.toString()) 
        .setNeutralButton("Ok", new DialogInterface.OnClickListener() { 
         public void onClick(DialogInterface arg0, int arg1) { 
          //do nothing 
          arg0.dismiss(); 
         } 
        }) 
        .show(); 
        break; 
      } 
     } 
    }; 
} 

它與ProtectedListActivity當我沒有設定一個內容視圖,但一切失敗的,不管是不是我設置的內容視圖和註釋掉動作條的東西。

回答

0

我改變了列表視圖明確地給它這樣的

<ListView android:id="@+id/list_view" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:layout_weight="1" 
    android:drawSelectorOnTop="false"/> 

一個ID,然後我改變了我的代碼,這

private void buildListView() 
{ 
    ListView lv = (ListView)findViewById(R.id.list_view); 

    lv.setTextFilterEnabled(true); 

    lv.clearChoices(); 

    lv.setAdapter(new UserListAdapter(SuspendedUsersActivity.this, R.layout.useritem, users)); 

    lv.setOnItemClickListener(clickListener); 
} 

而現在它的工作原理。出於某種原因,該列表視圖的默認ID不起作用。

0

可能您沒有將值設置爲ListView全局變量。

後getListView()代碼更多的幫助。

+1

'getListView()'是從ListActivity繼承的內置方法。 http://developer.android.com/reference/android/app/ListActivity.html#getListView() – Josh 2011-03-01 19:14:33

+0

也許您的適配器返回空值。 – 2011-03-01 19:29:34

0

的NPE上

setListAdapter(new UserListAdapter(SuspendedUsersActivity.this, R.layout.useritem, 
    users)); 

異常,所以用戶變量是最有可能爲空。

+0

用戶不爲空。在調用此方法時,數據已填充。 – Josh 2011-03-01 19:15:06

+0

@Josh R.layout.useritem是什麼樣的?和UserListAdapter。有些地方是空的,你的listview id很好,否則你會在setListAdapter()調用之前得到一個NPE。 – 2011-03-01 19:20:36

+0

我懷疑它是適配器還是該項目,因爲我有其他使用這些類的活動。我認爲這與我如何使用繼承來包裝常用功能有關。 – Josh 2011-03-01 19:26:02

0

ListView lv = getListView();

可能這是給你一個空值後設置一個斷點右。

老實說,我會嘗試去定期的活動,只是手動配置ListView。這並不難,它似乎是一個更好的方式來支持在一個活動中有兩個列表。

0

您必須將MainActivity延伸至ListActivity

public class MainActivity extends ListActivity { 
}