Function called on resume of the fragment. →
private fun getUnreadGrpMessageCount() {
try {
CometChat.getUnreadMessageCountForAllGroups(true, object :
CometChat.CallbackListener<HashMap<String?, Int?>?>() {
override fun onSuccess(stringIntegerHashMap: HashMap<String?, Int?>?) {
juiceActivityViewModel.grpChatList.forEach { groupChat ->
run {
val matchingGuids =
stringIntegerHashMap?.keys?.filter { gUID -> groupChat.groupId == gUID }
if (matchingGuids?.size ?: 0 > 0) {
val matchingGuid = matchingGuids?.get(0)
if (matchingGuid != null) {
groupChat.unReadMessageCount =
stringIntegerHashMap?.get(matchingGuid)
}
} else {
groupChat.unReadMessageCount = 0
}
}
}
channelAdapter.refreshAdapter(
juiceActivityViewModel.grpChatList,
juiceActivityViewModel.selectedChannelId
)
}
override fun onError(e: CometChatException?) {
Timber.e(e)
}
})
} catch (e: Exception) {
Timber.e(e)
}
}
Error Log->
Fatal Exception: java.lang.RuntimeException
Unable to resume activity {com.example.exampleApp/com.example.exampleApp.view.juice.JuiceActivity}: android.database.CursorWindowAllocationException: Cursor window allocation of 4194304 bytes failed. # Open Cursors=454 (# cursors opened by this proc=454)
android.app.ActivityThread.performResumeActivity (ActivityThread.java:4053)
android.app.ActivityThread.handleResumeActivity (ActivityThread.java:4085)
android.app.servertransaction.ResumeActivityItem.execute (ResumeActivityItem.java:51)
android.app.servertransaction.TransactionExecutor.executeLifecycleState (TransactionExecutor.java:145)
android.app.servertransaction.TransactionExecutor.execute (TransactionExecutor.java:70)
android.app.ActivityThread$H.handleMessage (ActivityThread.java:1984)
android.os.Handler.dispatchMessage (Handler.java:106)
android.os.Looper.loop (Looper.java:216)
android.app.ActivityThread.main (ActivityThread.java:7211)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:494)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:975)
Caused by android.database.CursorWindowAllocationException
Cursor window allocation of 4194304 bytes failed. # Open Cursors=454 (# cursors opened by this proc=454)
android.database.CursorWindow. (CursorWindow.java:142)
android.database.sqlite.SQLiteCursor.clearOrCreateWindow (SQLiteCursor.java:315)
android.database.sqlite.SQLiteCursor.fillWindow (SQLiteCursor.java:155)
android.database.sqlite.SQLiteCursor.getCount (SQLiteCursor.java:149)
android.database.AbstractCursor.moveToPosition (AbstractCursor.java:220)
android.database.AbstractCursor.moveToFirst (AbstractCursor.java:259)
com.cometchat.pro.repo.CurrentUserRepo.getCurrentUser (CurrentUserRepo.java:111)
com.cometchat.pro.core.ApiConnection.getDefaultHeaders (ApiConnection.java:1104)
com.cometchat.pro.core.ApiConnection.getGroupConversations (ApiConnection.java:685)
com.cometchat.pro.core.CometChat.getGroupConversations (CometChat.java:2763)
com.cometchat.pro.core.MessagesRequest.fetchMessagesForGroup (MessagesRequest.java:199)
com.cometchat.pro.core.MessagesRequest.fetchPrevious (MessagesRequest.java:92)
com.example.exampleApp.view.juice.ChatScreenFragment.fetchMessage (ChatScreenFragment.kt:945)
com.example.exampleApp.view.juice.ChatScreenFragment.onResume (ChatScreenFragment.kt:333)
androidx.fragment.app.Fragment.performResume (Fragment.java:2748)
androidx.fragment.app.FragmentStateManager.resume (FragmentStateManager.java:373)
androidx.fragment.app.FragmentManager.moveToState (FragmentManager.java:1211)
androidx.fragment.app.FragmentManager.moveToState (FragmentManager.java:1368)
androidx.fragment.app.FragmentManager.moveFragmentToExpectedState (FragmentManager.java:1446)
androidx.fragment.app.FragmentManager.moveToState (FragmentManager.java:1509)
androidx.fragment.app.FragmentManager.dispatchStateChange (FragmentManager.java:2637)
androidx.fragment.app.FragmentManager.dispatchResume (FragmentManager.java:2601)
androidx.fragment.app.Fragment.performResume (Fragment.java:2757)
androidx.fragment.app.FragmentStateManager.resume (FragmentStateManager.java:373)
androidx.fragment.app.FragmentManager.moveToState (FragmentManager.java:1211)
androidx.fragment.app.FragmentManager.moveToState (FragmentManager.java:1368)
androidx.fragment.app.FragmentManager.moveFragmentToExpectedState (FragmentManager.java:1446)
androidx.fragment.app.FragmentManager.moveToState (FragmentManager.java:1509)
androidx.fragment.app.FragmentManager.dispatchStateChange (FragmentManager.java:2637)
androidx.fragment.app.FragmentManager.dispatchResume (FragmentManager.java:2601)
androidx.fragment.app.FragmentController.dispatchResume (FragmentController.java:269)
androidx.fragment.app.FragmentActivity.onResumeFragments (FragmentActivity.java:478)
androidx.fragment.app.FragmentActivity.onPostResume (FragmentActivity.java:467)
androidx.appcompat.app.AppCompatActivity.onPostResume (AppCompatActivity.java:204)
android.app.Activity.performResume (Activity.java:7649)
android.app.ActivityThread.performResumeActivity (ActivityThread.java:4045)
android.app.ActivityThread.handleResumeActivity (ActivityThread.java:4085)
android.app.servertransaction.ResumeActivityItem.execute (ResumeActivityItem.java:51)
android.app.servertransaction.TransactionExecutor.executeLifecycleState (TransactionExecutor.java:145)
android.app.servertransaction.TransactionExecutor.execute (TransactionExecutor.java:70)
android.app.ActivityThread$H.handleMessage (ActivityThread.java:1984)
android.os.Handler.dispatchMessage (Handler.java:106)
android.os.Looper.loop (Looper.java:216)
android.app.ActivityThread.main (ActivityThread.java:7211)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:494)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:975)
I also gone through the file “CurrentUserRepo” → getCurrentUser function.
public static CurrentUser getCurrentUser() {
CurrentUser user = null;
try {
SQLiteDatabase db = SQLiteManager.getInstance().openDatabase();
Cursor cursor = db.rawQuery("SELECT * FROM CurrentUser WHERE uid LIKE '" + PreferenceHelper.getLoggedInUID() + "'", (String[])null);
if (cursor != null && cursor.moveToFirst()) {
cursor.moveToFirst();
user = new CurrentUser();
user.setUid(cursor.getString(0));
user.setName(cursor.getString(1));
user.setAvatar(cursor.getString(3));
user.setLink(cursor.getString(4));
user.setRole(cursor.getString(5));
if (cursor.getString(6) != null) {
user.setMetadata(new JSONObject(cursor.getString(6)));
}
user.setStatus(cursor.getString(8));
user.setStatusMessage(cursor.getString(9));
user.setLastActiveAt(cursor.getLong(10));
user.setIdentity(cursor.getString(11));
user.setSecret(cursor.getString(12));
user.setAuthToken(cursor.getString(13));
user.setJwt(cursor.getString(14));
String tagsArray = cursor.getString(15);
if (tagsArray != null) {
JSONArray tags = new JSONArray(tagsArray);
List<String> tagsList = new ArrayList();
for(int i = 0; i < tags.length(); ++i) {
tagsList.add(tags.getString(i));
}
user.setTags(tagsList);
}
}
SQLiteManager.getInstance().closeDatabase();
} catch (JSONException var7) {
Logger.error("Error getting users from local database : " + var7.getMessage());
}
return user;
}
Here the cursor used is not closed anywhere and is being called multiple times.
I debugged the code placing the breakpoint on getCurrentUser() which is being called 30-40 times in debug build and is continuously called in some intervals.