11

In my android App, I use multiple AsyncTask using THREAD_POOL_EXECUTOR which makes the tasks run in parallel. Sometime the app hangs. Below is the code I use.

  1. Could you please let me know how to fine tune so as to avoid any hanging issue ?
  2. How to find the point in which app is hanging ?

    new fetchInitialCoinsParallel().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, url);
    
    prefCoinList = getPrefCoin();
    if(prefCoinList.size()>0){
        for(int i=0;i<prefCoinList.size();i++){
            new fetchAltCoinsParallel().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, url);
        }
    }
    
    public class fetchAltCoinsParallel extends AsyncTask<String, String, String> {
    @Override
    protected void onPreExecute() {
    }
    
    protected String doInBackground(String... params) {
        try {
            InputStream is = getDataFromURL(params[0]);
            if(is!=null){
                BufferedReader br = new BufferedReader(new InputStreamReader(is));
                synchronized(this){
                    brList.add(br);
                }
    
            }else{
                prefCoinNotLoadedTimeOutCount=prefCoinNotLoadedTimeOutCount+1;
            }
    
    
            if(brList.size()==prefCoinList.size()-prefCoinNotLoadedTimeOutCount){
                try {
                    loadAltCoins(getAltCoinDataParallel());
                } catch (IOException e) {
                    e.printStackTrace();
                }
    
                maingame.dataReady=true;
            }
    
        } catch (IOException e) {
            e.printStackTrace();
        } 
        return null;
    }
    
    protected void onPostExecute(String params) {
    }
    protected void onProgressUpdate(String... progress) {
    }
    

    }

Thread details enter image description here

Ismail Iqbal
  • 2,774
  • 1
  • 25
  • 46
iappmaker
  • 2,945
  • 9
  • 35
  • 76
  • You should post more code. – Okas Jan 21 '18 at 11:16
  • Are implementaions of brList or prefCoinList threadsafe? You're not guaranteed to see the changes otherwise - also you're using AsyncTask instance as monitor (**synchronized(this)**) are you sure you use AsynctTask as monitor in other part of the code? Is your dataReady flag **volatile**? – Boris Treukhov Jan 21 '18 at 11:18
  • Also I would return and assign the whole list instance with the coins instead of inserting elements from another thread and checking the number – Boris Treukhov Jan 21 '18 at 11:28
  • I am fine with data in brList or prefCoinList . Only thing the app is hanging for some reason. – iappmaker Jan 21 '18 at 12:36
  • @Okas The give code is the place where I call using THREAD_POOL_EXECUTOR. and the code is hanging only when executing around 40 calls in parallel – iappmaker Jan 21 '18 at 12:37
  • what maximum value you will get in getPrefCoin();?? – Dhruv Patel Jan 23 '18 at 05:43
  • 40 coins is the max – iappmaker Jan 23 '18 at 16:51
  • Please look below link: http://blogs.innovationm.com/multiple-asynctask-in-android/ And http://codetheory.in/android-java-executor-framework/ – Patrick R Jan 24 '18 at 13:58
  • @iappmaker i have a very heavy processing app in playstore(so i have to keep the balance), the basic is simple if you run too much in threads/asynctasks your app will hang, my suggestion is to use "setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); or setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND+2);" or LOWEST with only 1 task at a time(using THREAD_POOL_EXECUTOR or any other technique), also don't frequently send updates to ui thread. Also note that reading buffer is slow for some devices even with good processors. – Diljeet Jan 27 '18 at 09:42
  • @iappmaker one more thing please post code -> how you are executing these tasks, also try to log output whether more than 1 task is running simultaneously or not, if you are running new thread in loadAltCoins(getAltCoinDataParallel()); than their is a huge chance that your app may run many threads at once. Also i will suggest to not open input streams until you start reading them (opening streams hangs my app too) – Diljeet Jan 27 '18 at 09:53

2 Answers2

1

Check the AsyncTaskLoader concept. This feature is supported by Android community introduced in API level 11 along with Honeycomb features.

AsyncTaskLoader solved the lot of limitations & workaround solutions of the AsyncTask.java

Official : https://developer.android.com/reference/android/content/AsyncTaskLoader.html

Good Sample: https://medium.com/google-developers/making-loading-data-on-android-lifecycle-aware-897e12760832

public class JsonAsyncTaskLoader extends AsyncTaskLoader<List<String>> {
    // You probably have something more complicated
    // than just a String. Roll with me
    private List<String> mData;

    public JsonAsyncTaskLoader(Context context) {
        super(context);
    }

    @Override
    protected void onStartLoading() {
        if (mData != null) {
            // Use cached data
            deliverResult(mData);
        } else {
            // We have no data, so kick off loading it
            forceLoad();
        }
    }

    @Override
    public List<String> loadInBackground() {
        // This is on a background thread
        // Good to know: the Context returned by getContext()
        // is the application context
        File jsonFile = new File(
                getContext().getFilesDir(), "downloaded.json");
        List<String> data = new ArrayList<>();
        // Parse the JSON using the library of your choice
        // Check isLoadInBackgroundCanceled() to cancel out early
        return data;
    }

    @Override
    public void deliverResult(List<String> data) {
        // We’ll save the data for later retrieval
        mData = data;
        // We can do any pre-processing we want here
        // Just remember this is on the UI thread so nothing lengthy!
        super.deliverResult(data);
    }
}
Gautam Chibde
  • 1,167
  • 3
  • 14
  • 27
Takermania
  • 1,345
  • 2
  • 12
  • 20
  • Well I will try this. Will this solve the Hanging issue ? – iappmaker Jan 21 '18 at 04:43
  • 2
    I wouldn't mess with Android loaders at all - they were invented on early stages of Android - what benefits do they provide except for unpredictable code with a lot of boiler plate and static classes - it's long since rxjava has been invented - https://stackoverflow.com/questions/20762514/why-are-loaders-bad-in-android – Boris Treukhov Jan 21 '18 at 11:25
  • 2
    TLDR I would pass a retained fragment code in review, but not the loaders in 2018. They were a confabulation many developers invested their into - even the author of the blog you reference added a note that **if you’re looking for a modern, flexible solution to this problem that doesn’t rely on Loaders (the chosen solution here), check out the Lifecycle Aware Data Loading with Architecture Components blog post.** – Boris Treukhov Jan 21 '18 at 11:31
  • 1
    AsyncTaskLoader? Just use a retained fragment, OR LiveData + ViewModel (where VM actually creates the retained fragment for you) – EpicPandaForce Jan 21 '18 at 13:13
  • @iappmaker Yes. This helps to resolve the issue.. Please let me know if any challenges by using AsyncTaskLoader. – Takermania Jan 23 '18 at 09:08
1

Instead of using Async Tasks, i recommend using RXJAVA for this purpose.

Here is the disadvantage given for Async Task: https://stackoverflow.com/a/9654445/9100553

Using RxJava will solve this problem, here is an perfect blog which can solve your problem of Multi Threading using RxJava.

http://www.nurkiewicz.com/2017/09/idiomatic-concurrency-flatmap-vs.html

(Read the second half) Both flatmap and parallel operators would be useful in your case.

  • 1
    Without understanding the problem you'd only get a mess in RxJava instead of a mess in AsyncTask. This should be a comment or a suggestion at the end of your answer. The core of the answer should focus on the described issue without trying to introduce more complexity (yes, RxJava is hard to pick up). – Eugen Pechanec Jan 28 '18 at 10:06
  • I think so, i have mentioned the solution in the form of 2 blogs with respect to this problem. Instead of using async task if you can use rx then above solution will help you... Simple. – fi - Anand Dubey Feb 25 '18 at 13:13