关闭

Android 系统中同时删除多条SMS的具体实现

标签: androidjavasms
630人阅读 评论(0) 收藏 举报
分类:

     昨天,遇到了一个同时删除多条记录的问题,在android系统中删除操作过慢导致了,导致用户体验不佳的现象。
     该问题一直都没有很好的解决,现在将整体的解决方案记录一下。

   一。AsyncQueryHander的具体实现

      通过代码我们看到这里是通过一个AsyncQueryHander实现的删除操作,该handler的具体实现

     public static class ConversationQueryHandler extends AsyncQueryHandler {
        private int mDeleteToken;

        public ConversationQueryHandler(ContentResolver cr) {
            super(cr);
        }

        public void setDeleteToken(int token) {
            mDeleteToken = token;
        }

        /**
         * Always call this super method from your overridden onDeleteComplete function.
         */
        @Override
        protected void onDeleteComplete(int token, Object cookie, int result) {
            if (token == mDeleteToken) {
                // Test code
//                try {
//                    Thread.sleep(10000);
//                } catch (InterruptedException e) {
//                }

                // release lock
                synchronized (sDeletingThreadsLock) {
                    sDeletingThreads = false;
                    sDeletingThreadsLock.notifyAll();
                }
            }
        }
    }

因为每个具体的ComposeMessageActivity 中都有关于这个删除操作的回调,这里主要完成的有两个这样

protected void onQueryComplete(int token, Object cookie, Cursor cursor)
protected void onDeleteComplete(int token, Object cookie, int result) 
这里的三个参数也是非常的实用,token 令牌,cookie (实体标识),cusor游标

下面是具体的实现。

private final class BackgroundQueryHandler extends ConversationQueryHandler {
        public BackgroundQueryHandler(ContentResolver contentResolver) {
            super(contentResolver);
        }

