0

in my app, I display an ErrorFragment object with a RETRY button to re-check for internet if there is none. However, when the user has established internet connectivity, and clicked the RETRY button, the UI hangs for a couple seconds.

I know not to perform this task on the main thread, so I implemented the following:

public class MainFragment extends VerticalGridFragment
{
    ....

    if (isConnectedToInternet() == true)
    {
        // Load data
    }
    else
    {
        displayInternetError();
    }

    public void displayInternetError()
    {
        Log.d(TAG, "displayInternetError");

        final ErrorFragment error = new ErrorFragment();

        getFragmentManager().beginTransaction().replace(R.id.main_browse_fragment, error)
                .commit();

        error.setImageDrawable(getResources().getDrawable(R.drawable.lb_ic_sad_cloud, null));
        error.setMessage(getResources().getString(R.string.no_internet_message));
        error.setDefaultBackground(true);

        error.setButtonText(getResources().getString(R.string.retry_connection));

        error.setButtonClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View arg0)
            {
                if (isConnectedToInternet() == true)
                {
                    getFragmentManager().beginTransaction().remove(error).commit();
                    getFragmentManager().popBackStack();

                    Singleton.getInstance().setInternetErrorShown(false);
                    prepareBackgroundManager();
                    setupFragment();
                    setupEventListeners();
                }
                else
                {
                    Singleton.getInstance().setInternetErrorShown(true);
                }
            }
        });
    }

    ...

     private class GetInternetStatus extends AsyncTask<Void,Void,Boolean>
    {
        @Override
        protected Boolean doInBackground(Void... params)
        {
            return hasInternetAccess();
        }

        protected boolean hasInternetAccess()
        {
            try
            {
                URL url = new URL("http://www.google.com");

                HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
                urlc.setRequestProperty("User-Agent", "Android Application:1");
                urlc.setRequestProperty("Connection", "close");
                urlc.setConnectTimeout(1000 * 30);
                urlc.connect();

                // http://www.w3.org/Protocols/HTTP/HTRESP.html
                if (urlc.getResponseCode() == 200 || urlc.getResponseCode() > 400)
                {
                    // Requested site is available
                    return true;
                }
            }
            catch (Exception ex)
            {
                // Error while trying to connect
                ex.printStackTrace();
                return false;
            }
            return false;
        }
    }

    // Checking for all possible internet connections
    public  boolean isConnectedToInternet()
    {
        Boolean result = false;

        try
        {
            // Get the result after executing AsyncTask
            result = new GetInternetStatus().execute().get();
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        catch (ExecutionException e)
        {
            e.printStackTrace();
        }
        return result;
    }

    ....
}

But it still hangs and the UI is unresponsive. How can I resolve this issue?

Thanks

Pangu
  • 3,721
  • 11
  • 53
  • 120

1 Answers1

1

It hangs the UI because even though you are using an AsyncTask, you are starting it and then immediately trying to get the result of it.. Instead, use the AsyncTask's onPostExecute method to either load the data or call displayInternetError.

Buddy
  • 10,874
  • 5
  • 41
  • 58
  • Are you saying to invoke `hasInternetAccess` on `onPostExecute` instead of `doInBackground`? – Pangu Jul 27 '16 at 00:24
  • @Pangu No, I'm saying to make isConnectedToInternet a void method that just kicks off the AsyncTask. And then the AsyncTask will call the appropriate method itself from within onPostExecute. – Buddy Jul 27 '16 at 00:32
  • Of course, at that point it might be clearer to rename some of the methods: isConnectedToInternet -> checkIsConnectedToInternet, etc.. – Buddy Jul 27 '16 at 00:33
  • Sorry I'm trying to understand this conceptually. I make `isConnectedToInternet` a void, ok got it, then I kick off `AsyncTask` within `isConnectedToInternet`. Then within `GetInternetStatus `, I call `hasInternetAccess` within `onPostExecute` instead of `doInBackground`? – Pangu Jul 27 '16 at 01:03
  • You kick off the `AsyncTask` which does the slow internet check (as you have it now), but then from `AsyncTask`'s `onPostExecute` method you handle the result of the check and either load the data or call `displayInternetError`. Read the `AsyncTask` docs for more information: https://developer.android.com/reference/android/os/AsyncTask.html – Buddy Aug 01 '16 at 05:17