Alex
Alex

Reputation: 108

Contexts and callbacks from asynchronous tasks

I've been experiencing this problem on some devices, especially Samsung.

I have an activity that has 7 fragments. In most of them, I start an async task for getting some data. I handle the exceptions by creating a handler in onCreateView().

 handler = new Handler(new Handler.Callback() {
            @Override
            public boolean handleMessage(Message msg) {
                if (msg.what == 0) {
                    Toast.makeText(getActivity().getApplicationContext(), getActivity().getResources().getString(R.string.connection_timed_out), Toast.LENGTH_SHORT).show();
                    return true;
                }
                return false;
            }
        });

When making the API call, in catch blocks, if exceptions occur, I cancel the async task and in the onCancelled() callback, I notify the handler.

new AsyncTask<Void, Void, ArrayList<UserProfile>>() {
            @Override
            protected ArrayList<UserProfile> doInBackground(Void... params) {
                try {
          return new APIService().GetUserProfiles(EnloopApplication.getCurrent().getAuthenticationToken(), thisUserProfile.getEnloop_friends());
            } catch (WampNetworkException e) {
                cancel(true);
                e.printStackTrace();
            } catch (WampApiException e) {
                e.printStackTrace();
            } catch (SocketTimeoutException e) {
                cancel(true);
            }
            return null;
        }

        @Override
        protected void onCancelled() {
            super.onCancelled();
            handler.sendEmptyMessage(0);
        }

On most devices, it works, but on Samsung devices sometimes I get null pointer exception since getActivity() returns nothing, as if the activity was destroyed and never got created again. Problem is the activity is not destroyed in code, since only thing that is happening is switching between fragments in same activity.

Upvotes: 1

Views: 79

Answers (1)

Dmitry Zaytsev
Dmitry Zaytsev

Reputation: 23982

getActivity() returning null is a perfectly valid scenario which you should expect as well.

This happens because by creating anonymous Handler in your onCreateView you're referencing Fragment which was already detached from Activity (therefore getActivity() returns null). Same goes for your AsyncTask - if you're creating it as an anonymous class inside Fragment then it also references same detached Fragment.

I would suggest you to revise your architecture. How? I believe, is that your UI components should not perform asynchronous operations by themselves. Instead, you should use any sort of publish/subscribe mechanism out there (there are solutions which are using LoaderManager, HandlerThread, RxJava, RoboSpice and other 3rd party libraries).

Upvotes: 1

Related Questions