        @Override
        protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
            /// M: @{
            MmsLog.d(TAG, "onQueryComplete, token=" + token + "activity=" + ComposeMessageActivity.this);
            /// @}
            switch(token) {
                case MESSAGE_LIST_QUERY_TOKEN:
                    /// @}
                    if (cursor == null) {
                        MmsLog.w(TAG, "onQueryComplete, cursor is null.");
                        return;
                    }
                    /// M: If adapter or listener has been cleared, just close this cursor@{
                    if (mMsgListAdapter == null) {
                        MmsLog.w(TAG, "onQueryComplete, mMsgListAdapter is null.");
                        cursor.close();
                        return;
                    }
                    if (mMsgListAdapter.getOnDataSetChangedListener() == null) {
                        MmsLog.d(TAG, "OnDataSetChangedListener is cleared");
                        cursor.close();
                        return;
                    }
                    /// @}
                    if (isRecipientsEditorVisible()) {
                        MmsLog.d(TAG, "RecipientEditor visible, it means no messagelistItem!");
                        return;
                    }
                    // check consistency between the query result and 'mConversation'
                    long tid = (Long) cookie;

                    if (LogTag.VERBOSE || Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
                        log("##### onQueryComplete: msg history result for threadId " + tid);
                    }
                    if (tid != mConversation.getThreadId()) {
                        log("onQueryComplete: msg history query result is for threadId " +
                                tid + ", but mConversation has threadId " +
                                mConversation.getThreadId() + " starting a new query");
                        if (cursor != null) {
                            cursor.close();
                        }
                        startMsgListQuery();
                        return;
                    }

                    // check consistency b/t mConversation & mWorkingMessage.mConversation
                    ComposeMessageActivity.this.sanityCheckConversation();

                    int newSelectionPos = -1;
                    long targetMsgId = getIntent().getLongExtra("select_id", -1);
                    if (targetMsgId != -1) {
                      if (cursor != null) {
                        cursor.moveToPosition(-1);
                        while (cursor.moveToNext()) {
                            long msgId = cursor.getLong(COLUMN_ID);
                            if (msgId == targetMsgId) {
                                newSelectionPos = cursor.getPosition();
                                break;
                            }
                          }
                        }
                    } else if (mSavedScrollPosition != -1) {
                        // mSavedScrollPosition is set when this activity pauses. If equals maxint,
                        // it means the message list was scrolled to the end. Meanwhile, messages
                        // could have been received. When the activity resumes and we were
                        // previously scrolled to the end, jump the list so any new messages are
                        // visible.
                        if (mSavedScrollPosition == Integer.MAX_VALUE) {
                            int cnt = mMsgListAdapter.getCount();
                            if (cnt > 0) {
                                // Have to wait until the adapter is loaded before jumping to
                                // the end.
                                newSelectionPos = cnt - 1;
                                mSavedScrollPosition = -1;
                            }
                        } else {
                            // remember the saved scroll position before the activity is paused.
                            // reset it after the message list query is done
                            newSelectionPos = mSavedScrollPosition;
                            mSavedScrollPosition = -1;
                        }
                    }
                    /// M: Code analyze 047, Extra uri from message body and get number from uri.
                    /// Then use this number to update contact cache. @{
                    if (mNeedUpdateContactForMessageContent) {
                        updateContactCache(cursor);
                        mNeedUpdateContactForMessageContent = false;
                    }
                    /// @}

                    mMsgListAdapter.changeCursor(cursor);

                    if (newSelectionPos != -1) {
                        /// M: remove bug ALPS00404266 patch, keep item top @{
                        mMsgListView.setSelection(newSelectionPos);     // jump the list to the pos
                        //View child = mMsgListView.getChildAt(newSelectionPos);
                        //int top = 0;
                        //if (child != null) {
                        //    top = child.getTop();
                        //}
                       // mMsgListView.setSelectionFromTop(newSelectionPos, top);
                        /// @}
                    } else {
                        /// M: google jb.mr1 patch, Conversation should scroll to the bottom
                        /// when incoming received @{
                        int count = mMsgListAdapter.getCount();
                        long lastMsgId = 0;
                        if (cursor != null && count > 0) {
                            cursor.moveToLast();
                            lastMsgId = cursor.getLong(COLUMN_ID);
                        }
                        // mScrollOnSend is set when we send a message. We always want to scroll
                        // the message list to the end when we send a message, but have to wait
                        // until the DB has changed. We also want to scroll the list when a
                        // new message has arrived.
                      //added by hongtao.fu for defect 2360303 at 2016.7.12 begin 
                      //smoothScrollToEnd(mScrollOnSend || lastMsgId != mLastMessageId, 0);
                        if(lastMsgId != mLastMessageId){
                        	mMsgListView.setSelection(mMsgListView.getCount());
                        	mLastMessageId=lastMsgId;
                        }
                    	//added by hongtao.fu for defect 2360303 at 2016.7.12 end 
                        mLastMessageId = lastMsgId;
                        /// @}
                        mScrollOnSend = false;
                    }
                    // Adjust the conversation's message count to match reality. The
                    // conversation's message count is eventually used in
                    // WorkingMessage.clearConversation to determine whether to delete
                    // the conversation or not.
                    if (mMsgListAdapter.getCount() == 0 && mWaitingForSendMessage) {
                        mConversation.setMessageCount(1);
                    } else {
                        mConversation.setMessageCount(mMsgListAdapter.getCount());
                    }
                    updateThreadIdIfRunning();
                    cursor.moveToPosition(-1);
                    while (cursor.moveToNext()) {
                        int read = cursor.getInt(MessageListAdapter.COLUMN_MMS_READ);
                        read += cursor.getInt(MessageListAdapter.COLUMN_SMS_READ);
                        if (read == 0) {
                            mConversation.setHasUnreadMessages(true);
                            break;
                        }
                    }
                    MmsLog.d(TAG, "onQueryComplete(): Conversation.ThreadId=" + mConversation.getThreadId()
                            + ", MessageCount=" + mConversation.getMessageCount());

                    // Once we have completed the query for the message history, if
                    // there is nothing in the cursor and we are not composing a new
                    // message, we must be editing a draft in a new conversation (unless
                    // mSentMessage is true).
                    // Show the recipients editor to give the user a chance to add
                    // more people before the conversation begins.
                    if (cursor != null && cursor.getCount() == 0 && !isRecipientsEditorVisible() && !mSentMessage) {
                        /// M: fix bug ALPS01098902, avoding checkObsoleteThreadId in this case
                        if (mSubSelectDialog != null && mSubSelectDialog.isShowing()
                                && mOldThreadID > 0 && mCutRecipients != null) {
                            mIsSameConv = false;
                        }
                        initRecipientsEditor(null);
                    }

                    // FIXME: freshing layout changes the focused view to an unexpected
                    // one, set it back to TextEditor forcely.
                    if (mSubjectTextEditor == null || (mSubjectTextEditor != null && !mSubjectTextEditor.isFocused()))
                    {
                        mTextEditor.requestFocus();
                    }

                    invalidateOptionsMenu();    // some menu items depend on the adapter's count
                    if (!mIsActivityStoped) {
                        mConversation.blockMarkAsRead(false);
                        mConversation.markAsRead();
                    }
                    return;

                case MESSAGE_LIST_QUERY_AFTER_DELETE_TOKEN:
                    // check consistency between the query result and 'mConversation'
                    tid = (Long) cookie;

                    if (LogTag.VERBOSE || Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
                        log("##### onQueryComplete (after delete): msg history result for threadId "
                                + tid);
                    }
                    if (cursor == null) {
                        return;
                    }
                    if (tid > 0 && cursor.getCount() == 0) {
                        // We just deleted the last message and the thread will get deleted
                        // by a trigger in the database. Clear the threadId so next time we
                        // need the threadId a new thread will get created.
                        log("##### MESSAGE_LIST_QUERY_AFTER_DELETE_TOKEN clearing thread id: "
                                + tid);
                        Conversation conv = Conversation.get(getApplicationContext(), tid,
                                false);
                        if (conv != null) {
                            conv.clearThreadId();
                            conv.setDraftState(false);
                        }

                        finish();
                    }
                    cursor.close();
                    break;
              case MESSAGE_GROUP_DETAILS_QUERY_TOKEN:
                 if (null == mConversation) {
                     Log.i(TAG, "group_details: mConversation is null!");
                     return;
                 }

                 ContactList contactList = mConversation.getRecipients();
                 if (null == contactList) return;

                 int failCount = (null != cursor) ? cursor.getCount() : 0;
                 if (failCount >= 1) {
                     List newContactList = new ArrayList();

                     Object[] contacts = contactList.toArray();
                     for (Object contact : contacts) {
                         Contact contactN = (Contact) contact;
                         String number = contactN.getNumber();
                         if (null != number && !"".equals(number)) {
                             newContactList.add(number);
                         }
                     }

                     StringBuffer failedSend = new StringBuffer();
                     StringBuffer successSend = new StringBuffer();

                     long date = 0l;

                     cursor.moveToPosition(-1);
                     int i = 0;
                     while (cursor.moveToNext()) {
                         String address = cursor.getString(0);
                         date = cursor.getLong(1);

                         if (i >= 1) failedSend.append(",");
                         failedSend.append(address);
                         newContactList.remove(address);
                         i ++;
                     }

                     for (int pos = 0; pos < newContactList.size(); pos ++) {
                         String address = (String) newContactList.get(pos);

                         if (null == address) continue;

                         if (pos >= 1) failedSend.append(",");
                         successSend.append(address);
                     }

                     String messageDetails = MessageUtils.getTextGroupFailMessageDetails(
                             ComposeMessageActivity.this, successSend.toString(), failedSend.toString(), date);
                     mDetailDialog = new AlertDialog.Builder(ComposeMessageActivity.this)
                     .setTitle(R.string.message_details_title)
                     .setMessage(messageDetails)
                     .setPositiveButton(android.R.string.ok, null)
                     .setCancelable(true)
                     .show();
                 }
                 break;
                default:
                    MmsLog.d(TAG, "unknown token.");
                    break;
            }
        }

        @Override
        protected void onDeleteComplete(int token, Object cookie, int result) {
            super.onDeleteComplete(token, cookie, result);
            /// M: fix bug ALPS00351620; for requery searchactivity.
            SearchActivity.setNeedRequery();
            switch(token) {
                case ConversationList.DELETE_CONVERSATION_TOKEN:
                    /// M: @{
                    /*
                    mConversation.setMessageCount(0);
                    // fall through
                    */
                    try {
                        if (TelephonyManagerEx.getDefault().isTestIccCard(0)) {
                            MmsLog.d(TAG, "All threads has been deleted, send notification..");
                            SmsManager
                                    .getSmsManagerForSubscriptionId(
                                   SmsReceiverService.sLastIncomingSmsSubId).getDefault().setSmsMemoryStatus(true);
                        }
                    } catch (Exception ex) {
                        MmsLog.e(TAG, " " + ex.getMessage());
                    }
                    // Update the notification for new messages since they
                    // may be deleted.
                    MessagingNotification.nonBlockingUpdateNewMessageIndicator(
                            ComposeMessageActivity.this, MessagingNotification.THREAD_NONE, false);
                    // Update the notification for failed messages since they
                    // may be deleted.
                    updateSendFailedNotification();
                    MessagingNotification.updateDownloadFailedNotification(ComposeMessageActivity.this);
                    break;
                    /// @}
                case DELETE_MESSAGE_TOKEN:
                    /// M: google jb.mr1 patch, Conversation should scroll to the bottom
                    /// when incoming received @{
                    if (cookie instanceof Boolean && ((Boolean)cookie).booleanValue()) {
                        // If we just deleted the last message, reset the saved id.
                        mLastMessageId = 0;
                    }
                    /// @}
                    /// M: Code analyze 027,Add for deleting one message.@{
                    MmsLog.d(TAG, "onDeleteComplete(): before update mConversation, ThreadId = " + mConversation.getThreadId());
                    ContactList recipients = getRecipients();
                    mConversation = Conversation.upDateThread(ComposeMessageActivity.this, mConversation.getThreadId(), false);
                    mThreadCountManager.isFull(mThreadId, ComposeMessageActivity.this,
                            ThreadCountManager.OP_FLAG_DECREASE);
                    /// @}
                    // Update the notification for new messages since they
                    // may be deleted.
                    MessagingNotification.nonBlockingUpdateNewMessageIndicator(
                            ComposeMessageActivity.this, MessagingNotification.THREAD_NONE, false);
                    // Update the notification for failed messages since they
                    // may be deleted.
                    updateSendFailedNotification();
                    /// M: Code analyze 027,Add for deleting one message.@{
                    MessagingNotification.updateDownloadFailedNotification(ComposeMessageActivity.this);
                    MmsLog.d(TAG, "onDeleteComplete(): MessageCount = " + mConversation.getMessageCount() +
                            ", ThreadId = " + mConversation.getThreadId());
                    if (mIpCompose.onDeleteComplete(token)) {
                        break;
                    }
                    if (mConversation.getMessageCount() <= 0 || mConversation.getThreadId() <= 0L) {
                        mMsgListAdapter.changeCursor(null);
                        if (needSaveDraft() && (recipients != null)) {
                            if (!isRecipientsEditorVisible()) {
                                makeDraftEditable(recipients);
                            }
                        } else {
                            /// M: fix bug for ConversationList select all performance ,update selected threads array.@{
                            ConversationListAdapter.removeSelectedState(mSelectedThreadId);
                            /// @
                            finish();
                        }
                    }
                    /// @}
                    break;
            }
            // If we're deleting the whole conversation, throw away
            // our current working message and bail.
            if (token == ConversationList.DELETE_CONVERSATION_TOKEN) {
                ContactList recipients = mConversation.getRecipients();
                Iterator iter = mMsgListAdapter.getItemList().entrySet().iterator();
                Boolean isMsgLocked = false;
                while (iter.hasNext()) {
                    @SuppressWarnings("unchecked")
                    Map.Entry<Long,Boolean> entry = (Entry<Long,Boolean>) iter.next();
                    if (entry.getValue()) {
                    	 if (isMsgLocked(entry)) {
                    		 Log.d(TAG," isMsgLocked(entry)    locked ");
                    		 isMsgLocked = true; 
                    		 break;
                    	 }
                    }
                }
                if( (! isMsgLocked) || (isMsgLocked && mIsDeleteLockMsg) ){
                	mWorkingMessage.discard();
                }
                
                // Remove any recipients referenced by this single thread from the
                // contacts cache. It's possible for two or more threads to reference
                // the same contact. That's ok if we remove it. We'll recreate that contact
                // when we init all Conversations below.
                if (recipients != null) {
                    for (Contact contact : recipients) {
                        contact.removeFromCache();
                    }
                }

                // Make sure the conversation cache reflects the threads in the DB.
                Conversation.init(getApplicationContext());
                //finish();
                startMsgListQuery(MESSAGE_LIST_QUERY_AFTER_DELETE_TOKEN, 0);
                //modify by hongtao.fu for defect 1552661 at 2016.2.17 end
            } else if (token == DELETE_MESSAGE_TOKEN) {
                /// M: Code analyze 027,Add for deleting one message.@{
                // Check to see if we just deleted the last message
                startMsgListQuery(MESSAGE_LIST_QUERY_AFTER_DELETE_TOKEN, 0);
                /// @}
            }
            if (mActionMode != null) {
            	mHandler.postDelayed(new Runnable() {
            		public void run() {
            			if (mActionMode != null && !isFinishing()) {
            				mActionMode.finish();
            			}
            		}
            	}, 300);
            }
        }
    }


