2

i am creating asynchtask on thread pool on an listview . i am handling those task through an listarray of asynchtask . i have to remove those task when fragments get destroy and have to again assign those task when i make new fragment after destroying last one .

my code in listview adapter is

if(FragmentNowPlaying.task.isEmpty()){
        FragmentNowPlaying.task.add( new ProgressAsynchTask(holder.info,tvShows, position));
        FragmentNowPlaying.task.get(position).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
    }
    else if(position >= FragmentNowPlaying.task.size()){
        FragmentNowPlaying.task.add( new ProgressAsynchTask(holder.info,tvShows, position));
        FragmentNowPlaying.task.get(position).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);    
    }
    else if(position < FragmentNowPlaying.task.size()){

        if(FragmentNowPlaying.task.get(position).getStatus().RUNNING == null){
            FragmentNowPlaying.task.remove(position);
            FragmentNowPlaying.task.add( new ProgressAsynchTask(holder.info,tvShows, position));
            FragmentNowPlaying.task.get(position).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
        } else if(FragmentNowPlaying.task.get(position).getStatus().RUNNING != null){

            FragmentNowPlaying.task.get(position).cancel(true);
            FragmentNowPlaying.task.remove(position);
            FragmentNowPlaying.task.add( new ProgressAsynchTask(holder.info,tvShows, position));
            FragmentNowPlaying.task.get(FragmentNowPlaying.task.size()-1).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
        }
    }

problem is that i couldn't remove and cancel last asynchtask threads , this is causing rejectedExecuationException and do not allowing it to create new thread as thread pool size get reach. Please tell me how can i get over this issue ? so my progressbars run smoothly and save me from this error.

again reminding i have a fragment which have a listview.

Muhammad Adil
  • 4,358
  • 3
  • 32
  • 36

1 Answers1

4

In your case it's easy to get this exception. ThreadPoolExecutor

New tasks submitted in method execute(Runnable) will be rejected when the Executor has been shut down, and also when the Executor uses finite bounds for both maximum threads and work queue capacity, and is saturated.

Task rejection lead to generation of RejectedExecutionException. In your case maximum number of threads are achieved. Threads and task limitation depends on Android platform version for example for Android 4.0.1 MAXIMUM_POOL_SIZE = 128.

That is why even if you have logic like in your example it's easy to reach thread limitation with 128 items in your list, especially if it's long runnig tasks.

I don't think that updating progress bar in a list require separate thread per list item. From my point of view it's enough one Thread or AsyncTask to complete this job. There is not enough of code to do appropriate refactoring but simplest concept to do that as follow:

Handler uiHandler = new Handler(Looper.getMainLooper());

//Somewhere in your activity

Thread updateThread = new Thread(){
    @Override
    public void run() {
        while(!isInterrupted()){
            final Map<Integer, Integer> progressStates = getCurrentProgress();
            uiHandler.post(new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < adapter.getCount(); i++) {
                        int progress = progressStates.get(i);
                        adapter.getItem(i).setProgress();//It's not default method you need to implement it in your item
                    }
                    adapter.notifyDataSetChanged();
                }
            });
            try {
                sleep(1000); //Schedule next update in 1 second
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private Map getCurrentProgress(){
        //do long running operation here
        ...
        return progresStates;
    }
}.start();

//Don't forget stop this thread if user gone from screen. For example in your activity
public void onDestroy(){
    updateThread.interrupt();
}

If you actually has special thread (for example player thread) where progress is calculated, there is no need to start new one, just do progress update from this thread.

Roman Nazarevych
  • 7,513
  • 4
  • 62
  • 67
Nikolay Nikiforchuk
  • 1,998
  • 24
  • 20
  • i want contiguous updates until it gets upto maxvalue ok i will manage this some how. and one thing more i want to ask how can i get this progressbar ?? actually i am trying but do not have any help . – Muhammad Adil Aug 22 '14 at 13:43
  • ok i just replaced the line adapter.getItem(i).setProgress(); with **((ProgressBar)(((ViewGroup) mImageGrid.getItemAtPosition(i)).getChildAt(3))).setProgress(progress);** – Muhammad Adil Aug 22 '14 at 13:54
  • plz check it again . i have posted an answer . – Muhammad Adil Aug 22 '14 at 14:56