处理ConcurrentModificationException以同时访问

时间:2014-11-24 08:37:27

标签: java android android-service

在我的应用程序中,我有一个简单的Service从Web服务和主要活动中获取一些数据我正在查看已保存的数据。对于此操作,我使用此类结构来设置数据结构以便保存它进入数据库并使用此结构读取数据以查看项目到Android ListView,使用此类结构可能同时访问并且我得到错误

ReceivedItemStructure类结构:

public class ReceivedItemStructure implements Serializable {
    public String  mLastID;
    public String  mUserID;
    public String  mSmsBody;
    public String  mMobileNumber;
    public String  mDate;
    public String  mSenderName;
    public String  mSmsNumber;
    public String  mContactName;
    public Integer mRead; 
    public Bitmap  mPhoto;
}
将数据保存到数据库的

saveReceivedItemsToDatabase方法:

public void saveReceivedItemsToDatabase(List<ReceivedItemStructure> receiveRow, String username) {
    if (receiveRow != null) {
        for (ReceivedItemStructure rf : receiveRow) {
        /* Find Duplicate row if not exist then can be write into DataBase */
            if (!G.db.searchLastID ( username, rf.getmLastID () )) {
                addReceivedToDataBase ( new ReceivedItemStructure (
                        rf.getmLastID (),
                        username,
                        rf.getmSmsBody (),
                        rf.getmSmsNumber (),
                        rf.getmSenderName (),
                        rf.getmContactName (),
                        rf.getmDate (),
                        rf.getmRead (),
                        rf.getmPhoto ()
                ) );
            }
        }
    }
}

