Button variable turns to null after calling method - android

In my mainactivity I have the following snip
MainActivity.class
private Button btnx10;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Button btnx10=(Button)findViewById(R.id.MainCOPbtn);
DrawLines();
}
private void drawLines(){
float centerYOnImage1=btnx10.getHeight()/2;
}
I'm trying to access the button that is created in the onCreate() method from the method drawLines()
i.e. in the same class MainActivity.class but outside of this method.
When I am trying to access the button in the drawlines()method it's value is null.
How can I access the button?

Since you have declared the Button in Scope of Method onCreate()
Button btnx10=(Button)findViewById(R.id.MainCOPbtn);
and you are trying to access it outside of the method onCreate(), that makes it inaccessible outside of this method.
Just make the reference on class level (Globally) and use the same Reference in onCreate() method.
you can do this:-
private Button btnx10;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
btnx10 = (Button)findViewById(R.id.MainCOPbtn);
DrawLines();
}
private void drawLines(){
float centerYOnImage1 = btnx10.getHeight()/2;
}

Change the code to
btnx10= findViewById(R.id.MainCOPbtn);
You are casting Button in the declaration which makes global variable inaccessible.

Remove local declaration of Button again.
Just use btnx10=(Button)findViewById(R.id.MainCOPbtn); in onCreate()

You are declaring Button btnx10 twice. Remove the local declaration.
You should declare outside the method, and define inside the method.
Class MainActivity...
private Button btnx10;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
btnx10=(Button)findViewById(R.id.MainCOPbtn); //MINOR CORRECTION IN THIS LINE
DrawLines()
}
private void drawLines() {
float centerYOnImage1=btnx10.getHeight()/2;
}

Related

Calling findViewById() before setContentView() causes NullPointerException but not always? [duplicate]

This question already has answers here:
NullPointerException with findViewById in variable definition
(1 answer)
findViewByID returns null
(33 answers)
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 2 years ago.
Well i get a NullPointerException when i I call findViewById() to access a Button. I think I understand why I'm getting this error but there are some questions I have unsolved in my head.
Well I think I'm getting this error because I moved the findViewById() calls from inside the onCreate() method to class scope, outside of all the methods.
So now I'm initializing my Button's and EditText's outside the onCreate() method.
Well if I understand correctly, this is happening(Null error) cause the setContentView() method is called after the findViewById() method, so that's why it throws an Exception.
But what I don't understand is that I have done the same thing in my second activity and works well without any null exception. And I'm initializing my Buttons etc outside the onCreate() method!
It does confuse me a little bit. Any help clearing this in my head would be much appreciated.
First Activity
public class FirstActivity extends AppCompatActivity {
private Button signUpButton= findViewById(R.id.lo_signUpButton);
private Button loginButton = findViewById(R.id.lo_loginButton);
private EditText username= findViewById(R.id.lo_usernameText);
private EditText password= findViewById(R.id.lo_passwordText);
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//set view
setContentView(R.layout.activity_login);
Log.i(TAG,"Create "+formatter.format(new Date()));
//listeners
signUpButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
startActivity(new Intent(LoginActivity.this, SignUpActivity.class));
finish();
}
});
}
Second Activity
public class SecondActivity extends AppCompatActivity {
private EditText username = findViewById(R.id.su_username);
private EditText password = findViewById(R.id.su_password);
private TextView errorText= findViewById(R.id.su_error_msg);
private Button signUpButton=findViewById(R.id.su_signupButton);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//set view
setContentView(R.layout.activity_signup);
Log.i(TAG,"Create");
//listeners
Button backButton = findViewById(R.id.su_backButton);
backButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
startActivity(new Intent(SignUpActivity.this, LoginActivity.class));
Log.i(TAG,"Going Back ");
finish();
}
});
You can't use this initialization:
public class SecondActivity extends AppCompatActivity {
private Button signUpButton= findViewById(R.id.lo_signUpButton);
//....
}
Use:
public class SecondActivity extends AppCompatActivity {
private Button signUpButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//set view
setContentView(R.layout.activity_signup)
signUpButton= findViewById(R.id.lo_signUpButton);
//...
}
}
In the 2nd Activity you are doing something different:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_signup);
Button backButton = findViewById(R.id.su_backButton);
//...
}
and it is correct since you declaring and initializing the backButton with the findViewById method inside the onCreate after the setContentView call.
In the 1st Activity you are setting the listener with signUpButton.setOnClickListener but the signUpButton is not initialized (since it is outside the onCreate method)
Also in the 2nd Activity the other buttons that are wrongly initialized are not used in the OnCreate method.
In second activity, you have not used the buttons that are wrongly initialized, once you use them, it will cause exception too.
You have used backButton which is correctly initialized.
The answer is quite simple. the global variables get initialized before setContentView() is called, meaning what findViewById() will return null. findViewById() returns the view if found or null. As you didn't call setContentView yet, it cannot find the view you want.
The global variables in FirstActivity as well as SecondActivity are all null.
The difference between FirstActivity and SecondActivity is, that you don't access any global variable in SecondActivity.
The only view you used in SecondActivity is backButton, which you retrieved after calling setContentView, so of course, no NullPointerException will be thrown.
Always declare the variable as globally and initialize it in onCreate(). Even better, try to avoid global variables and pass them though method parameters.

I get crash or loop in my app if I use onResume() method

