11

我已經從ResourceCursorAdapter我曾經newViewbindViewSimpleCursorAdapter我在哪裏僅使用getView方法切換。的NullPointerException在onLoaderFinished使用SimpleCursorAdapter

現在我有onLoaderFinished錯誤。雖然它給了我NullPointerExceptionadapter.swapCursor(cursor)我的兩個適配器和光標對象是NOT NULL。我將在下面發佈我的所有代碼。任何幫助非常感謝(沒有留下太多的頭髮拉出)。

import android.annotation.SuppressLint; 
import android.content.Context; 
import android.database.Cursor; 
import android.net.Uri; 
import android.os.Bundle; 
import android.provider.ContactsContract; 
import android.support.v4.app.FragmentActivity; 
import android.support.v4.app.LoaderManager; 
import android.support.v4.content.CursorLoader; 
import android.support.v4.content.Loader; 
import android.support.v4.widget.ResourceCursorAdapter; 
import android.util.Log; 
import android.util.SparseBooleanArray; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.view.ViewGroup; 
import android.view.Window; 
import android.widget.CheckBox; 
import android.widget.ListView; 
import android.widget.TextView; 

public class ContactSelect extends FragmentActivity implements LoaderManager.LoaderCallbacks<Cursor> { 
private static final int LOADER_ID = 1; 
private MyAdapter adapter; 
private ListView list; 
private View row; 
private SparseBooleanArray checkedState = new SparseBooleanArray(); 

@SuppressLint({ "NewApi", "NewApi" }) 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); 
    setContentView(R.layout.activity_contact_select);  

    adapter = new MyAdapter(this, R.layout.contacts_select_row, null, null, null, 0);  

    getSupportLoaderManager().initLoader(LOADER_ID, null, this);   

    list = (ListView)findViewById(R.id.list);     

    list.setAdapter(adapter); 
    list.setEmptyView(findViewById(R.id.empty));  

} 

@SuppressLint("NewApi") 
public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) { 
    final String projection[] = new String[]{ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME}; 
    final Uri uri = ContactsContract.Contacts.CONTENT_URI; 

    final String selection = ContactsContract.Contacts.HAS_PHONE_NUMBER + "=1" + 
    " AND " + ContactsContract.Contacts.IN_VISIBLE_GROUP + " =1"; 

    final String order = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"; 

    final CursorLoader loader = new CursorLoader(this, uri, projection, selection, null, order); 

    return loader;  
} 

public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { 
    for(int i=0;i<cursor.getCount();i++){ 
     checkedState.put(i, false); 
    } 

    adapter.swapCursor(cursor);     
} 

public void onLoaderReset(Loader<Cursor> loader) { 
    adapter.swapCursor(null);  
} 

private class MyAdapter extends SimpleCursorAdapter implements OnClickListener{ 
    private CheckBox markedBox; 
    private TextView familyText; 
    private Context context; 
    private Cursor cursor; 

    public MyAdapter(Context context, int layout, Cursor c, String[] from, 
      int[] to, int flags) { 
     super(context, layout, c, from, to, flags); 

     this.context = context; 
     this.cursor = getCursor(); 
    } 

    @Override 
    public View getView(int position, View view, ViewGroup group) { 

     final LayoutInflater li = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     row = li.inflate(R.layout.contacts_select_row, group, false); 

     view.setTag(cursor.getPosition()); 
     view.setOnClickListener(this); 

     familyText = (TextView)view.findViewById(R.id.contacts_row_family_name); 
     markedBox = (CheckBox)view.findViewById(R.id.contacts_row_check); 
     familyText.setText(cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME))); 

     boolean currentlyChecked = checkedState.get(cursor.getPosition()); 
     markedBox.setChecked(currentlyChecked);  


     setProgressBarIndeterminateVisibility(false); 

     return super.getView(position, view, group); 
    } 

    public void onClick(View view) { 
     int rowId = (Integer)view.getTag(); 
     Log.d("OnClick", String.valueOf(rowId)); 
     boolean currentlyChecked = checkedState.get(rowId); 
     markedBox.setChecked(!currentlyChecked); 
     checkedState.put(rowId, !currentlyChecked); 
     Log.d("checkedState", "checkedState(" + rowId + ") = " + checkedState.get(rowId)); 
    }  
     }  
} 
+0

提供您的import語句,因爲準確的光標包improted或不 –

+0

我已經加入我的進口原題 – Stephen

+3

你可以張貼logcat的嗎?我只需要知道,如果堆棧結束在你提到的點或進一步 – nandeesh

回答

12

SimpleCursorAdapter類的swapCursor方法的調用將觸發它映射從提供給構造函數的String陣列列名的函數(第4參數)轉換爲表示列索引的整數數組。正如你在MyAdapter代表從遊標的列名String數組構造函數傳遞null,這將拋出一個NullPointerException後來當swapCursor將努力使映射(該NullPointerException應該出現在一個方法findColumns,這是實際方法使用列名稱String數組)。

的解決方案是通過一個有效的String陣列,您可能還需要爲int陣列爲代表的觀點的ID在其中放置數據做到這一點:

String[] from = {ContactsContract.Contacts.DISPLAY_NAME}; 
int[] to = {R.id.contacts_row_family_name, R.id.contacts_row_check}; 
adapter = new MyAdapter(this, R.layout.contacts_select_row, null, from, to, 0); 

我不知道你正在嘗試做什麼,但是你的方法的實現並不完全正確:

你做的getView方法(創建佈局,搜索視圖,綁定數據)的正常東西,然後你只需返回視圖從超類(?!?),你可能會看到默認值沒有任何東西的佈局。

的方式你寫的getView方法不是很有效,你可能想看看進入視野的回收和視圖持有人格局。

cursor.getPosition()不會做你想要什麼,你不將光標移動到正確的位置。默認情況下,基於光標的適配器將在getView方法中爲您執行此操作,但是,當您覆蓋該方法時,您需要移動光標的位置。

您應該離開getView方法並使用兩種方法newViewbindView,因爲它們提供了更好的邏輯分離。

2

adapter = new MyAdapter(this,R.layout.contacts_select_row,null,null,null,0);

和你MyAdapter類你逝去的空光標

public MyAdapter(Context context, int layout, Cursor c, String[] from, 
      int[] to, int flags) { 
     super(context, layout, c, from, to, flags); 

     this.context = context; 
     this.cursor = getCursor(); 
    } 
+0

你好,謝謝你的迴應。 空遊標傳遞的原因是因爲在LoaderManager完成之前我沒有遊標對象。我應該指出,這段代碼在使用ResourceCursorAdapter時工作得很好 – Stephen

相關問題