现在在这个方法中,我从具有该类结构的数据库中读取(这是启动活动时的错误原因)同时访问(将数据从服务保存到数据库并从数据库读取并使用一些数据填充ReceivedItemStructure类:

public static void fillItems(ContentResolver cr){
    Cursor cursor = db.getReceivedCursorFromDatabase(config_username);
    cursor.moveToFirst();
    String name = "";
    String id   = "";
    items.clear ();
    if ( cursor != null && cursor.getCount() != 0 ) {
        do {
            ...
            items.add(item);
        }while(cursor.moveToNext());
        cursor.close();
    }
}

items是:

public static ArrayList<ReceivedItemStructure> items;
G类中的

Application延伸。现在如何处理这个错误并修改它?

POST UPDATE:

public void addReceivedToDataBase(ReceivedItemStructure fields) {
    db = this.getWritableDatabase();
    ContentValues values = new ContentValues();
    values.put(COLUMN_LASTID,       fields.getmLastID());           // ReceiveFields last ID
    values.put(COLUMN_USERID,       fields.getmUserID());           // ReceiveFields last ID
    values.put(COLUMN_MOBILENUMBER, fields.getmMobileNumber());
    values.put(COLUMN_SENDERNAME,   fields.getmSenderName()); 
    values.put(COLUMN_SMSBODY,      fields.getmSmsBody());
    values.put(COLUMN_SMSNUMBER,    fields.getmSmsNumber());
    values.put(COLUMN_RECEIVEDATE,  fields.getmDate());
    values.put(COLUMN_READ_STATE ,  fields.getmRead ());
    db.insert(RECEIVE_FIELDS_TABLE, null, values);
}

在服务中读取Web服务并将数据保存到数据库:

public static void getRequestFromServer (long lastID, int count, ContentResolver cr) throws JSONException {
    String received = null;
    String firstID = "";
    try {
        received = new JsonService ( config_username, config_password, lastID, count, F_RECEIVE_SMS ).request ();
    } catch (Exception e) {
        e.printStackTrace ();
        return;
    }
        /* UPDATE CODE */ 
        items_temp = new ArrayList<ReceivedItemStructure> ();

        JSONArray object = new JSONArray ( received );
        JSONArray data_array = null;
        data_array = new JSONArray ( received );

        String mUserID = config_username;
        JSONObject json_obj = null;
        for (int i = 0; i < data_array.length (); i++) {
            try {
                json_obj = data_array.getJSONObject ( i );
            } catch (JSONException e) {
                e.printStackTrace ();
                DebugLog.log ( String.valueOf ( e ) );
            }
            String mLastID     = null;
            String mSmsBody    = null;
            String mSmsNumber  = null;
            String mSenderName = null;
            mLastID     = json_obj.getString  ( "id_recived_sms" );
            mSmsBody    = json_obj.getString  ( "sms_body" );
            mSmsNumber  = json_obj.getString  ( "sms_number" );
            mSenderName = json_obj.getString  ( "mobile_number" );
            String mContactName = getContentNameFromContactList ( mSenderName , cr);
            if (TextUtils.isEmpty ( mContactName ))
            /* if contact name not exist in contact show resolve by service */
                mContactName = mSenderName;

            String mDate = null;
                  mDate = json_obj.getString ( "recived_date" );
            Bitmap mPhoto = getContactPhoto ( mSenderName , cr );
            ReceivedItemStructure item = new ReceivedItemStructure ();
            item.setmLastID       ( mLastID );
            item.setmUserID       ( mUserID );
            item.setmSmsBody      ( mSmsBody );
            item.setmSmsNumber    ( mSmsNumber );
            item.setmSenderName   ( mSenderName );
            item.setmContactName  ( mContactName );
            item.setmDate         ( mDate );
            /* set read to false, after clicking on viewGroup thats set to true */
            item.setmRead         ( 0 ); /* that means FALSE  */
            item.setmPhoto        ( mPhoto );

            /* UPDATE CODE */ 
            items_temp.add ( item );

        }
        /* UPDATE CODE */ 
        db.saveReceivedItemsToDatabase ( items_temp, config_username );
}

如果用户运行应用程序我从数据库中读取并使用fillItems方法填充ReceivedItemStructure类(同时访问)。

更新帖子2:

将新的ArrayList定义为items_temp并使用items_temp()和activity从服务中分离G.items。有时我遇到问题,我的申请也会崩溃。

items_temp课程中的

G是:

public static ArrayList<ReceivedItemStructure> items_temp;

logcat的:

java.lang.RuntimeException: An error occured while executing doInBackground()
    at android.os.AsyncTask$3.done(AsyncTask.java:299)
    at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
    at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
    at java.util.concurrent.FutureTask.run(FutureTask.java:239)
    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
    at java.lang.Thread.run(Thread.java:838)
Caused by: java.util.ConcurrentModificationException
    at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:569)
    at ir.tsms.DataBase.DatabaseHandler.saveReceivedItemsToDatabase(DatabaseHandler.java:133)
    at ir.tsms.Class.G.getRequestFromServer(G.java:339)
    at ir.tsms.ServiceDialog$LongOperation.doInBackground(ServiceDialog.java:179)
    at ir.tsms.ServiceDialog$LongOperation.doInBackground(ServiceDialog.java:173)
    at android.os.AsyncTask$2.call(AsyncTask.java:287)
    at java.util.concurrent.FutureTask.run(FutureTask.java:234)
    ... 4 more
java.util.ConcurrentModificationException
    at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:569)
    at ir.tsms.DataBase.DatabaseHandler.saveReceivedItemsToDatabase(DatabaseHandler.java:133)
    at ir.tsms.Class.G.getRequestFromServer(G.java:339)
    at ir.tsms.ServiceDialog$LongOperation.doInBackground(ServiceDialog.java:179)
    at ir.tsms.ServiceDialog$LongOperation.doInBackground(ServiceDialog.java:173)
    at android.os.AsyncTask$2.call(AsyncTask.java:287)
    at java.util.concurrent.FutureTask.run(FutureTask.java:234)
    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
    at java.lang.Thread.run(Thread.java:838)

2 个答案:

答案 0 :(得分:0)

如果addReceivedToDataBasereceiveRow列表中添加了一个元素,那就是您获得的异常的原因。使用增强的for循环迭代时,您无法更改List(添加/删除元素)。

编辑:

您不应该使用public static ArrayList<ReceivedItemStructure> items列表来存储从服务器接收的数据和存储从数据库加载的数据,因为正如您所注意到的,这两个进程可能会相互干扰。

从服务器加载数据时,将其存储在不同的List中,然后保存到数据库中。完成数据库更新后,将数据库中的数据重新加载到items(通过调用fillItems)。

答案 1 :(得分:0)

使用迭代器而不是增强的for循环。
例如: for (Iterator iter = list.iterator(); iter.hasNext(); ) { E element = iter.next(); ... }