1

I am developing an android app. Each activity binds to a service that is used to do all the actual work. Normally, everything works great - but not when an array with about 100 000 objects arrives from the server as an update.

After about 10 000 objects are inserted the DB thread and even the UI thread hangs. The processor load is never more than 60%, memory used is less than 200 MB.

I do all my DB work in a separate thread on the service; I make sure not to overload the Db queue, extracting objects from the JsonArray just enough so that there are always about 100 objects in DB thread queue.

When the big array with updates arrives from the server as a Json Array, I gradually disassemble it and work with each object separately.

Db queue uses Room to access the database.

`@Update(onConflict = OnConflictStrategy.FAIL)`
`public abstract void update(User localTransport);`

There are no transactions.

Ids of all DB objects are stored in a HashMap so I may choose to update or insert a row with no overhead.

Here is my update function:

private long doUpdateOrInsert(Sendable s) {
    if (Core.core.dbHelper.storage.hasItem(s)) {
        dbDao.updateSendable(s);
        return s.id;
    }
    else {
        long id = this.dbDao.insert(s);
        Core.core.dbHelper.storage.addItem(s,id);
        return id;
    }
}

Please, could you tell me how to solve this problem? Why does my UI thread hang? I don't get anything unusual in logs except for ANR cause UI is unresponsive for five seconds and my logs that my DB thread stops processing messages.

Edit:

Sorry for not stating clearly, all my work is done on a Service. It is separate from activities, launched with startService(), and is bound to the current activity. Db Thread is run by a separate thread in the Service.

Here are the screenshots of profiler after app randomly died and returned to the previous screen even though I din't touch the phone, without even writing anything to the app logs.

Threads

Memory

  • Have you [profiled your app](https://developer.android.com/studio/profile/android-profiler)? – Morrison Chang Feb 16 '19 at 05:55
  • Yes, I did, and I didn't see anything weird. All my threads were running with plenty of sleep time, UI threads were almost free. – Ilya Shishlakov Feb 16 '19 at 08:10
  • I don't see thread `main` on that profile, though. What is thread `main` doing? If it is blocked, your UI's gonna hang. – greeble31 Feb 16 '19 at 17:34
  • I think I figured it out. I saw a flash of OutOfMemory exception. It is weird cause there is no memory shortage on the phone - system tells that there are 700 mb free memory, and my app uses 200 mb. – Ilya Shishlakov Feb 17 '19 at 11:26

2 Answers2

0

Maybe try using rxJava for db operations(use schedulers for threads) and use events to update ui

user8024871
  • 71
  • 1
  • 7
  • I am not sure that migrating from Room is optimal, as a lot of functions in both Sever and Client were built around the DAO file. I already use the events to update UI! Perhaps I would have to decrease the object amount and change db functions to work not with a single object, but a couple of hundreds at the same time? Still, concerned about the sudden problems. Better to solve them now then leave them for later. Thank you for the advice! – Ilya Shishlakov Feb 16 '19 at 08:33
0

Use an IntentService, so that the work is done on a background thread.

I tried to make a thread that will do the upload/download but once the Service is finished Android kill my Thread.

Which is why you should use an IntentService, as Android manages both the background thread and stopping the Service for you. You just send it work via

startService()

and do the work in onHandleIntent().

Service class uses the application's main thread, while IntentService creates a worker thread and uses that thread to run the service.

Akash Pal
  • 1,055
  • 8
  • 15
  • Thank you for your reply! Indeed, Service is mandatory - but I already use a service. I use startService() and then bind with activities to the service, and the Db is a separate thread. That's the problem basically - I don't see any obvious problems. Sure, about 1 000 000 objects is a lot - but they are created and destroyed in the span of several minutes, so no more then 100 MB memory is used. – Ilya Shishlakov Feb 16 '19 at 09:12
  • thats what i was asking wherther you are using Service or IntentService – Akash Pal Feb 16 '19 at 09:16
  • Service class uses the application's main thread, while IntentService creates a worker thread and uses that thread to run the service. – Akash Pal Feb 16 '19 at 09:18
  • So, I should use Intent Service when I need to do some work? Actually, I do all the work in separate thread - the Service class I use does nothing more then start the threads, so App doesn't crash because I run work on UI thread - there is some hidden limit that forces all threads, including UI thread, to stop – Ilya Shishlakov Feb 16 '19 at 09:35
  • yeah in this particular casse where you need to do a particular ammount of work leave that on IntentService it will handle it good – Akash Pal Feb 16 '19 at 09:36
  • using intent service in database would make sure that the work is continued on worker thrad that will be created as result of IntentService – Akash Pal Feb 16 '19 at 09:38
  • Sorry, replied in the message above yours) Thank you for the info! But I don't use Service to do the db access, I have separate threads that do it. Like this: – Ilya Shishlakov Feb 16 '19 at 09:38
  • public class DbConnection extends Connection implements Runnable – Ilya Shishlakov Feb 16 '19 at 09:40
  • As, you said "all my work is done on a Service." So, all i am saying is use intentService and see if it helps and i would suggest learning about the different use case of different types of service – Akash Pal Feb 16 '19 at 09:41
  • please take a look here : https://stackoverflow.com/questions/15524280/service-vs-intentservice might help – Akash Pal Feb 16 '19 at 09:43
  • 1
    Thank you! Now I will try to migrate to IntentService and see if this solves the issue! – Ilya Shishlakov Feb 16 '19 at 09:46
  • Well there is not much to do ; try and let me know if it dosent help – Akash Pal Feb 16 '19 at 09:48