11

Tôi đã chuyển từ một ResourceCursorAdapter nơi tôi sử dụng newViewbindView đến một SimpleCursorAdapter nơi tôi đang sử dụng chỉ có phương pháp getView.NullPointerException trong onLoaderFinished sử dụng SimpleCursorAdapter

Bây giờ tôi gặp lỗi trong onLoaderFinished. Mặc dù nó cung cấp cho tôi NullPointerException trên adapter.swapCursor(cursor) cả bộ điều hợp và đối tượng con trỏ của tôi là NOT null. Tôi sẽ đăng tất cả mã của tôi bên dưới. Bất kỳ sự giúp đỡ nào được đánh giá cao (không còn nhiều tóc để kéo ra).

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

cung cấp tuyên bố nhập của bạn vì gói Con trỏ chính xác bị hủy hoặc không –

+0

Tôi đã thêm hàng nhập của mình vào câu hỏi gốc – Stephen

+3

bạn cũng có thể đăng nhật ký không? Tôi chỉ cần biết liệu ngăn xếp có kết thúc tại thời điểm bạn đã đề cập hoặc đi xa hơn không? – nandeesh

Trả lời

12

Một cuộc gọi của phương pháp swapCursor của lớp SimpleCursorAdapter sẽ kích hoạt một chức năng mà bản đồ các tên cột từ String mảng cung cấp cho các nhà xây dựng (lần thứ 4 tham số) đến một mảng các số nguyên đại diện cho các chỉ mục cột. Khi bạn vượt qua null trong hàm tạo của MyAdapter cho mảng String đại diện cho các tên cột từ con trỏ, điều này sẽ ném một NullPointerException sau đó khi swapCursor sẽ cố gắng thực hiện ánh xạ (NullPointerException sẽ xuất hiện theo phương thức findColumns, đó là thực tế phương pháp sử dụng các tên cột String mảng).

Giải pháp là để vượt qua một String mảng hợp lệ, bạn cũng có thể muốn làm điều này cho int mảng đại diện cho id cho các quan điểm, trong đó để đặt dữ liệu:

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); 

Tôi không biết những gì bạn đang cố gắng làm nhưng việc thực hiện lại các phương pháp getView là không hoàn toàn đúng:

bạn làm những thứ bình thường đối với các getView phương pháp (tạo bố trí, tìm kiếm quan điểm, ràng buộc dữ liệu) và sau đó bạn chỉ đơn giản là trả lại nhìn từ superclass (?!?), có thể bạn sẽ chỉ thấy mặc định bố trí không có gì trong đó.

Cách bạn đã viết phương pháp getView không hiệu quả lắm, bạn có thể muốn xem xét việc tái chế chế độ xem và mẫu chủ sở hữu chế độ xem.

cursor.getPosition() sẽ không làm những gì bạn muốn vì bạn không di chuyển con trỏ đến đúng vị trí. Theo mặc định con trỏ dựa trên bộ điều hợp sẽ làm điều này cho bạn trong phương pháp getView, nhưng, khi bạn overrode phương pháp đó là công việc của bạn để di chuyển vị trí của con trỏ.

Bạn nên để phương thức getView và sử dụng hai phương pháp newViewbindView khi chúng cung cấp sự tách biệt logic tốt hơn.

2

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

và lớp MyAdapter của bạn, bạn đang đi qua vô trỏ

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

Xin chào! Cảm ơn bạn đã phản hồi. Lý do cho việc chuyển con trỏ null là vì tôi sẽ không có đối tượng con trỏ cho đến khi Trình quản lý tải kết thúc.Tôi nên chỉ ra rằng mã này làm việc hoàn toàn tốt trong khi sử dụng ResourceCursorAdapter – Stephen

Các vấn đề liên quan