The following code does not work, and throws a RuntimeException caused by NullPointerException
public class ListFilteredActivity extends Activity {
LinearLayout typeSelector = new LinearLayout(this) ;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ScrollView sv = new ScrollView(this);
this.setContentView(sv);
//this.typeSelector = new LinearLayout(this);
this.typeSelector.setOrientation(LinearLayout.VERTICAL);
sv.addView(this.typeSelector);
}
When I moved the initialization of this.typeSelection inside onCreate() it works great.
#Override
public void onCreate(Bundle savedInstanceState) {
...
this.typeSelector = new LinearLayout(this);
...
}
Why is the null pointer error? The inline declaration in the first piece of code happens as soon as constructor is called, and then the onCreate() has access to the object, isn't it?
LinearLayout requires you pass in a Context. This is an Android lifecycle object and not a Java object. When declaring and initializing the field directly, this will be initialized using the Java default constructor. However you'll only get a context once the onCreate lifecycle method occurs, which is much, much later and part of Android, not Java. So when you call the LinearLayout constructor with this, Android is expecting a reference to a Context, which you only get after the call to onCreate.
Related
I need to execute a method before initiating the layout in an activity. If I call the method I need to execute inside onCreate(), would it be executed before the layout is set?
The reason is because I need the method to return a piece of information that is displayed in the layout before initiating it. Would love some feedback on this.
You can do whatever you like before setContentView like so:
public class TestActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int i = 0;
setContentView(R.layout.main);
}
}
As long as you do not interact with views that have not been inflated yet
For example this is an error:
public class TestActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ERROR, CAN'T TOUCH UI ELEMENTS
ImageView img = (ImageView)findViewById(R.id.img);
setContentView(R.layout.main);
}
}
Default activity created with Android Studio contains following code
#Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Here is code, that executed before layout inflated
setContentView(R.layout.example_activity); //This line inflates layout
}
BTW, you can even remove setContentView and inflate layout programmaticaly.
Do it in onCreate(), preferably before calling setContentView().
However, if the data you want to receive comes from the network, then it will be obtained on a separate Thread (as no network calls can be done on the main Thread). In this situation the layout will almost certainly display before the data is obtained.
A solution would be to obtain the piece of data before you start the Activity, pass it in the Intent as extra and then retrieve in onCreate() using getIntent().getStringExtra()
You are probably inflating your layout in Activity.onCreate() with setContentView(), so you need to put your function call in that method before the call to setContentView().
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
yourFunctionCallHere();
setContentView(R.layout.act_main);
}
I was trying out coding android layout on Java. Then, I noticed that following code is incorrect (as in not working):
public class MainActivity extends Activity {
LinearLayout topLayout = new LinearLayout(this);
Button button1 = new Button(this);
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
... setText, layoutParam and etc ...
topLayout.addView(button1, layoutParam);
setContentView(topLayout);
}
}
while following code is correct (working):
public class MainActivity extends Activity {
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
LinearLayout topLayout = new LinearLayout(this);
Button button = new Button(this);
... setText, layoutParm and etc ...
topLayout.addView(button1, layoutParam);
setContentView(topLayout);
}
}
Why is that?
The context of an Activity is created once onCreate() is called.
In the first case, you don't have context set.
The comment made by #Blundell explains it, but if you want to go a little bit deeper, you need to understand the object lifecycle and order of things.
An Activity is a Java Object in the end. And so it must go through the Java Object creation process.
public class MainActivity extends Activity {
LinearLayout topLayout = new LinearLayout(this);
Button button1 = new Button(this);
Member variables (or Fields) are created right after the constructor. If you don't have a constructor, one is created for you (even tho you don't see it) you can try to create one:
public class MainActivity extends Activity {
public MainActivity() {
super();
Log.d("MAINACTIVITY", "Constructor!");
}
Now add log to your onCreate()…
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
Log.d("MAINACTIVITY", "onCreate!");
}
Start your Activity and look at the log.
You should see:
Constructor!
onCreate!
With that being said, Since an Activity implements a Context interface, you cannot use them until they are not constructed, something that can be considered done after the constructor is called and ends.
Field members which are initialized inline, must be initialized during object Construction too, because that's the idea of their initialization being there…
So in short, you're trying to initialize Field Members that require something (a context) that is not yet available because it hasn't been created (this).
;)
I created a new class in android that creates LinearLayouts when instantiated. However I can't figure out the context to put in the brackets of: new LinearLayout(context). Can someone shed some light? (I've already tried reading everything i can on contexts)
I'm assuming I don't need to extend Activity in my class
public class NewLayouts {
...
newParentLayout = new LinearLayout(getApplicationContext()); //<--eclipse warns of error here saying not a valid context
newParentLayout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT));
newParentLayout.setOrientation(LinearLayout.VERTICAL);
TextView monthDisplay = new TextView(getApplicationContext()); //<--eclipse warns of error here saying not a valid context
...
}
My main activity:
public class MainActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
NewLayouts Sample = new NewLayouts(1,2); //variables required in my constructor for new Layouts
setContentView(Sample.newParentLayout);
}
Change the constructor of NewLayouts to be something like...
public NewLayouts(Context ctx, int X, int Y) {...}
...then use ctx as the Context in NewLayouts for creating the Views.
In the Activity then do the following...
NewLayouts Sample = new NewLayouts(this, 1, 2);
That will pass the Activity's own Context into NewLayouts constructor.
try new LinearLayout(this) or new LinearLayout(newLayouts.this)
I want to create layout programmatically in different class which is not an activity so i will call one function from Activity and all code for creating layout is in function. so please give me some idea to write code.
this is my Activity:
public class Main extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TableLayout tl = (TableLayout) findViewById(R.id.table1);
testing t1 = new testing();
Main m = new Main();
t1.makelayout(tl,m);
}
}
And this is my class which has function that is generating layout programmatically:
public class testing {
public void makelayout(TableLayout tl,Main m1) {
// TODO Auto-generated method stub
//Main m = new Main();
TextView tv= new TextView(m1);
tv.setText("hello1");
tl.addView(tv);
}
}
can i do this or not please help me.
If your makelayout(TableLayout tl,Main m1) would be makelayout(Context c, TableLayout tl) and you call it by giving the Activity's context, then it would work.
For such "external" things, you always need to give over the appropriate context to allow creating the Views in it.
Another Java/Android newbie...
My Activity contains a delcaration for a variable of a class that I've defined...
public Teams theTeams = null;
Within the onCreate method of this Activity, I create an object of that class...
Teams theTeams = new Teams();
I've been able to make some changes to this object...
theTeams.setName("A", "Jets");
... which assigns "Jets" to a string in the class.
However, from within a private method of the Activity, attempts to refer to "theTeams" give me a null pointer error. I guess there's something about object visibility that I'm not understanding. Can someone clarify?
You declared first public Teams theTeams = null;
Then in the onCreate method, you have this
Teams theTeams = new Teams();
So you are initializing a new theTeams object of type Team inside the onCreate, which you can see only in the scope of onCreate.
So when you call a method on theTeams in your private method, the method is called in the object you have declared first outside the onCreate (which is still null)
So inside, your onCreate, you have to use:
theTeams = new Teams();
Something like the following should work (untested):
private Teams theTeams = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
theTeams = new Teams();
}
private void myMethod() {
theTeams.getName();
}