11

का उपयोग कर मैं एक ResourceCursorAdapter जहां मैं एक SimpleCursorAdapter करने के लिए newView और bindView इस्तेमाल किया, जहां मैं केवल getView विधि का उपयोग कर रहा से बदला गया है।NullPointerException SimpleCursorAdapter

अब मुझे onLoaderFinished में कोई त्रुटि है। हालांकि यह मुझे NullPointerException पर adapter.swapCursor(cursor) पर देता है, लेकिन मेरे एडाप्टर और कर्सर ऑब्जेक्ट शून्य नहीं हैं। मैं नीचे अपना पूरा कोड पोस्ट करूंगा। किसी भी मदद की बहुत सराहना की जाती है (बाहर खींचने के लिए ज्यादा बाल नहीं छोड़े गए हैं)।

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

अपना आयात विवरण प्रदान करें क्योंकि सटीक कर्सर पैकेज इंप्रेशन किया गया है या नहीं –

+0

मैंने मूल प्रश्न – Stephen

+3

पर अपना आयात जोड़ा है क्या आप लॉगकैट भी पोस्ट कर सकते हैं? मुझे बस यह जानने की जरूरत है कि क्या स्टैक आपके द्वारा उल्लिखित बिंदु पर समाप्त होता है या आगे जाता है – nandeesh

उत्तर

12

गुजर रहे हैं SimpleCursorAdapter वर्ग के swapCursor पद्धति की एक कॉल एक समारोह जो नक्शे निर्माता के लिए प्रदान की String सरणी से स्तंभ नाम को गति प्रदान करेगा (4 पैरामीटर) कॉलम इंडेक्स का प्रतिनिधित्व करने वाले पूर्णांक की सरणी में। आप String सरणी कर्सर से स्तंभ नाम का प्रतिनिधित्व करने के लिए MyAdapter के निर्माता में null पारित रूप में, यह एक NullPointerException बाद में फेंक जब swapCursor मानचित्रण बनाने के लिए कोशिश करेंगे (NullPointerException एक विधि findColumns है, जो वास्तविक है में दिखाई देनी चाहिए विधि जो कॉलम नाम String सरणी का उपयोग करती है)।

समाधान, एक वैध String सरणी पारित करने के लिए है कि आप भी है, जिसमें डेटा जगह int सरणी विचारों के लिए आईडी का प्रतिनिधित्व करने के लिए ऐसा करना चाहते हो सकता है:

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 विधि (लेआउट, खोज विचार, बाध्यकारी डेटा बनाने) के लिए सामान्य सामान करते हैं और फिर आप बस दृश्य को वापस कर देते हैं superclass (?!?), आप शायद डिफ़ॉल्ट देखेंगे इसमें कुछ भी नहीं लेआउट।

जिस तरह से आपने getView विधि लिखा है वह बहुत ही कुशल नहीं है, आप रीसाइक्लिंग और व्यू धारक पैटर्न को देखना चाहते हैं।

cursor.getPosition() वह नहीं करेगा जो आप चाहते हैं क्योंकि आप कर्सर को सही स्थिति में नहीं ले जाते हैं। डिफ़ॉल्ट कर्सर आधारित एडाप्टर getView विधि में आपके लिए यह करेंगे, लेकिन, जैसा कि आप विधि को ओवरराइड करते हैं, यह कर्सर की स्थिति को स्थानांतरित करने का आपका काम है।

आपको getView विधि छोड़नी चाहिए और दो विधियों newView और bindView का उपयोग करना चाहिए क्योंकि वे तर्क के बेहतर पृथक्करण की पेशकश करते हैं।

2

एडाप्टर = नए MyAdapter (यह, R.layout.contacts_select_row, अशक्त, अशक्त, अशक्त, 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

हाय वहाँ, जवाब देने के लिए धन्यवाद। teh null कर्सर पास का कारण यह है क्योंकि लोडरमेनर समाप्त होने तक मेरे पास कर्सर ऑब्जेक्ट नहीं होगा।मुझे यह इंगित करना चाहिए कि ResourceCursorAdapter का उपयोग करते समय यह कोड पूरी तरह ठीक काम करता है – Stephen