created new class in android but can't figure out context - android

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)

Related

Android layout coding on Java: declaration location

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).
;)

Android app crashes when defining and setting element properties

My app is crashing. What am I doing wrong?
I am using an AsyncTask in a class fetchsSchools.
public class fetchSchools extends AsyncTask<Void, Void, ArrayList<String>>{
#Override
protected ArrayList<String> doInBackground(Void... arg0) {
ArrayList<School> schools = new ArrayList<School>();
ArrayList<String> schoolNames = new ArrayList<String>();
... code omitted for conciseness...
return schoolNames;
}
In this class I have an onPost Execute, my code gets to this, if I remark out the cls2 lines my app runs:
public void onPostExecute(ArrayList<String> schoolNames) {
MainActivity cls2=new MainActivity();
cls2.updateSpinner(schoolNames);
cls2.switchScreens();
}
The above fires off these two outines back in MainActivity which crash the app:
public void updateSpinner(ArrayList<String> schoolNames) {
Spinner schoolSpinner = (Spinner)findViewById(R.id.school_spinner);
schoolSpinner.setAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_dropdown_item, schoolNames));
}
public void switchScreens() {
ProgressBar progressBar1 = (ProgressBar)findViewById(R.id.progressBar1);
progressBar1.setVisibility(View.GONE);
TextView loading_label = (TextView)findViewById(R.id.loading_label);
loading_label.setVisibility(View.GONE);
}
Eclipse isn't showing any coding errors. Am I creating and acting on these variables correctly?
Though you have not given code for MainActivity and logcat. Seeing your code looks like MainActivity extends Activity. If so you cannot call
MainActivity cls2=new MainActivity();
MainActivity has to be initialized by android framework with appropriate context. Calling constructor yourself will not call any lifecycle methods of the Activity.
So all subsequent calls that use Context will fail, especially findViewByid
You need to do startActivity instead of what you are doing.
Edit:
Create a constructor in Asynctask pass MainActivity when instantiating and assign like below and remove new MainActivity line
public class fetchSchools extends AsyncTask<Void, Void, ArrayList<String>>{
MainActivity cls2;
fetchSchools(MainActivity activity){
cls2 = activity;
}
#Override
protected ArrayList<String> doInBackground(Void... arg0) {
ArrayList<School> schools = new ArrayList<School>();
ArrayList<String> schoolNames = new ArrayList<String>();
... code omitted for conciseness...
return schoolNames;
}
public void onPostExecute(ArrayList<String> schoolNames) {
cls2.updateSpinner(schoolNames);
cls2.switchScreens();
}
}
In MainActivity, you call
new fetchSchools(mMainActivity).execute(param);
If this is a seperate class from that your main activity, then you're trying to findViewById from where? You probably get NullPointerException on very first line of onPostExecute which is this one:
cls2.updateSpinner(schoolNames);
Because you try to find a view in this method. But you do not have any parent view which contains the view that you seek to find.
So i would suggest you to move this fetchSchools class as a private inner class of your mainActivity. so you'll be able to find those views globally and set them however you want.

pass UI Controls from activity to a class

I stuck at this issue many times and I passed the problem in different ways and I'm not sure that I made it in the right way.
I simplified the problem in a the following example. I know that I can pass only the data to the class but I do want to pass the editText cause I have this problem with more difficult UI controls.
mainactivity.java
public class mainactivity extends Activity {
public EditText clickEditText;
int count =0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
newTxt();
}
public void newTxt() {
txt = new MyText(context);
txt.updateTextEdit("Main Activity");
}
}
myText.java
public class MyText
{
private Context _context;
// constructor
public MyText(Context context)
{
_context = context;
}
public void updateTextEdit(String str)
{
private EditText strEditText;
strEditText= (EditText)findViewById(_context.R.id.editTextClick); // ????
strEditText.setText(str + " and myTxt");
}
}
if you could explain me how to fix the updateTextEdit function. i passed the context of the main activity. How can I change the editText? Thank you very much!!!
If you really want to do this this way, you need to save a reference to Activity, not Context. Like this:
public class MyText
{
private Activity _activity;
// constructor
public MyText(Activity activity)
{
_activity= activity;
}
public void updateTextEdit(String str)
{
private EditText strEditText;
strEditText= (EditText)activity.findViewById(R.id.editTextClick);
strEditText.setText(str + " and myTxt");
}
}
and in newTxt() you will need to change:
txt = new MyText(context);
to:
txt = new MyText(this);
But wouldn't it be easier to just put this method inside your activity? Why do you want it in another class? If it really needs to be in another class, you could make that class an inner class of your activity and you would still have access to the activity's methods and member variables.
There's a similar question here
How to access Activity UI from my class?
You didn't say how you obtained the context, you should use this and get the mainactivity in the other class. not context.
then you can call runOnUIThread to perform UI updates.

Making activity layout in another class

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.

Why does not this work - Android - onCreate()

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.

Categories

Resources