Attempt to invoke virtual method on a null object reference for SharedPreferences in ActionbarActivity's Fragment

I'm_With_Stupid picture I'm_With_Stupid · Dec 23, 2014 · Viewed 27.7k times · Source

My app needs to access a shared preference file in the background. Ever since I started using the v21 support library's actionbaractivity to hold my fragment, my app force closes. It force closes whenever the fragment goes off screen, but the async task is still running and trying to access that sharedpreferences file. Why is it trowing this error and how do I fix it?

Here's the stack trace:

12-22 23:49:49.469: E/AndroidRuntime(23016): FATAL EXCEPTION: AsyncTask #4
12-22 23:49:49.469: E/AndroidRuntime(23016): Process: com.bernard.beaconportal.activities, PID: 23016
12-22 23:49:49.469: E/AndroidRuntime(23016): java.lang.RuntimeException: An error occured while executing doInBackground()
12-22 23:49:49.469: E/AndroidRuntime(23016):    at android.os.AsyncTask$3.done(AsyncTask.java:300)
12-22 23:49:49.469: E/AndroidRuntime(23016):    at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
12-22 23:49:49.469: E/AndroidRuntime(23016):    at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
12-22 23:49:49.469: E/AndroidRuntime(23016):    at java.util.concurrent.FutureTask.run(FutureTask.java:242)
12-22 23:49:49.469: E/AndroidRuntime(23016):    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
12-22 23:49:49.469: E/AndroidRuntime(23016):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
12-22 23:49:49.469: E/AndroidRuntime(23016):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
12-22 23:49:49.469: E/AndroidRuntime(23016):    at java.lang.Thread.run(Thread.java:818)
12-22 23:49:49.469: E/AndroidRuntime(23016): Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.SharedPreferences android.support.v4.app.FragmentActivity.getSharedPreferences(java.lang.String, int)' on a null object reference
12-22 23:49:49.469: E/AndroidRuntime(23016):    at com.bernard.beaconportal.activities.Due_Tommorow_Fragment$Update.doInBackground(Due_Tommorow_Fragment.java:815)
12-22 23:49:49.469: E/AndroidRuntime(23016):    at com.bernard.beaconportal.activities.Due_Tommorow_Fragment$Update.doInBackground(Due_Tommorow_Fragment.java:1)
12-22 23:49:49.469: E/AndroidRuntime(23016):    at android.os.AsyncTask$2.call(AsyncTask.java:288)
12-22 23:49:49.469: E/AndroidRuntime(23016):    at java.util.concurrent.FutureTask.run(FutureTask.java:237)
12-22 23:49:49.469: E/AndroidRuntime(23016):    ... 4 more

Here's the specific line of code where the error happens:

    SharedPreferences userName = getActivity().getSharedPreferences(
            "Login_Info", Context.MODE_PRIVATE);

Here's the async task where the error happens:

public class Update extends AsyncTask<String, Void, Void> {

        private final HttpClient Client = new DefaultHttpClient();

