7

I'm still new to Android programming, so this question is rather basic. I see lots of code samples on the Internet where UI components, like a TextView, are being initialised and accessed in the onCreate() method of an Activity.

When I use Android Studio to create a new project - FirstApp - with default settings, a blank Activity called MainActivity bringing along with it activity_main and fragment_main, I can immediately compile this into an APK, deploy it on my device, and I get a screen with a header "FirstApp" and a TextView in the top left showing "Hello world!".

If I give the TextView an ID of textview1, and create a member variable, TextView myTextView;, then I can reference it in the onCreate() method of the Activity, like so (no compiler errors, of course):

    @Override
    protected void onCreate (Bundle savedInstanceState)
    {
        super.onCreate (savedInstanceState);
        setContentView (R.layout.activity_main);
        myTextView = (TextView) findViewById (R.id.textview1);
        myTextView.setText ("Hello tablet!");

        if (savedInstanceState == null)
        {
            getSupportFragmentManager().beginTransaction().add (R.id.container,new PlaceholderFragment()).commit();
        }
    }

However, if I compile and run the APK it results in an "Unfortunately, FirstApp has stopped." message.

I have previously got around this issue by moving startup code that accesses UI components into the onStart() method of the Activity, like so:

    @Override
    protected void onStart()
    {
        super.onStart();
        myTextView = (TextView) findViewById (R.id.textview1);
        myTextView.setText ("Hello tablet!");
    }

Which would result in a working APK with a single TextView in the top left showing "Hello tablet!" - my simple questions are two-fold...

  1. If the project uses Fragments then should I fully expect that the UI components cannot be accessed in the onCreate() method of the Activity, as I see happening with lots of sample code on the Internet, probably because they've not been created yet?
  2. Is it acceptable for me to be accessing UI components within the onStart() method of the Activity (which does work) - or should I be doing something else? Previously I have also used the onCreateView method of the Fragment, but is the best place to access UI components inside a Fragment actually in the onCreate() method of the Fragment, which I have not yet tried?

I also note that the onCreate() method of the default Fragment Android Studio creates for you when you create a new project does not have a stub provided... but onCreateView does, and the lifecycle documentation implies (to me, anyway) that this might be the best place to be doing things like this.

Any guidance on this is appreciated.

Hippogriff
  • 295
  • 1
  • 4
  • 18
  • When it crashed, get the Logcat Stacktrace so we can see where the error lies. Also is `myTextView` being setup somewhere else ie `TextView myTextView;`? – TMH Feb 14 '14 at 11:30
  • You should read about fragments in general. 1. The fragment's view is not yet available there(it's not a simple view that you add to the layout) 2. You can access the views from what callback you want(`onCreate()` is generally preferred). The problem is that you try to access the fragment's view which you should avoid and instead let the fragment handle this on its own. – user Feb 14 '14 at 11:32
  • @Tom Hart - yes, `TextView myTextView;` is included as a member variable. Is your response implying that you think this UI component *should* be perfectly accessible in the `onCreate()` method of the Activity itself? – Hippogriff Feb 14 '14 at 11:39

2 Answers2

7

The fragment transaction commit command only puts the transaction in Que - the transaction will be processed some time in the future. This is why you couldnt use it straight from on create.

I suggest you to use fragments to encapsulate their Ui behavior - I wouldn't change a fragment's Ui elements explicitly from the activity.

OnCreateView inside a fragment is a good place to init the fragment's Ui elements since it is called when the fragment view is created.

Working with fragments is quite tricky and painful at start but From my experiance they do help to create a much more modular code.

I suggest you read more about fragments in the docs before starting a serious project with them. http://developer.android.com/guide/components/fragments.html

chipopo
  • 326
  • 2
  • 9
  • Thank you... yes, accessing UI components in a Fragment during the `onCreateView` method **does** work fine, as long as I use `rootView.findViewById` - I have discovered that I do not understand how I would even try and access a UI component in the `onCreate` method of a Fragment, because I don't seem to have access to a `container`, something which is obviously passed down to `onCreateView` and is readily available for the `inflate` method. – Hippogriff Feb 14 '14 at 11:50
  • P.S. - is it OK if I just add that I'm not *exactly* choosing to use Fragments per se, I have chosen to use Android Studio and it seems that Android Studio wants to try and *enforce* (encourage) the use of Fragments, by providing one when you create a new project. This is no bad thing... I just need to get my head around things properly, as a lot of code samples that you see on the Internet seem to not use Fragments, therefore I was running into issues with simple things. Thanks! – Hippogriff Feb 14 '14 at 11:52
  • The new release of Android Studio now allows you to create a new project *without* a default Fragment and, for the apps I am creating, this appears to be a good thing for me, so it makes things a bit simpler. – Hippogriff Mar 09 '14 at 14:21
0

@chipopo is right in the diagnostics and in the encapsulation recommendations.

But in case you need you can call FarmentManager.executePendingTransactions() after commiting the transaction. This ensures that the operations on fragments queue are execute synchronously. I used that sometimes in non UI retainedInstance fragments.

lujop
  • 13,504
  • 9
  • 62
  • 95