In one of my android App, extending Activity, I use onResume() to refresh activity in return from PreferenceActivity, such this way ...
public class ListViewWebShort extends Activity {
ListView listView;
#Override
protected void onResume() {
super.onResume();
this.onCreate(null);
}
....
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_view);
// Get ListView object from xml
listView = (ListView) findViewById(R.id.list);
....
.. and here, App works as expected.
In another App, where I extend AppCompatActivity, the same onResume() method, makes my app crash or loop on start :
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
ListView listView;
ArrayAdapter<String> adapter;
....
#Override
protected void onResume() {
super.onResume();
this.onCreate(null);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
....
If I use requestWindowFeature(Window.FEATURE_NO_TITLE); before setContentView, I see in debug that App loops in getDelegate().setContentView(layoutResID), inside AppCompactActivity.java, but if I remove it, the app FCs in the same function.
It really makes me drive crazy .. what am I missing?
Thanks in advance for any suggestion.
Don't call any activity lifecycle method directly. These methods are intended to be called from the system (inversion of control).
Especially in the super implementation of onCreate() there might happen something, that leads to crashes if they are called in the wrong order.
Try to extract the code, which you want to call in onCreate() and in onResume() in a separate method and call this method from onCreate() and onResume().
Actually in every call of onCreate, the onResume method of the application is also called.
So just move whatever code you wrote in the onCreate to onResume.
Hope it helps.

Android: How to execute a method before the layout is initiated/created in an activity

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

Getting string resource from xml file outside onCreate method

I am trying to use a String from the string.xml file as a key in a key-value pair. However when I try to declare the variable before the onCreate() method, the program crashes. So if I use the following code I get an error:
public class MainActivity extends ActionBarActivity {
String MAX_SQUAT = getResources().getString(R.string.max_squat);
protected void onCreate(Bundle savedInstanceState) {
//blah blah blah
}
}
Whereas when I declare MAX_SQUAT inside the onCreate() method, there is no problem. I want to declare it outside of onCreate() method so I don't need to define it in other methods
You need a Context to get resources (as you can see in the Docs getResources() is a method of Context). Since the Context isn't available before onCreate(), you can't do this.
You can declare the variable before onCreate() but you can't initialize it until after onCreate() has been called.
Ex.
public class MainActivity extends ActionBarActivity {
String MAX_SQUAT;
protected void onCreate(Bundle savedInstanceState) {
// super call, set content view
// now you can get the string from strings.xml safely
MAX_SQUAT = getResources().getString(R.string.max_squat);
}
Declaring it as a member variable this way but initializing it in onCreate() will allow you to use it throughout the class and keep it from crashing.

Android application closes on click

I do my android app , but I have a bug I don't know how to fix it.
My code is below :
This is my Main Activity :
public class MainActivity extends Activity {
private ImageView imgHot;
public final static String EXTRA_MESSAGE="com.cuonglm.KhoHinh.MESSAGE";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imgHot=(ImageView)findViewById(R.id.imageViewHot);
imgHot.setOnClickListener(toContentHot);
}
View.OnClickListener toContentHot=new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent content=new Intent(MainActivity.this,ContentActivity.class);
String signal="1";
content.putExtra(EXTRA_MESSAGE,signal);
startActivity(content);
}
};
And this is my second Activity :
public class ContentActivity extends Activity {
private TextView viewMessage;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent content=getIntent();
String messageReceive=content.getStringExtra(MainActivity.EXTRA_MESSAGE);
viewMessage=(TextView)findViewById(R.id.content_receive);
viewMessage.setText(messageReceive);
setContentView(R.layout.activity_content);
}
I want to click on the image on the Main Activity , string "1" or number "1" will send to the Second Activity via Intent and view on the TextView.
But my app will be close "Unfortunately..."
Thanks
Change to
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_content);
viewMessage=(TextView)findViewById(R.id.content_receive);
viewMessage.setText(messageReceive);
In your ContentActivity
findViewById looks for a view with the id for the current infalted layout. SO you need to set the content of your layout to the activity first and then initialize your views.
You are probably gettting NullPointerException coz your initialization fails.
You need to call setContentView() in your second Activity before trying to access any of the Views in that layout. Change it to
public class ContentActivity extends Activity {
private TextView viewMessage;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_content);
Intent content=getIntent();
String messageReceive=content.getStringExtra(MainActivity.EXTRA_MESSAGE);
viewMessage=(TextView)findViewById(R.id.content_receive);
viewMessage.setText(messageReceive);
}
If this doesn't fix your problem then please post your logcat so we can see the error. Also always post logcat in the future when your app crashes. They aren't always this easy to see.
Also, I'm not sure you understand how putExtra() works. It is a key, value pair so when you put EXTRA_MESSAGE as the key then that is what you would use to retrieve the value added in the second param. So the way you are doing it may work if the Activity gets destroyed but it looks really strange to me and probably not realy safe or efficient. I would change it to something like
content.putExtra("message",signal);
in your first Activity then get it with
String messageReceive = content.getStringExtra("message");
in your second Activity
You need to set the layout before trying to reference the Views associated with it.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent content=getIntent();
String messageReceive=content.getStringExtra(MainActivity.EXTRA_MESSAGE);
setContentView(R.layout.activity_content);
viewMessage=(TextView)findViewById(R.id.content_receive);
viewMessage.setText(messageReceive);
}

Categories

Resources