1

Basically I am starting to port a purely Activities application to Fragments and I am stuck nearly at the first step.

In my current application I extend application to have access to global constant and variables used to customize the application.

public class MyApplication extends Application {
    private final int nbreLivres = 50;
    private final String[] nomsLivres = new String[nbreLivres];

    private final int colorCount = 25;
    private final int[] customColors = new int[colorCount];

    private SparseIntArray hmColors = new SparseIntArray();

    private int mCustomFontSize = 14;

    private static MyApplication instance;

    ...
    ... 

    public int getColorCount() {
        return colorCount;
    }

    public int getColorFromIndex(int index) {
        return customColors[index];
    }

    ...
    ...
    ...
}

Accessing this from activities I do something like

((MyApplication) this.getApplication()).getColorCount();

and if I need to access it with an instance I do

private MyApplication mApp = MyApplication.getMyApplication();
mApp.getColorCount();

Question :

When doing these in a Fragment, for example to set the values of a list (ListFragment) to list all the colors available in my app I do

((MyApplication) getActivity().getApplication()).getColorsList();

and I tried also

MyApplication.getMyApplication().getColorsList();

both just crash at that line with a "null pointer" exception.

What have I not understand or what am I doing wrong ?

EDIT

Sorry I forget to mention it is based on the master/detail example given in Eclipse, where I try to populate the master list with my own data.

Here it is (I did not copy/paste all the useless stuff).

public class LivreListFragment extends ListFragment {

    ...
    ...

    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setListAdapter(new ArrayAdapter<String>(getActivity(),
            android.R.layout.simple_list_item_activated_1,
            android.R.id.text1, ((MyApplication) getActivity().getApplication()).getColorsList() ));
    }
}

ANSWER

Finally I simply found that I had forgotten to define my application name in my manifest file !

Now my code works as is.

However according to the answer of @CharlieCollins, I must put it in the onActivityCreated and not in the onCreate (unsafe).

Thx for your help, learning that onActivityCreated thing was important.

HpTerm
  • 8,151
  • 12
  • 51
  • 67
  • Well you say that it crashes with a NPE, so it might be helpful to see your fragment code (which actually crashes the application) ;-) – avalancha Jun 10 '13 at 14:41

2 Answers2

6

Ok so here is what I did:

Custom application

public class MyApplication extends Application {

    public int getColorCount() {
        return 1;
    }
}

Custom activity

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        getFragmentManager().beginTransaction().add(R.id.container, new TestFragment()).commit();
    }
}

Custom fragment

public class TestFragment extends Fragment {

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        int test = ((MyApplication) getActivity().getApplication()).getColorCount();
        Log.d("testfrag", "" + test);
    }
}

And it prints out "1" just as expected.
Now I don't know if you can just code alongside this example and find the problem in your code on your own, that would be great of course. If not then I guess what we need here is progressively more details out of your app, your fragment implementation, Log output etc.

Remark

The above implementation is outlined to retrieve the hosting activity upon it being fully created. This might differ from application to application:

  • If you simply want to access your activity as an Object use the onAttach callback
  • If you want to access a fully created activity use the onActivityCreated callback

These are two different use cases and you should always be aware of what you need

Community
  • 1
  • 1
avalancha
  • 1,457
  • 1
  • 22
  • 41
  • Thank you for your answer. I started on this basis to debug and it helped me. However according to Charlie Collins it is "unsafe" to call it in the onCreate. – HpTerm Jun 11 '13 at 08:48
  • Absolutely correct, I simply wanted to line my version as close to yours as possible while still fully functional. See [here](http://developer.android.com/guide/components/fragments.html#Creating) for more knowledge on the lifecycle of a fragment. Then you can make an educated decision on your own :) If you need any more help let me know, if not I would appreciate an accept. Regards – avalancha Jun 11 '13 at 09:43
  • 1
    @avalancha even though your answer works, it is unsafe. I understand you wanted to answer close to my question but I am wrong doing it in onCreate. For futur readers, edit your answer to have onActivityCreated instead of onCreate and then I will accept the answer as a "correct" one. By the way thank you for your help. – HpTerm Jun 12 '13 at 05:50
1

Android: Fragment cannot get activity

Basically you are likely trying to access Activity at the wrong point in the Fragment lifecycle. Make sure you only try to access Activity during or after onActivityCreated. (And I say likely because without code it's impossible to tell. If that's not the issue please show more of the Fragment code.)

Community
  • 1
  • 1
Charlie Collins
  • 8,806
  • 4
  • 32
  • 41
  • this is probably the correct answer but it has a tiny flaw: you should always access the activity in the `onAttach` callback! This is recommended by android and used in various recommended patterns (Fragment callbacks to host activity for example). `onAttach` is **guaranteed** to be the first call and has the activity as parameter – avalancha Jun 10 '13 at 14:45
  • The difference with onAttach and onActivityCreated is that onActivityCreated is, by design and definition, the first method in the frag lifecycle invoked AFTER the act has finished onCreate. You should NOT use onAttach for stuff where you need the act to have been created. (The example pattern you mention for callbacks is different, that is not tied to the lifecycle of the act.) See docs: http://developer.android.com/guide/components/fragments.html#CoordinatingWithActivity – Charlie Collins Jun 10 '13 at 15:07
  • @HpTerm, your edited question confirms my answer. You're trying to call "getActivity" inside of "onCreate." You can't do that safely. See the answer already here, and the linked docs. – Charlie Collins Jun 10 '13 at 20:28
  • @CharlieCollins, first of all thanks for your answer. I have carefully read your answer and read some of the documentation in the light of your answer. Correct me if I am wrong. The problem is that I try to access the activity in which the fragment is, before the activity is created. So I tried to put my setListAdapter in an override of onActivityCreated. But it is still crashing with NPE. I am investigating why. Another point is that, with what you say, why the example of avalancha is working ? Shouldn't he put the code in onActivityCreated ? – HpTerm Jun 11 '13 at 06:45
  • Ok I have my code up and running. I am so dumb. I simply forget to define my application name in the manifest file ! Now I tried both to put my code in onCreate and in onActivityCreated. Both appears to work. But you advise me to put it in onActivityCreated right ? – HpTerm Jun 11 '13 at 08:53
  • as seen in my dialog with Charlie: if you simply need the activity put it in onAttach(), if you need the fully created activity put it in onActivityCreated. These are two different things for two different needs, evaluate judiciously! – avalancha Jun 11 '13 at 09:46
  • In order to do what you're doing, that is get the activity for a reference to the application, use onActivityCreated. – Charlie Collins Jun 11 '13 at 15:13
  • @CharlieCollins Ok great, I learned something really important. So now, if avalancha edit his answer to have onActivityCreated instead of onCreate I will validate him as the "answer", orelse it will be you. I think the main point is that onActivityCreated thing and that's you who pointed it out. Thanks for your help. – HpTerm Jun 12 '13 at 05:52