上面是删除操作的具体实现AsyncQueryHandler类的具体实现,下面才是正式的调用,

例如,查询一条SMS的detail

        final String mGroupsSmsFlag = msgItem.mGroupsSmsFlag;
        mBackgroundQueryHandler
                .cancelOperation(MESSAGE_GROUP_DETAILS_QUERY_TOKEN);
        try {
            mBackgroundQueryHandler.postDelayed(new Runnable() {
                public void run() {
                    mBackgroundQueryHandler.startQuery(
                            MESSAGE_GROUP_DETAILS_QUERY_TOKEN, null,
                                   ContentUris.withAppendedId(Uri
                                           .withAppendedPath(
                                                   Telephony.MmsSms.CONTENT_URI,
                                                   "group_details"),
                                           mConversation.getThreadId()),
                               new String[] {
                                   Sms.ADDRESS
                               }, "group_sms_flag=?", new String[] {
                                   mGroupsSmsFlag
                               }, null);
                }
            }, 50);
        } catch (SQLiteException e) {
            SqliteWrapper.checkSQLiteException(ComposeMessageActivity.this, e);
        }
调用完成之后注意查看上面的第二段代码,里在里面可以通过token和cookie得到回调,通过回调显示具体的实现。


二。言归正转,删除的实现

下面是具体的实现,首先通过创建一个线程,然后在线程遍历每条信息,将sms,mms的KEY值(也是数据库中的_id),保存到agrsSmsList中。然后通过判断是否上锁,最后直接调用一个AsyncQueryHandler的删除操作,实现删除。
final boolean deleteLocked = mDeleteLockedMessages;
            new Thread(new Runnable() {
                public void run() {
                    Iterator iter = mMsgListAdapter.getItemList().entrySet().iterator();
                    Uri deleteSmsUri = null;
                    Uri deleteMmsUri = null;
                    ArrayList<String> argsSmsList = new ArrayList<String>();
                    ArrayList<String> argsMmsList = new ArrayList<String>();
                    int i = 0;
                    int j = 0;
                    while (iter.hasNext()) {
                        @SuppressWarnings("unchecked")
                        Map.Entry<Long,Boolean> entry = (Entry<Long,Boolean>) iter.next();
                        if (entry.getValue()) {
                        	 if (!mDeleteLockedMessages && isMsgLocked(entry)) {
                        			 continue;
                        	 }
                                if (entry.getKey() > 0) {
                                    MmsLog.i(TAG, "sms");
                                    argsSmsList.add(Long.toString(entry.getKey()));
                                   //argsSms[i] = Long.toString(entry.getKey());
                                    MmsLog.i(TAG, "argsSms[i]" + argsSmsList.get(i));
                                    deleteSmsUri = Sms.CONTENT_URI;
                                    i++;
                                } else {
                                    MmsLog.i(TAG, "mms");
                                    argsMmsList.add(Long.toString(-entry.getKey()));
                                   // argsMms[j] = Long.toString(-entry.getKey());
                                    MmsLog.i(TAG, "argsMms[j]" + argsMmsList.get(j));
                                    deleteMmsUri = Mms.CONTENT_URI;
                                    j++;
                                }
                        }
                    }
                    String[] argsSms = new String[argsSmsList.size()];
                    String[] argsMms = new String[argsMmsList.size()];
                    argsMmsList.toArray(argsMms);
                    argsSmsList.toArray(argsSms);
                    if (deleteSmsUri != null) {
                    	List<String> list=new ArrayList<String>();
						for (int count = 0; count < argsSms.length; count++) {
							MessageItem mMessageItem = getMessageItem("sms",Long.parseLong(argsSms[count]),true);
							Boolean deletingLastItem = false;
		                    Cursor cursor = mMsgListAdapter != null ? mMsgListAdapter.getCursor() : null;
		                    if (cursor != null) {
		                        cursor.moveToLast();
		                        long msgId = cursor.getLong(COLUMN_ID);
		                        deletingLastItem = msgId == mMessageItem.mMsgId;
		                    }
		                    boolean isLocked = mMessageItem.mLocked;
		                    MmsLog.d(TAG,"SMS the isLocked is :"+isLocked + "     and the deleteLocked is :"+deleteLocked);
		                    MmsLog.d(TAG, "SMS the mMessageItem.mMessageUri is : "+mMessageItem.mMessageUri);
		                    if (isLocked) {
		                    	if (deleteLocked) {
//		                    		mBackgroundQueryHandler.startDelete(DELETE_MESSAGE_TOKEN,
//				                            deletingLastItem, mMessageItem.mMessageUri,
//				                            isLocked ? null : "locked=0", null);
		                    		list.add(argsSms[count]);
								}
							} else {
//								mBackgroundQueryHandler.startDelete(DELETE_MESSAGE_TOKEN,
//			                            deletingLastItem, mMessageItem.mMessageUri,
//			                            isLocked ? null : "locked=0", null);
								list.add(argsSms[count]);
							}
						}
						if(list.size()>=1){
							String s[]=new String[list.size()];
							list.toArray(s);
							mBackgroundQueryHandler.startDelete(DELETE_MESSAGE_TOKEN, null,
		                            deleteSmsUri, FOR_MULTIDELETE, s);
						}
					}
                    
                    if (deleteMmsUri != null) {
                    	List<String> list=new ArrayList<String>();
						for (int count = 0; count < argsMms.length; count++) {
							MessageItem mMessageItem = getMessageItem("mms",Long.parseLong(argsMms[count]),true);
							Boolean deletingLastItem = false;
		                    Cursor cursor = mMsgListAdapter != null ? mMsgListAdapter.getCursor() : null;
		                    if (cursor != null) {
		                        cursor.moveToLast();
		                        long msgId = cursor.getLong(COLUMN_ID);
		                        deletingLastItem = msgId == mMessageItem.mMsgId;
		                    }
		                    boolean isLocked = mMessageItem.mLocked;
		                    MmsLog.d(TAG,"MMS the isLocked is :"+isLocked + "     and the deleteLocked is :"+deleteLocked);
		                    MmsLog.d(TAG, "MMS the mMessageItem.mMessageUri is : "+mMessageItem.mMessageUri);
		                    if (isLocked) {
		                    	if (deleteLocked) {
//		                    		mBackgroundQueryHandler.startDelete(DELETE_MESSAGE_TOKEN,
//				                            deletingLastItem, mMessageItem.mMessageUri,
//				                            isLocked ? null : "locked=0", null);
		                    		list.add(argsMms[count]);
								}
							} else {
//								mBackgroundQueryHandler.startDelete(DELETE_MESSAGE_TOKEN,
//			                            deletingLastItem, mMessageItem.mMessageUri,
//			                            isLocked ? null : "locked=0", null);
								list.add(argsMms[count]);
							}
						}
						if(list.size()>=1){
							String s[]=new String[list.size()];
							list.toArray(s);
							mBackgroundQueryHandler.startDelete(DELETE_MESSAGE_TOKEN, null,
		                            deleteMmsUri, FOR_MULTIDELETE, s);
						}
					}
                }
            }).start();
