Search code examples
androidandroid-fragmentsandroid-progressbarevent-busotto

Circle Progress Bar on Fragment is not showing progress


I'm trying to show feedback the percentage of which they have downloaded data from a server.

The flow goes something like this:

LoginActivity - onSuccess, call Service to download data - while Service is working, I've already switched the user to HomeActivity

HomeActivity -This activities layout holds a Fragment I created called LoadingFragment -There is a method in LoadingFragment that is subscribed to an event that is posted by the Service

My problem is that the Fragment UI is not changing at all whenever an event has been posted.

I logged everything, and I can see the event posting the correct data but the data is not being reflected on the UI.

Below is my Service:

@Override
public int onStartCommand(Intent intent, int flags, final int startId) {

    Integer id = intent.getIntExtra("id", 0);
    //do sync here
    Log.i(LOG_TAG, "Make rest call to retrieve all r for id: " + id);
    mRestClient.getApiService().getR(id, new Callback<List<R>>() {
        @Override
        public void success(List<R> rResponse, Response response) {
            Integer outstanding = routeResponse.size();
            Integer percentage;
            LoadingEvent loadingEvent = new LoadingEvent();
            SyncEvent syncEvent = new SyncEvent();

            Log.i(LOG_TAG, "Callback success r");
            System.out.println("yohellotest");
            Log.i(LOG_TAG, "Begin insertion");

            DaoMaster daoMaster = MyApp.getDaoMaster();
            DaoSession session = daoMaster.newSession();
            SQLiteDatabase db = session.getDatabase();
            RDao rDao = session.getRDao();
            WDao wDao = session.getWDao();
            JDao jDao = session.getJDao();

            Log.i(LOG_TAG, "--Beginning Transaction--");
            //db.beginTransaction();
            try {
                int counter = 0;
                for(int i = 0; i < rResponse.size(); i++) {
                    R r = rResponse.get(i);
                    rDao.insert(r);
                    Log.i(LOG_TAG, "inserted r: " + r.getId());

                    for(int j = 0; j < r.getW().size(); j++) {
                        W w = r.getW().get(j);
                        wDao.insert(w);
                        Log.i(LOG_TAG, "inserted w: " + w.getId());

                        for(int k = 0; k < w.getJ().size(); k++) {
                            J j = w.getJ().get(k);
                            jDao.insert(j);
                            Log.i(LOG_TAG, "inserted j: " + j.getJId());
                        }
                    }
                    counter += 1;
                    percentage = (int) Math.floor((double) counter / outstanding * 100);
                    loadingEvent.setPercentage(percentage);
                    bus.post(loadingEvent);

                }
                Log.i(LOG_TAG, "Finished inserting");
                //db.setTransactionSuccessful();
            } catch (Exception e) {
                Log.i(LOG_TAG, "Exception happened " + e.getMessage().toString());
                System.out.println("yo something happened, but I don't know what");
            } finally {
                Log.i(LOG_TAG, "--Closing transaction--");
                //db.endTransaction();

            }

            syncEvent.setIsSuccess(true);
            syncEvent.setStatus(200);
            bus.post(syncEvent);

        }

        @Override
        public void failure(RetrofitError error) {
            Log.i(LOG_TAG, "Rest call failed for this api");
            System.out.println("failtests");

        }

    });

    return START_STICKY;
}

Fragment Subscribed Method

@Subscribe
public void loadingResponse(final LoadingEvent loadingEvent) {
    Log.i(LOG_TAG, "Response from loading: " + loadingEvent.getPercentage());

    if(getActivity() == null)
        return;
    textTest.setText(loadingEvent.getPercentage().toString());
    getActivity().runOnUiThread(new Runnable() {
        @Override
        public void run() {
            Log.i(LOG_TAG, "Updating ui for loading text" + loadingEvent.getPercentage().toString());
            mCircularProgressBar.setProgress(loadingEvent.getPercentage());
            textTest.setText(loadingEvent.getPercentage().toString());
        }
    });

}

When I check my Logs, I see everything coming in fine, but the UI is not reflecting it. What am I missing here?

EDIT Forgot to mention. I'm using this library for my circle progress bar:

CircleProgressBar

EDIT

As of today, I still have yet to figure this out. I also noticed that my adapter is not being updated when the service posts the event. Previously, the context used to startService() was the getApplicationContext() from the LoginActivity. I thought this might have been a problem so I changed it to get the instance of the HomeActivity instead. I thought that firing the service from my HomeActivity would have solved the problem, but I'm still getting the same results unfortunately.


Solution

  • Okay so no one really tried to attempt answering my question but I figured it out.

    I actually skimped over the documentation part of the Service class and didn't know that it was executing on the Main Thread. To fix this, I had to run an AsyncTask to execute my operation in the background.

    The only thing I had to change in my codebase was to move the executing code from the onStartCommand method into an AsyncTask. The AsyncTask will be initiated onStartCommand and everything should be working fine.

    My code looks something like this now :

    Service

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        DownloadTask downloadTask = new DownloadTask();
        downloadTask.execute();
        return START_STICKY;
    }
    
    private class DownloadTask extends AsyncTask<Void, Void, LoginEvent> {
         @Override
         protected LoginEvent doInBackground(Void... params) {
              //Code here to run my operations
              //Call api, insert to db, post events etc...
              //
         }
    
         @Override
         protected void onPostExecute(LoginEvent event) {
              //run anything here you want to do after execution
         }
    }
    

    You can ignore my LoginEvent as this was something for my event bus to post events to any subscribers.

    Also, keep in mind that if you are going to change any views from this AsyncTask through the bus, make sure the subscriber uses the runOnUi to execute or else you'll hit a runtime exception since you're trying to change a view from something other than the MainThread.