0

I have a MainActivity class that has a method called: updateTabTitles();

updateTabTitles() does what it sounds like, updates the titles of my tabs.

    String tabName = tabNames[tabNumber];
    String font = "helveticaneuebold.ttf"; // Fonts found in assets/fonts/ folder

    SpannableString title = new SpannableString(tabName);
    SpannableString subTitle;

    // This line gives me trouble
    title.setSpan(new TypefaceSpan(getBaseContext(), font), 0, title.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

I call this function from my ChecklistTab class that extends the Fragment class. The following method is in my ChecklistTab class:

 public int calculateRemaining(ArrayList<ChecklistItem> checklistItems, int tabNumber) {
    int remaining = 0;

    for (int i = 0; i < checklistItems.size(); i++) {
        if (!checklistItems.get(i).getCheckBox().isChecked() && checklistItems.get(i).getCheckBox().isEnabled() && !checklistItems.get(i).getCheckBox().getText().equals("N/A")) {
            remaining++;
        }
    }

    // NULL POINTER HERE
    ((MainActivity) getActivity()).updateTabTitles(tabNumber, remaining);

    return remaining;
}

Lastly, I found a custom TypefaceSpan class online for changing fonts. This is the constructor that is called from updateTabTitles()

public TypefaceSpan(Context context, String typefaceName) {
    mTypeface = sTypefaceCache.get(typefaceName);

    if (mTypeface == null) {
        mTypeface = Typeface.createFromAsset(context.getApplicationContext()
                .getAssets(), String.format("fonts/%s", typefaceName));

        // Cache the loaded Typeface
        sTypefaceCache.put(typefaceName, mTypeface);
    }
}

I really don't know much about contexts, but this code used to work with my old implementation. However, since refactoring, I can't seem to figure out what's wrong now.

Stacktrace:

java.lang.NullPointerException
            at com.brettrosen.atls.fragments.ChecklistTab.calculateRemaining(ChecklistTab.java:179)
            at com.brettrosen.atls.onclicklisteners.CheckboxOnClickListener.onClick(CheckboxOnClickListener.java:46)
            at android.view.View.performClick(View.java:4192)
            at android.widget.CompoundButton.performClick(CompoundButton.java:100)
            at android.view.View$PerformClick.run(View.java:17327)
            at android.os.Handler.handleCallback(Handler.java:725)
            at android.os.Handler.dispatchMessage(Handler.java:92)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:5019)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
            at dalvik.system.NativeStart.main(Native Method)
Brejuro
  • 3,421
  • 8
  • 34
  • 61
  • Please post your Java stack trace. Also, where are you calling `calculateRemaining()`? – CommonsWare Jan 28 '16 at 19:49
  • Why don't you use just "this" as a context instead of getBaseContext? – Sebastian Breit Jan 28 '16 at 19:50
  • @CommonsWare I posted my stacktrace. `calculateRemaining` is called from a number of different classes. Some of which are custom OnClickListener classes – Brejuro Jan 28 '16 at 19:52
  • `TypefaceSpan.java:22` is?? – Naman Jan 28 '16 at 19:53
  • @nullpointer In the block of code above, I wrote a comment above the line saying thats where the error is thrown – Brejuro Jan 28 '16 at 19:55
  • "I've tried using getApplicationContext(), this, MainActivity.this, none have worked" -- well, you will be getting different stack traces for the latter two. Your problem is that `getBaseContext()` is returning `null`, and it is not possible for `this` to be `null`. I never use `getBaseContext()`, and pretty much every use I have ever seen of it online is wrong. I suggest that you switch to `this`, and post the stack trace for that crash. – CommonsWare Jan 28 '16 at 19:59
  • http://stackoverflow.com/questions/10641144/difference-between-getcontext-getapplicationcontext-getbasecontext-and and http://stackoverflow.com/questions/1026973/whats-the-difference-between-the-various-methods-to-get-a-context should be a good read – Naman Jan 28 '16 at 20:07
  • @CommonsWare I updated the new stacktrace and commented where the null pointer is – Brejuro Jan 28 '16 at 20:19
  • Well, the only way that line can directly have a `NullPointerException` is if `getActivity()` is `null`. And the only way that would happen is if your app is seriously messed up, where you have a `CompoundButton`, that you think is managed by a fragment, still on the screen after the fragment has been detached from its original activity. – CommonsWare Jan 28 '16 at 20:34

3 Answers3

0

Can you try getApplicationContext instead of getBaseContext

title.setSpan(new TypefaceSpan(getApplicationContext(), font), 0, title.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
Claud
  • 1,065
  • 3
  • 26
  • 38
  • Thanks for the reply. I've tried using getApplicationContext(), this, MainActivity.this, none have worked. – Brejuro Jan 28 '16 at 19:51
0

Try using

title.setSpan(new TypefaceSpan(this, font), 0, title.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
Naman
  • 27,789
  • 26
  • 218
  • 353
  • Thanks for the reply. I've tried using getApplicationContext(), this, MainActivity.this, none have worked. – Brejuro Jan 28 '16 at 19:53
0

The stacktrace says PrearrivalPlan is your fragment since its onCreateView() is being invoked. But you're calling getActivity() in ChecklistTab which seems to be another fragment and it's not attached to any activity. getActivity() returns null and hence the different NPEs you are seeing.

You can pass in a Context as an argument to those methods that need one, and use getActivity() in fragments only between onAttach() and onDetach() lifecycle events in the fragment lifecycle.

laalto
  • 150,114
  • 66
  • 286
  • 303
  • I think that's exactly the problem, thanks for pinpointing that. How can I use context as a parameter to use this same line `((MainActivity) getActivity()).updateTabTitles(tabNumber, remaining);` I cant seem to call `context.getActivity()` – Brejuro Jan 28 '16 at 23:45