阅读上面的代码,有两段注释掉的代码,之前就是使用的注释掉的代码来删除,每删除一条调用一次AsyncQueryHander.startDelete()而这个方法涉及到多次回调,在它的回调中也涉及到大量的耗时操作,所以批量的删除信息会比较的慢。



三。数据库中批量删除的实现

content provider 中对于数据库的调用,最后会传递到数据库端,所以上面的调用,会出现不符合SQL的语法。
完整的SQL调用应该
SELECT DISTINCT thread_id FROM sms WHERE _id IN %s      //%s 等价与(,,,)

 public int delete(Uri url, String where, String[] whereArgs) {
。。。。
if (where != null && where.equals(FOR_MULTIDELETE)) {
                    Log.d(TAG, "delete FOR_MULTIDELETE");
                    String selectids = getSmsIdsFromArgs(whereArgs);
                    String threadQuery = String.format("SELECT DISTINCT thread_id FROM sms " +
                            "WHERE _id IN %s", selectids);
                    Cursor cursor = db.rawQuery(threadQuery, null);
                    /// M: fix ALPS01263429, consider cursor as view, we should read cursor
                    /// before delete related records.
                    long[] deletedThreads = null;
                    try {
                        deletedThreads = new long[cursor.getCount()];
                        int i = 0;
                        while (cursor.moveToNext()) {
                            deletedThreads[i++] = cursor.getLong(0);
                        }
                    } finally {
                        cursor.close();
                    }
                    String finalSelection = String.format(" _id IN %s", selectids);
                    count = deleteMessages(db, finalSelection, null);
                    if (count != 0) {
                        MmsSmsDatabaseHelper.updateMultiThreads(db, deletedThreads);
                    }
                    Log.d(TAG, "delete FOR_MULTIDELETE count = " + count);

实际的删除操作:

    /// M: because of triggers on sms and pdu, delete a large number of sms/pdu through an
    /// atomic operation will cost too much time. To avoid blocking other database operation,
    /// remove trigger sms_update_thread_on_delete, and set a limit to each delete operation. @{
    private static final int DELETE_LIMIT = 100;

    static int deleteMessages(SQLiteDatabase db,
            String selection, String[] selectionArgs) {
        Log.d(TAG, "deleteMessages, start");
        int deleteCount = DELETE_LIMIT;
        if (TextUtils.isEmpty(selection)) {
            selection = "_id in (select _id from sms limit " + DELETE_LIMIT + ")";
        } else {
            selection = "_id in (select _id from sms where " + selection
            + " limit " + DELETE_LIMIT + ")";
        }
        int count = 0;
        while (deleteCount > 0) {
            deleteCount = db.delete(TABLE_SMS, selection, selectionArgs);
            count += deleteCount;
            Log.d(TAG, "deleteMessages, delete " + deleteCount + " sms");
        }
        Log.d(TAG, "deleteMessages, delete sms end");
        return count;
    }

对上面方法调用进行整理,得到实际的应用语句应该是:

 while (deleteCount > 0) {
            deleteCount = db.delete(TABLE_SMS, <span style="font-family: Arial, Helvetica, sans-serif;">_id in (select _id from sms where </span><span style="font-family: Arial, Helvetica, sans-serif;">_id IN %s )</span>,<span style="font-family: Arial, Helvetica, sans-serif;">selectids</span>);
            count += deleteCount;
            Log.d(TAG, "deleteMessages, delete " + deleteCount + " sms");
        }

通过上面的注释,我们发现里面的 为了避免数据库阻塞,这里对实际删除的操作还进行了一个最大值的判断,这一点在很多地方都没有讲解,但是再实际的应用中,我们都应该注意这一点。









1
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:25419次
    • 积分:577
    • 等级:
    • 排名:千里之外
    • 原创:31篇
    • 转载:33篇
    • 译文:0篇
    • 评论:3条
    文章分类
    最新评论