Android App 디 버 깅 메모리 유출 Cursor 편
// Sample Code
Cursor cursor = db.query();
List<String> list = convertToList(cursor);
cursor.close();
이것 은 가장 간단 한 cursor 사용 장면 입 니 다.만약 에 이곳 의 cursor 가 닫 히 지 않 았 다 면 수많은 침 과 욕 을 불 러 일 으 킬 수 있 었 을 것 이 라 고 생각 합 니 다.그러나 실제 장면 은 그렇지 않 을 수 있 습 니 다.이곳 의 cursor 는 닫 히 지 않 을 수도 있 습 니 다.적어도 다음 과 같은 두 가지 가능성 이 있 습 니 다.2.Cursor 가 닫 히 지 않 았 을 가능성(1).cursor.close()이전에 이상 이 발생 했 습 니 다.(2).cursor 는 계속 사용 해 야 합 니 다.바로 닫 을 수 없습니다.뒤에서 닫 는 것 을 잊 었 습 니 다.3.Cursor.close()이전에 이상 이 발생 한 것 은 쉽게 이해 할 수 있 고 초보 자 들 이 처음에 겪 는 흔 한 문제 일 것 이다.예 를 들 어 다음 과 같다.
try {
Cursor c = queryCursor();
int a = c.getInt(1);
......
// , cursor.close()
......
c.close();
} catch (Exception e) {
}
정확 한 표기 법 은 다음 과 같다.
Cursor c;
try {
c = queryCursor();
int a = c.getInt(1);
......
// , cursor.close()
//c.close();
} catch (Exception e) {
} finally{
if (c != null) {
c.close();
}
}
간단 하지만 항상 명심 해 야 한다.4.Cursor 는 계속 사용 해 야 합 니 다.바로 닫 을 수 없습니다.이런 경우 가 있 습 니까?어 떡 하지?정 답 은 있 습 니 다.Cursor Adapter 는 전형 적 인 예 입 니 다.Cursor Adapter 예 는 다음 과 같 습 니 다.
mCursor = getContentResolver().query(CONTENT_URI, PROJECTION,
null, null, null);
mAdapter = new MyCursorAdapter(this, R.layout.list_item, mCursor);
setListAdapter(mAdapter);
// mCursor.close(),
// list
5.이러한 Cursor 는 언제 닫 아야 합 니까?이것 은 대답 을 잘 할 수도 있 고 대답 하기 어 려 울 수도 있 는 질문 입 니 다.바로 Cursor 가 더 이상 사용 하지 않 을 때 닫 는 것 입 니 다.예 를 들 어 위의 조 회 는 들 어가 거나 resume 에 들 어 갈 때마다 다시 조회 하여 실 행 됩 니 다.일반적으로 이런 수요 이기 도 합 니 다.제 가 화면 을 볼 수 없 을 때 계속 조회 결 과 를 표시 하 는 경 우 는 드 물 죠.만약 에 정말 있 으 면 토론 하지 않 고 최종 적 으로 끄 면 OK 입 니 다.이 럴 때 우 리 는 보통 onStop()방법 에서 cursor 를 끌 수 있다.4567913)저 는 Cursor Adapter 의 change Cursor()방법 소스 코드 를 전문 적 으로 동봉 하여 여러분 에 게 더욱 분명하게 보 여 드 리 겠 습 니 다.불안 하지 않도록 change Cursor(null)방법:
@Override
protected void onStop() {
super.onStop();
// mCursorAdapter cursor, cursor
mCursorAdapter.changeCursor(null);
}
6.실전 AsyncQuery Handler 에서 Cursor 의 닫 기 문제 AsyncQuery Handler 는 전형 적 인 분석 Cursor 의 예 입 니 다.피 를 볼 수 있 을 뿐만 아니 라 하 나 를 보면 열 을 수 있 을 뿐만 아니 라 매우 흔 합 니 다.나중에 피하 기 위해 서.AsyncQueryHandler 문서 참조 주소:http://developer.android.com/reference/android/content/AsyncQueryHandler.html 다음 코드 는 Android 2.3 시스템 에서 Mms 정보 홈 페이지 의 ConversationList 소스 코드 의 일부분 입 니 다.Cursor 가 정확하게 닫 혔 는 지 보 시 겠 습 니까?4567913)
/**
* Change the underlying cursor to a new cursor. If there is an existing cursor it will be
* closed.
*
* @param cursor The new cursor to be used
*/
public void changeCursor(Cursor cursor) {
Cursor old = swapCursor(cursor);
if (old != null) {
old.close();
}
}
/**
* Swap in a new Cursor, returning the old Cursor. Unlike
* {@link #changeCursor(Cursor)}, the returned old Cursor is <em>not</em>
* closed.
*
* @param newCursor The new cursor to be used.
* @return Returns the previously set Cursor, or null if there wasa not one.
* If the given new Cursor is the same instance is the previously set
* Cursor, null is also returned.
*/
public Cursor swapCursor(Cursor newCursor) {
if (newCursor == mCursor) {
return null;
}
Cursor oldCursor = mCursor;
if (oldCursor != null) {
if (mChangeObserver != null) oldCursor.unregisterContentObserver(mChangeObserver);
if (mDataSetObserver != null) oldCursor.unregisterDataSetObserver(mDataSetObserver);
}
mCursor = newCursor;
if (newCursor != null) {
if (mChangeObserver != null) newCursor.registerContentObserver(mChangeObserver);
if (mDataSetObserver != null) newCursor.registerDataSetObserver(mDataSetObserver);
mRowIDColumn = newCursor.getColumnIndexOrThrow("_id");
mDataValid = true;
// notify the observers about the new cursor
notifyDataSetChanged();
} else {
mRowIDColumn = -1;
mDataValid = false;
// notify the observers about the lack of a data set
notifyDataSetInvalidated();
}
return oldCursor;
}
문제 가 있다 고 생각 하 십 니까?주로 두 가지:(1).THREADLIST_QUERY_TOKEN 분기 의 Cursor 가 정확하게 닫 혔 나 요?(2). HAVE_LOCKED_MESSAGES_TOKEN 분기 의 Cursor 가 정확하게 닫 혔 나 요?앞의 조목조목 분석 에 따 르 면 답 은(1).THREAD 이다.LIST_QUERY_TOKEN 분기 의 Cursor 는 mListAdapter 에 전달 되 었 으 며,mListAdapter 는 onStop 에서 changeCursor(null)를 사용 합 니 다.사용자 가 현재 Activity 를 떠 날 때 이 Cursor 는 정확하게 방출 되 어 누설 되 지 않 습 니 다.(2). HAVE_LOCKED_MESSAGES_TOKEN 분기 의 Cursor(즉,매개 변수 cursor)는 하나의 판단 의 조건 으로 사용 되 고 사용 되 지 않 지만 꺼 지지 않 아 cursor 가 유출 되 었 습 니 다.StrictMode 감시 하에 이 곳 에 도착 하면 이 오류 가 발생 합 니 다.E/StrictMode(639):A resource was acquired at attached stack trace but never released.See java.io.Closeable for information on avoiding resource leaks.E/StrictMode(639):java.lang.Throwable:Explicit termination method'close'not called E/StrictMode(639):at dalvik.system...................................................................................실제로 인터넷 에 서 는 AsyncQuery Handler 를 많이 사용 합 니 다.예 를 들 어 이 실 수 를 저 질 렀 습 니 다.이 글 을 본 후에 다 시 는 AsyncQuery Handler 의 cursor 가 유출 되 는 것 을 두려워 하지 않 습 니 다.그리고 현재 사용 하고 있 는 배경 strictmode 의 cursor not close 이상 문 제 를 해결 할 수 있 을 지도 모른다 고 합 니 다.7.소결 은 아직 cursor 가 닫 히 지 않 은 경우 가 많다 고 생각 하지만 근본 적 인 문 제 는 바로 cursor 를 정확하게 닫 는 것 입 니 다.메모리 유출 cursor 편 은 제 업무 경험 상의 정리 입 니 다.잘 훑 어 본 후에 저 자신 이 모두 에 게 도움 이 되 고 복잡 한 문 제 를 본질 화하 고 단순화 시 킵 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
IOS 메모리 누출 검사 방법 및 MLeakFinder 다시 쓰기iOS 개발에 있어 메모리 유출 문제는 이미 흔히 말하는 화제이다.일상적인 면접에서 이런 문제들이 자주 언급된다.우리는 일상적인 개발 과정에서 메모리 유출 검사를 하는데 일반적으로 인스트루먼트 도구의 Leaks/Al...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.