0

I created a sample to play around with an activity that contains a fragment with multiple progressbars that are filled by AsyncTasks that are executed by calling executeOnExecutor() on them. To support rotation, the fragment retains its instance.

The weird thing is that, when i rotate after some tasks are completed (and some progressbars are filled), these progressbars become empty. I shouldn't happen because i call setProgress on the progressbars (cellView.updateProgress) from the syncSetup method called from onCreateView().

In the onCreateView, there's some code to run the syncSetup method on the ui thread (in comments), when i do this everything works correctly

Why does it work correctly when doing that? in my knowledge, onCreateView is always called on the ui thread...

EDIT: It's not because the syncSetup is called on a non-ui thread. The code in comments works correctly because the runnable is posted directly in the messageQueue of the main thread. I still have no idea why this makes a difference

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    System.out.println("Call to Fragment onCreate");
    setRetainInstance(true);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.fragment_async, container, false);

    System.out.println("Call to Fragment onCreateView");
    System.out.println("Got "+tasks.size()+" tasks in list");
    System.out.println("Running? "+isRunning);

    list = (LinearLayout) v.findViewById(R.id.container);
    btnExeDefault = (Button) v.findViewById(R.id.buttonExecuteDefault);
    btnExeParallel  = (Button) v.findViewById(R.id.buttonExecuteParallel);
    btnCancel = (Button) v.findViewById(R.id.buttonCancel);

    btnExeDefault.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            execute(false);
        }
    });
    btnExeParallel.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            execute(true);
        }
    });
    btnCancel.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if(isRunning){
                isRunning = false;
                for(int i = 0; i < POOL; i++){
                    tasks.get(i).cancel(false);
                    cells.get(i).reset();
                }
                tasks.clear();
                allowExecution(true);
            }
        }
    });

    /*
    new Handler(Looper.getMainLooper()).post((new Runnable()
    {
        @Override
        public void run()
        {
            syncSetup();
        }
    }));
    */
    syncSetup();

    return v;
}

private void syncSetup(){
    cells = new ArrayList<>();
    for(int i = 0; i < POOL; i++){
        CellThread cellView = new CellThread(getContext());
        cellView.setNumber(i);
        list.addView(cellView, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        cells.add(cellView);
        if(tasks.size() > i) {
            BasicAsyncTask task = tasks.get(i);
            System.out.println("Manually set task #"+i+" to reflect "+task.getProgress()+"%");
            cellView.updateProgress(task.getProgress());
            tasks.get(i).setUpdateCallback(cellView);
        }
    }
    allowExecution(!isRunning);
}
DennisVA
  • 2,068
  • 1
  • 25
  • 35

1 Answers1

0

This is a known problem in Android. A handler is just a workaround for the bug

android progressBar does not update progress view/drawable

Community
  • 1
  • 1
DennisVA
  • 2,068
  • 1
  • 25
  • 35