        @Override
        protected Void doInBackground(String... urls) {
            SharedPreferences bDay = getActivity().getSharedPreferences(
                    "Login_Info", Context.MODE_PRIVATE);

            String day1 = Integer.toString(bDay.getInt("Day", 0));

            String year1 = Integer.toString(bDay.getInt("Year", 0));

            String month1 = Integer.toString(1 + bDay.getInt("Month", 0));

            SharedPreferences userName = getActivity().getSharedPreferences(
                    "Login_Info", Context.MODE_PRIVATE);

            String day = day1.replaceFirst("^0+(?!$)", "");

            String month = month1.replaceFirst("^0+(?!$)", "");

            String year = year1.replaceFirst("^0+(?!$)", "");

            String birthday = month + "/" + day + "/" + year;

            System.out.println("Birthday = " + birthday);

            String user = userName.getString("username", "");

            // String user = (username).split("@")[0];

            System.out.println("Username = " + user);

            try {

                // HttpClient httpClient = new DefaultHttpClient();
                HttpContext localContext = new BasicHttpContext();
                // HttpGet httpGet = new HttpGet(
                // "http://www.beaconschool.org/~markovic/lincoln.php");

                HttpClient httpclient = new DefaultHttpClient();
                HttpPost httppost = new HttpPost(
                        "http://www.beaconschool.org/~markovic/lincoln.php");

                try {
                    // Add your data
                    List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(
                            2);
                    nameValuePairs
                            .add(new BasicNameValuePair("username", user));
                    nameValuePairs.add(new BasicNameValuePair("birthday",
                            birthday));
                    httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

                    // Execute HTTP Post Request
                    response = httpclient.execute(httppost);

                    Log.d("Http Response:", response.toString());

                } catch (ClientProtocolException e) {
                    // TODO Auto-generated catch block
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                }

                try {
                    Log.d("receiver", "animation stopped and downloaded file");

                    String homework = new Scanner(response.getEntity()
                            .getContent(), "UTF-8").useDelimiter("\\A").next();

                    // String homework =
                    // Html.fromHtml(duetommorow_html).toString();

                    SharedPreferences.Editor localEditor = getActivity()
                            .getSharedPreferences("homework",
                                    Context.MODE_PRIVATE).edit();

                    SimpleDateFormat dateFormat = new SimpleDateFormat(
                            "MM/dd hh:mm a");
                    Calendar cal = Calendar.getInstance();
                    String downloaded = dateFormat.format(cal.getTime());

                    localEditor.putString("homework_content", homework);

                    localEditor.putString("download_date", downloaded);

                    localEditor.apply();

                    localEditor.putString("homework_content", homework);

                    localEditor.apply();

                    Log.d("receiver", "information given to shared preferences");

                    due_tommorow_list.clear();

                    parse_due_tommorow_string();

                    parse_due_tommorow_content();

                } catch (IllegalStateException e) {

                    e.printStackTrace();
                } catch (IOException e) {

                    e.printStackTrace();
                } catch (NullPointerException e) {

                    due_tommorow_list.clear();

                    parse_due_tommorow_string();

                    parse_due_tommorow_content();

                    SharedPreferences.Editor localEditor = getActivity()
                            .getSharedPreferences("homework",
                                    Context.MODE_PRIVATE).edit();

                    localEditor.putString("download_error", "yes");

                    localEditor.apply();

                    e.printStackTrace();
                }

                catch (NoSuchElementException e) {

                    due_tommorow_list.clear();

                    parse_due_tommorow_string();

                    parse_due_tommorow_content();

                    SharedPreferences.Editor localEditor = getActivity()
                            .getSharedPreferences("homework",
                                    Context.MODE_PRIVATE).edit();

                    localEditor.putString("download_error", "yes");

                    localEditor.apply();

                    e.printStackTrace();
                }

                catch (RuntimeException e) {

                    due_tommorow_list.clear();

                    parse_due_tommorow_string();

                    parse_due_tommorow_content();

                    SharedPreferences.Editor localEditor = getActivity()
                            .getSharedPreferences("homework",
                                    Context.MODE_PRIVATE).edit();

                    localEditor.putString("download_error", "yes");

                    localEditor.apply();

                    e.printStackTrace();
                }

            } finally {

            }
            return null;

        }

        @Override
        protected void onPostExecute(Void result) {

            swipeLayout.setRefreshing(false);

            Log.d("sender", "Broadcasting message");

            Intent intent = new Intent("up_navigation");

            intent.putExtra("message", "This is my message!");
            LocalBroadcastManager.getInstance(getActivity()).sendBroadcast(
                    intent);

            Toast.makeText(getActivity(), "Refresh Finished", 4000).show();

            SharedPreferences download_error = getActivity()
                    .getSharedPreferences("homework", Context.MODE_PRIVATE);

            String error = download_error.getString("download_error", "no");

            String download_date = "Download error, refreshed homework using homework downloaded at "
                    + download_error.getString("download_date", "");

            if (error.equals("yes")) {

                SharedPreferences.Editor localEditor = getActivity()
                        .getSharedPreferences("homework", Context.MODE_PRIVATE)
                        .edit();

                Toast.makeText(getActivity(), download_date, Toast.LENGTH_LONG)
                        .show();

                localEditor.putString("download_error", "no");

                localEditor.commit();

            }

            adapter.notifyDataSetChanged();

            swipeLayout.setRefreshing(false);

        }

    }

Answer

Wesley picture Wesley · May 4, 2015

You do something time-consuming in an AsyncTask, when the getActivity() part is executed, the Activity has been destroyed. So the reference getActivity() return null, which is quite correct.

Which you should do is in your Thread or AsyncTask, you should always check if getActivity() is null, in case of the Activity which host your Fragment has been destroyed.

I don't think @I'm_With_Stupid 's answer is a good pratice, coz it's bad to hold an Activity reference in your Fragment and Fragment has already done that for you.