Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update UI while working on background

I have an update database operation, that has an activity, which keeps updating the percentage and it runs inside an AsyncTask.

Inside doInBackground() I call the controller that updates the database and keep updating the percentage on the activity, however, if I press home button or back button, the operation is cancelled. What u suggest me to do?

I was trying to start a Service inside doInBackground() so it would run in background, but it looks like its not working.

My code looks like this:

public class UpdateDatabaseAsyncTask extends AsyncTask<Void, Integer, Integer>
{   
    @Override
    public void onPreExecute()
    {
        mCustomProgressBar.startAnimation();
    }

    @Override
    public Integer doInBackground(Void... params)
    {
        return mController.updateDatabase();
    }

    @Override
    public void onPostExecute(Integer result)
    {
        mCustomProgressBar.stopAnimation();
        // finish the activity
    }

    @Override
    public void onProgressUpdate(Integer... value)
    {
        updatePercentageValue(value[0]);
    }

    public void callPublishProgress(Integer value)
    {
        publishProgress(value);
    }
}

And inside the controller I call the method callPublishProgress(value) passing the current percentage value, so it will publishProgress(value) in the UI.

I was debugging, and I pressed the home/back button, and it just stopped running the worker thread.


Another solution I tried, was starting a Service to run in background no matter the user press home/back button or not, so I thought, and the Service would make a call to the controller method that does the work, and it would call the callPublishProgress(value) to update the percentage value on the UI anyways.

However, what was happening is, the code reach doInBackground() and start the service, but it goes to onPostExecute() immediately, it just didn't wait the service to finish(of course!). So it gives a NullPointerException. I thought of making a loop inside doInBackground() with a flag set in the Service, so it would leave this loop while the service hasn't been finished (I was using an IntentService), but it didn't work anyways.

I thought of using a Timer too. But I don't know.

I was reading the articles in documentation about Threads, etc. And it suggests using AsyncTask, just as I was trying to do. It also talks about runOnUiThread(Runnable).

Anyways what I need is to make an operation in background(probably using an IntentService), so no matter if the user press the home button, it will keep running, but it must update the percentage on the UI, and when the user leave the screen and back to it, it shows the current percentage value updated in the screen.

What is the best solution for my case?

Thanks.

like image 578
rogcg Avatar asked Apr 27 '12 17:04

rogcg


People also ask

How would you update the UI of an activity from a background service?

Step 1 − Create a new project in Android Studio, go to File ⇒ New Project and fill all required details to create a new project. Step 2 − Add the following code to res/layout/activity_main. xml. In the above code, we have taken text view, when user gets the data from intent service it will update.

Can I update the UI on background thread Android?

In this case, to update the UI from a background thread, you can create a handler attached to the UI thread, and then post an action as a Runnable : Handler handler = new Handler(Looper. getMainLooper()); handler. post(new Runnable() { @Override public void run() { // update the ui from here } });

Is it a good idea to update a UI element from a background task?

You're updating the UI from a background thread. Don't do that. But the runtime is not required to provide a safety system that prevents or detects your error. It is not required to produce an error when you do something that you shouldn't be doing in the first place.

What is update UI?

The updateUI() method of the BackgroundFetchUpdateUIEvent interface updates the title and icon in the user interface to show the status of a background fetch. This method may only be run once, to notify the user on a failed or a successful fetch.


3 Answers

public class MyServce extends Service{
public static final String BROADCAST_ACTION = "com.myapp";
Intent intent;
private final Handler handler = new Handler();

@Override
public void onCreate()
{
    super.onCreate();
    intent = new Intent(BROADCAST_ACTION);
}

 @Override
    public void onStart(Intent intent, int startId) {
        handler.removeCallbacks(sendUpdatesToUI);
        handler.postDelayed(sendUpdatesToUI, 1000); // 1 second

    }
   private Runnable sendUpdatesToUI = new Runnable() {
        public void run() {
            DoYourWorking();        
            handler.postDelayed(this, 1000); // 1 seconds
        }

        private void DoYourWorking() {
        ........
                    ........
                     intent.putExtra("key", progress);
             sendBroadcast(intent);

        }
    };   

@Override
public IBinder onBind(Intent intent) {
    // TODO Auto-generated method stub
    return null;
}
@Override
public void onDestroy() {   
    super.onDestroy();
    handler.removeCallbacks(sendUpdatesToUI);       

}

Now in your Activity register broadcast to service

private BroadcastReceiver brodcast = new BroadcastReceiver() {

    @Override
    public void onReceive(Context context, Intent intent) {
                 //intent.getWhatever
        // update your progress
        //progressbar.setProgress 
    }

register broadcast

 registerReceiver(brodcast, new IntentFilter(MyService.BROADCAST_ACTION));
like image 144
Sunny Avatar answered Sep 20 '22 11:09

Sunny


This worked for me. I started a background service on a thread that just fetches the values and updates an object in a singleton.

In the view controller, I start a timer that keeps updating the view by fetching data from the object in singleton.

I had a little problem understanding your entire question text, so I'm not sure if you have tried this. But this is what worked. Also, the service was started with START_STICKY

like image 37
kishu27 Avatar answered Sep 18 '22 11:09

kishu27


Use an IntentService (which is a Service on a thread of its own), and Handler to pass the data back to the Activity.

like image 37
Yusuf X Avatar answered Sep 19 '22 11:09

Yusuf X