Error: Attempted to access a cursor after it has been closed?

*爱你&永不变心* 提交于 2019-12-11 02:19:51

问题


In my application I'm fetching inbox messages from native application to my application. Also there are checkboxes to select multiple messages.But the problem arises are no messages are displaying in listview while running code and also showing error android.database.StaleDataException: Attempted to access a cursor after it has been closed.

ArrayAdapter<SMSListModel> adapter;
List<SMSListModel> list = new ArrayList<SMSListModel>();
TextView textViewSMSSender, textViewSMSBody

 public void getInboxSms() {
    //Uri message = Uri.parse("content://sms/inbox");
    ContentResolver cr = getContentResolver();
    c = cr.query(Uri.parse("content://sms/inbox"), null, null, null, null);
    //startManagingCursor(c);
     //totalSMS = c.getCount();
    if (c.moveToFirst()) {
        for (int i = 0; i < c.getCount(); i++) {

            Log.d("SMSss", "Contact number : "+ c.getString(c.getColumnIndexOrThrow("address"))+ "\n"
                            + "msg : " + c.getColumnIndexOrThrow("body")
                            + "\n"
                            + "Person : "
                            + getContactName(getApplicationContext(),c.getString(c.getColumnIndexOrThrow("address"))));
            c.moveToNext();
        }
    }
   c.close();

}

public String getContactName(Context context, String phoneNumber) {
    ContentResolver cr = context.getContentResolver();
    Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI,
            Uri.encode(phoneNumber));
    Cursor cursor = cr.query(uri,
            new String[] { PhoneLookup.DISPLAY_NAME }, null, null, null);
    if (cursor == null) {
        return null;
    }
    String contactName = null;
    if (cursor.moveToFirst()) {
        contactName = cursor.getString(cursor
                .getColumnIndex(PhoneLookup.DISPLAY_NAME));
    }
    if (cursor != null && !cursor.isClosed()) {
        cursor.close();
    }
    return contactName;
}
private List<SMSListModel> getModel() 
{
    if(c.getCount()>0)
    {
        for(int i=0;i<c.getCount();i++)
        {
            if(c.moveToPosition(i))
            {                   
                list.add(new SMSListModel(c.getString(c.getColumnIndex("address")),c.getString(c.getColumnIndex("body"))));

            }
        }
    }

    return list;

}

SmsListAdapter

public class SMSListAdapter extends ArrayAdapter<SMSListModel> {

private final List<SMSListModel> list;
private final Activity mContext;
boolean checkAll_flag = false;
boolean checkItem_flag = false;

public SMSListAdapter(Activity context,List<SMSListModel> list) 
{
    super(context, R.layout.listview_each_item, list);
    Log.d("size of list", ""+list.size());
    mContext = context;
    this.list = list;

}

static class ViewHolder {
    protected TextView textAddress;
    protected TextView textBody;
    protected CheckBox checkbox;
}

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

    ViewHolder viewHolder = null;
    if (convertView == null) {
        LayoutInflater inflator = mContext.getLayoutInflater();
        convertView = inflator.inflate(R.layout.listview_each_item, null);
        viewHolder = new ViewHolder();
        viewHolder.textAddress = (TextView) convertView.findViewById(R.id.tvSMSSend);
        viewHolder.textBody = (TextView) convertView.findViewById(R.id.tvSMSBody);
        viewHolder.checkbox = (CheckBox) convertView.findViewById(R.id.cbSelect);
        viewHolder.checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {

                    @Override
                    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                        int getPosition = (Integer) buttonView.getTag();  // Here we get the position that we have set for the checkbox using setTag.
                        list.get(getPosition).setSelected(buttonView.isChecked()); // Set the value of checkbox to maintain its state.
                    }
                });
        convertView.setTag(viewHolder);
        convertView.setTag(R.id.tvSMSSend, viewHolder.textAddress);
        convertView.setTag(R.id.tvSMSBody, viewHolder.textBody);
        convertView.setTag(R.id.cbSelect, viewHolder.checkbox);
    } else {
        viewHolder = (ViewHolder) convertView.getTag();
    }
    viewHolder.checkbox.setTag(position); // This line is important.
    viewHolder.textAddress.setText(list.get(position).getAddress());
    viewHolder.textBody.setText(list.get(position).getBody());
    viewHolder.checkbox.setChecked(list.get(position).isSelected());    
    return convertView;
}}

SMSListModel

public class SMSListModel {

private String address;
String body;
private boolean selected;

public SMSListModel(String address, String body) {
    this.address = address;
    this.body = body;
}

public String getAddress() {
    return address;
}

public String getBody() {
    return body;
}

public boolean isSelected() {
    return selected;
}

public void setSelected(boolean selected) {
    this.selected = selected;
}}


回答1:


cursor "c" is a global variable which you use in these two methods

getModel();

getInboxSms();

But the problem is you close the cursor in getInboxSms() method and try to access same cursor in getModel() method.

So remove this line from getInboxSms() method and try.

 c.close();

Update this method

private List<SMSListModel> getModel() {
        if (c.getCount() > 0) {
            c.moveToFirst();

            for (int i = 0; i < c.getCount(); i++) {
                list.add(new SMSListModel(c.getString(c.getColumnIndex("address")), c.getString(c.getColumnIndex("body"))));
                c.moveToNext();
            }
        }

        return list;

    }

Update your onCreate() Method

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        context = this;
        listViewSMS = (ListView) findViewById(R.id.lvSMS);

        getInboxSms();
        textViewSMSSender = (TextView) findViewById(R.id.tvSMSSend);
        textViewSMSBody = (TextView) findViewById(R.id.tvSMSBody);
        smsListAdapter = new SMSListAdapter(this, getModel());

        listViewSMS.setAdapter(smsListAdapter); // you forget to add this line
        listViewSMS.setOnItemClickListener(this);

    }



回答2:


Do not try to close the cursor in both your method that is

public String getContactName(Context context, String phoneNumber) 
 public void getInboxSms()

You can try to close the cursor when all your operations are completed



来源:https://stackoverflow.com/questions/23131866/error-attempted-to-access-a-cursor-after-it-has-been-closed

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!