I am getting an NPE in onCreate of the following file (MySubActivity):
public class MySubActivity extends MySuperActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myTextView.setText(getResources().getString(R.string.myString));
}
}
MySuperActivity:
public class MySuperActivity extends Activity {
protected TextView myTextView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_layout);
myTextView = (TextView)findViewById(R.id.myTextViewid);
}
}
The strange thing is that I have never seen this crash while testing the app. The page works fine when I test it. However I got a crash report from Google notifying me of the crash. I cannot reproduce it, and I have no idea under what scenario this crash could happen. Seeing as how it works for me, the resource ids and string names etc. must be correct.
The only thing that came across my mind was that maybe the user had their phone set to a different language, so it couldn't properly pull the resources. However, there are default resources for all of them, and I tested changing the language of my emulator and it didn't crash. Any ideas?
Set your view in another method, like this:
public class MySubActivity extends MySuperActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
private void setView(){
myTextView.setText(getResources().getString(R.string.myString));
}
}
Edit: Don't call setView() in MySuperActivity
public class MySuperActivity extends Activity {
protected TextView myTextView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_layout);
myTextView = (TextView)findViewById(R.id.myTextViewid);
// Or, you can do this in a method called getView() if you like
}
}
Related
I decided to try and make my code more object oriented and avoid repetitive code in another class.
Source code for Activities :
public class EasyMode extends MainActivity {
GameActivityPVP game = new GameActivityPVP();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.game_layout_pvp);
game.initializeButtons();
}
}
public class GameActivityPVP extends MainActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.game_layout_pvp);
initializeButtons();
}
public void initializeButtons() {
button[0] = (Button) findViewById(R.id.button1);
}
}
The second the program gets to the line where I try to call a method using game.methodName(); the program crashes. No compiling errors or anything.
I am new to programming in general so please take it easy on me and I tried to simplify my code as much as possible.
Android Monitor/logcat :
W/OpenGLRenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...
and
W/art: Before Android 4.1, method int android.support.v7.widget.ListViewCompat.lookForSelectablePosition(int, boolean) would have incorrectly overridden the package-private method in android.widget.ListView
You can use another class's method by creating object of parent class.
See below example;
Here you want to use method from 'GameActivityPVP' class. So you need to create one object in this class only.
public class GameActivityPVP extends MainActivity {
public static GameActivityPVP mGameActivity;
public GameActivityPVP getInstance(){
return mGameActivity; // assign value in onCreate() method.
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.game_layout_pvp);
mGameActivity = this; // Do not forget this, otherwise you'll get Exception here.
initializeButtons();
}
public void initializeButtons() {
button[0] = (Button) findViewById(R.id.button1);
}
}
Now use this Object in another class 'EasyMode' like this;
if(GameActivityPVP.getInstance()!=null){
GameActivityPVP.getInstance().initializeButtons();
}
Try This:
Make one Class Utils:
In Utils:
public class Utils{
private Activity context;
Button button;
public Utils(Activity context) {
this.context=context;
}
public void inititializeButton(Activity context){
button[0]= (Button) context.findViewById(R.id.button_flasher);
}
}
And in your Class use:
public class EasyMode extends MainActivity {
Utils utils;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.game_layout_pvp);
utils=new Utils(this);
utils.initializeButtons();
}
}
As already stated, you shouldn't use nested activities, they are not supposed to interact like this. If you want two activities to interact you have to do it through an intent. Regarding the duplicated code, you have few solution presented but my personal opinion is that the OOP rules are not followed. If I had to write that logic, I would create a BaseActivity to hold the common logic of the other two activities and use inheritance to extend them.
public class BaseActivity extends Activity {
protected List<Button> buttons = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.game_layout_pvp);
initializeButtons();
}
protected void initializeButtons() {
buttons.add((Button) findViewById(R.id.button1));
}
}
public class EasyMode extends BaseActivity {
// Add here logic that is used only in EasyMode activity
}
public class GameActivityPVP extends BaseActivity {
// Add here logic that is used only in GameActivityPVP activity
}
Note that in this way you don't have to override onCreate again to initialise the buttons and so on. Also, I saw that you used the same layout for both activities, but if you want to use different layouts you can do it as usual and then call initializeButtons.
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listen();
}
public void listen() {
Toast a = Toast.makeText(MainActivity.this,"HI",Toast.LENGTH_SHORT);
a.show();
}
}
Will this goes on printing the HI string..?
No It won't.
However, onCreate() function is called somewhat more often than you think!
(like on Screen Rotation and more ...)
Checkout Activity Lifecycle and learn when onCreate() is called.
I have the following code:
public class MainActivity extends Activity {
TextView number=(TextView)findViewById(R.id.number2);
TextView number2=(TextView)findViewById(R.id.number2);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
number.setText("Text");
number.setText("Text");
}
followed by more code, but when I run it it crashes.
After doing that i tried to initialize TextViews in onCreate()
public class MainActivity extends Activity {
TextView number;
TextView number2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
number=(TextView)findViewById(R.id.number);
number2=(TextView)findViewById(R.id.number2);
number.setText("Text");
number.setText("Text");
}
and it worked. Why must objects be initialized in onCreate?
Your activity won't have a Window until onCreate(). Attempting to find any views before the window is initialized will lead to NPE.
Additionally, attempting to find views before setContentView() will return nulls and so the return values are not good for anything.
I have two activities almost doing the same thing. The only thing that differs them is a URL to be parsed.
What is considered best practice regarding Android development, subclass just to set the URL or send the URL via an intent?
public SuperActivity extends Activity{
protected String pageUrl;
#Override
protected void onCreate(Bundle savedInstanceState) {
[...lots of stuff...]
super.onCreate(savedInstanceState);
}
}
public SubActivityOne extends SuperActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
pageUrl = "http://urlOne.com"
super.onCreate(savedInstanceState);
}
}
public SubActivityTwo extends SuperActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
pageUrl = "http://urlTwo.com"
super.onCreate(savedInstanceState);
}
}
or
public SuperActivity extends Activity{
private String pageUrl;
#Override
protected void onCreate(Bundle savedInstanceState) {
Bundle extras = getIntent().getExtras();
pageUrl = extras.getString("intent_key_url");
[...lots of stuff...]
super.onCreate(savedInstanceState);
}
}
if you have multiple activities, which share similar functionality (and/or variables/methods) -> go for sub-classing.
if all you need is to pass a value from the invoking activity, use intents (or maybe Static)
In your case, I would subclass, but do it slightly differently than you. It's dangerous to put some code in onCreate when it's not definitely needed. (You may get lost in your hierarchy and not call exactly what you want to call in the correct order) I would use an overriden method rather than a variable. Do that:
public abstract SuperActivity extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
[...lots of stuff...]
// instead of using pageUrl, use a method when you need it: pageUrl()
super.onCreate(savedInstanceState);
}
protected abstract String pageUrl();
}
And your subactivities would look like: (only one shown here)
public SubActivityOne extends SuperActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
protected String pageUrl() {
return "http://urlOne.com";
}
}
The intent way is good too, but it might become complicated if later on you want to add more differences in your subactivities. With subclasses, it's very flexible.
To avoid duplicate code (which is mostly the good thing), make base activity class (make it abstract) and put your common code there. Then make your "real" activities extend base class. So option "A" is the way.
A third option would be to make a callback interface and have any class you want implement it. Something like "PageUrlProvider"
public interface PageUrlProvider
{
String getPageURL();
}
Then the concrete implementation would be
public MyActivity extends Activity implements PageUrlProvider
{
private String pageUrl ="http://example.com/";
#Override
protected void onCreate(Bundle savedInstanceState)
{
String myURL = getPageURL();
super.onCreate(savedInstanceState);
}
#Override
public String getPageURL()
{
return pageUrl;
}
}
Which option you choose is largely dependent on what you are trying to accomplish. But this option offers a lot of flexibility.
I have a function named 'func()'. I want to run this function when application start without clicking any button. just when application load I want to show a massage.that massage in that function. I just want to run that function when app start what will be the code.
public class TextViewActivity extends Activity {
public static EditText etxt;
public final void func(){
etxt.setText("Massage");
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
etxt= (EditText) findViewById(R.id.etxt2);
}
}
Just put a call to the function on the onCreate
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
etxt= (EditText) findViewById(R.id.etxt2);
func(); //A call to the function.
}
Hope that helps.
I don't recommend subclassing the Application in order to do this. When the application starts it will go to the main activity. So I would say just keep a SharedPreference boolean value if it has been set. If not show the message.
So keep state of the application here: http://developer.android.com/reference/android/content/SharedPreferences.html, just set a boolean. Remember when you app gets called, the activity onCreate always gets called of the main activity, so its just a matter of not calling it again.
try using below code.. you need to call ur function after you initialize edittext etxt. so it can not cause you NPE
public final void func(){
etxt.setText("Message");
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
etxt= (EditText) findViewById(R.id.etxt2);
func();// here your function call.
}
Try this:
public class TextViewActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
findViewById(R.id.etxt2).setText("SMTH");
}
}
In case you really need a function to be called, you can use this:
public class TextViewActivity extends Activity {
public final void func() {
findViewById(R.id.etxt2).setText("SMTH");
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
func();
}
}