App Crashes on AsyncTask Screen Rotation

前端 未结 2 1850
无人及你
无人及你 2021-01-17 04:22

I\'m using AsyncTask in one of the fragments of an activity.

The AsyncTask is working perfectly but on screen rotation, it loses the reference to activity

相关标签:
2条回答
  • 2021-01-17 04:45

    Try this way

    <activity
        android:name=".ActivityName"
        android:configChanges="orientation|screenSize|keyboardHidden"/>
    
    0 讨论(0)
  • 2021-01-17 04:50

    There are plenty of solutions to this. One simple one for you is to use what's known as a "Retain" fragment. This is an approach that is used in some of the Google samples. A retain fragment has no UI, and persists across orientation change. This is usually defined as a static inner class of your activity like so:

    public static class RetainFragment extends Fragment {
        private static final String TAG = "RetainFragment";
    
        public RetainFragment() {}
    
        public static RetainFragment findOrCreateRetainFragment(FragmentManager fm) {
            RetainFragment fragment = (RetainFragment) fm.findFragmentByTag(TAG);
            if (fragment == null) {
                fragment = new RetainFragment();
            }
            return fragment;
        }
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setRetainInstance(true);
        }
    }
    

    Then, put your AsyncTask inside of your RetainFragment. When onPostExecute is called, you can simply use the fragment's getActivity() method to get the Activity that it is attached to.

    Hope that helps, let me know if there is still some confusion!

    Edit: Here is a Google sample of a retain fragment

    Edit 2: (as per comments)

    public class A {
    
        // This class holds a reference to it's outer A instance. It can be
        // accessed using A.this.
        public class innerClassA {
            //...
        }
    
        // This class does not hold a reference to it's outer A instance.
        public static class innerClassB {
            //...
        }
    }
    

    Edit 3: In the comments, I ended up writing the full code anyway. For anyone interested:

    public class MyActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_my);
    
            Button b = (Button) findViewById(R.id.aaa);
            b.setOnClickListener(new View.OnClickListener() {
                @Override public void onClick(View v) {
                    RetainFragment retainFragment =
                            RetainFragment.findOrCreateRetainFragment(getFragmentManager());
                    retainFragment.loadAsync();
                }
            });
        }
    
        private void handleResponse(String response) {
            // do something with the response...
        }
    
        public static class RetainFragment extends Fragment {
            private static final String TAG = "RetainFragment";
    
            public RetainFragment() {
            }
    
            public static RetainFragment findOrCreateRetainFragment(FragmentManager fm) {
                RetainFragment fragment = (RetainFragment) fm.findFragmentByTag(TAG);
                if (fragment == null) {
                    fragment = new RetainFragment();
                    fm.beginTransaction().add(fragment, TAG).commit();
                }
                return fragment;
            }
    
            @Override
            public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setRetainInstance(true);
            }
    
            private void loadAsync() {
                new AsyncTask<Void, Void, String>() {
                    @Override protected String doInBackground(Void... params) {
                        // Do some work...
                        return null;
                    }
    
                    @Override protected void onPostExecute(String response) {
                        MyActivity myActivity = (MyActivity)getActivity();
                        if (myActivity != null) {
                            myActivity.handleResponse(response);
                        }
                    }
                }.execute();
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题