Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android data storage performance

Tags:

android

mobile

I m actually developping an Android application with data storage, and I proceed like this :

Activity -> Business services -> Repo (with Spring REST fw). Using this, I m forced to let the activity finish his storing job before closing it (thread treatment, progress dialog ...).

Is this a bad way of coding to use an android service to store data ?

With this, users can continue to navigate, and have the impression to work with a very fluid application. Is this a good solution ?

Thanks

like image 215
mfrachet Avatar asked Nov 27 '22 17:11

mfrachet


1 Answers

There is no need to keep your activity in the foreground waiting for a background logic to complete.

What you should do instead is to execute this background logic in a way which is 'detached' from your activity.

There are two ways of solving this problem: risky and safe.


The Risky Way

class MyActivity extends Activity {

     void calledWhenActivityNeedsToBeClosed() {

          // start a thread to do background work
          new Thread() {
                public void run() {
                     perform long running logic here
                }
          }.start();

          // and clos the activity without waiting for the thread to complete
          this.finish();
     }
}

You can use an AsyncTask or any of the java.concurrent constructs instead of the thread. They will all do the work.

I have used this way for years. It mostly works fine. But.. it is inherently flawed.
Why? Because once activity is finish()-ed, Android can at any time reclaim it together with all its resources and including halting of all worker threads.
If your long running work does not exceed several seconds, and I assume your repo update is such, the risk here is minimal. But why take it?


The Safe Way

Declare a Service and before activity going down activate it to perform the long running action:

class MyActivity extends Activity {

     void calledWhenActivityNeedsToBeClosed() {

          // delegate long running work to service
          startService(this, new Intent(this, MyWorkerService.class));

          // and close the activity without waiting for the thread to complete
          this.finish();
     }

}


This is much safer. Android can, and often does, also kill running services, but is does so much more reluctantly than killing background activities.


Note that if you can see a scenario in which your UI is visible while the worker service is still running, you would probably want to use an IntentService instead.


Finally - if you want to be absolutely assured that background logic will not be cleared by Android, you should use a foreground service. Below is how to do it, but please be warned - in cases like you have described, a foreground service is probably over engineering:

static final int NOTIF_ID = 100;

// Create the FG service intent 
Intent intent = new Intent(getApplicationContext(), MyActivity.class); // set notification activity
showTaskIntent.setAction(Intent.ACTION_MAIN);
showTaskIntent.addCategory(Intent.CATEGORY_LAUNCHER);
showTaskIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

PendingIntent pIntent = PendingIntent.getActivity(
                getApplicationContext(),
                0,
                intent,
                PendingIntent.FLAG_UPDATE_CURRENT);

Notification notif = new Notification.Builder(getApplicationContext())
                .setContentTitle(getString(R.string.app_name))
                .setContentText(contentText)
                .setSmallIcon(R.drawable.ic_notification)
                .setContentIntent(pIntent)
                .build();

startForeground(NOTIF_ID, notif);


like image 159
Gilad Haimov Avatar answered Dec 10 '22 06:12

Gilad Haimov