• After 15+ years, we've made a big change: Android Forums is now Early Bird Club. Learn more here.

Apps Button Issue

Conor Calby

Newbie
May 3, 2011
22
0
I am developing a small android application for my martial arts club however, whenever it opens, it force closes straight away.

The way it is meant to go is like so.. You open the app (loads main.xml) then you press a button (button1) to continue to bels.xml. So far, I am trying to make the whitebelt button (button2) go to whitebelt.xml.

I have the pages/screens created and here is the activity.java file.
[Java] EvolutionTheoryHelperActivity.java - Pastebin.com

Now, its this part that is causing the issue as if I remove it, it works fine... However it doesn't allow my button2 to work.
Code:
Button button2 = (Button)this.findViewById(R.id.button2);
    button2.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View whitebelt) {
           // button 1 was clicked!
                setContentView(R.layout.whitebelt);
        }
        });
Do you think you could help?
Regards,

--Conor Calby
 
I personally hate when I see someone create an object within a method parameter....oh well, java.

Basically part of the problem is scope I think. You are calling a method of the activity from within a listener. And since a listener does not extend Activity, AND it is being created inside a method of another object it has no such method itself.

Anyways, try this -- it should be more clear this way:
Code:
//MyActivity.java

Button button2 = (Button) findViewById(R.id.button2);
button2.setOnClickListener(myButton2listener);


// this is now an inner class and can "see" the methods in the activity
// let's have it call our own protected method setSecondContentView()

View.OnClickListener myButton2listener = new View.OnClickListener() 
{         
     @Override         
     public void  onClick(View v) 
     { 
         // button 2 was clicked!                  
          setSecondContentView();
     }         
}



protected void setSecondContentView()
{
     setContentView(R.layout.whitebelt);
}
if that doesnt work, post the stack trace and we'll see if we can figure it out from there :)
 
  • Like
Reactions: Conor Calby
Upvote 0
Your problem is, indeed, a scope issue.

Furthermore, alostpacket's solution will not work either. The reason is that, like alostpacket stated, you are both creating an inner class. Inner classes are ultimately bad programming practices, but they are often "forgiven" in Android development (why, I am not sure). In any rate, the reason they are looked down upon in normal practice is for this reason. Scope becomes a pain in the rear end to manage and often leads to hard-to-find bugs.

At any rate, what you both are doing is creating a new interface and attempting to call a method of another class (the Activity subclass) in your new interface (the listener). You really only have a couple ways to go about this correctly:

1) Perhaps the simplest is to make your activity class the listener by implementing the listerner using the implements keyword.

Example:
Code:
public class MyActivity extends Activity implements View.OnClickListener
{
       ...
       Button button2;
       ...
       @override
       public void onCreate(Bundle savedInstanceState)
       {
               super.onCreate(savedInstanceState);
               ...
               button2 = (Button)findViewById(R.id.button2);
               button2.setOnClickListener(this);
               ...
       }

       @Override
       public void onClick(View v)
       {
            if(v == button2)
                 this.setContentView(R.layout.whitebelt);
       }
}

2) The second, more accepted approach, is to create another class that implements the listener and pass a pointer to the Activity subclass as a parameter of the constructor. Then, use that pointer to call the setContentView method inside onClick. Inside of your Activity subclass, you would create an instance of the new class.

Since you are apparently new to Java, and likely OOP in general, I would recommend making things easy on yourself and using the 1st approach. Although it is not the best programming practice, it gets the job done and is easy to implement.
 
  • Like
Reactions: Conor Calby
Upvote 0
Furthermore, alostpacket's solution will not work either.

Ahem :)

I do this all the time...I'm looking at an identical method in one of my apps :p


Anyways, the problem with my solution is that the compiler generates all those $access2000 static methods because it's not sure if inner classes accessing private/protected methods of the outer class is valid (even though it technically is)

One way to solve that though is to make any method called by an inner class have package level scope. A bit "dangerous" but it reduces code size and is better for performance.

The problem with your solution (#1) is you have taken a step towards making the activity the God anti-pattern. I dont like having my activities handle all the work. Making listener objects (seems at least) to make them more portable down the road for refactoring. Solution #2 is good though.

Either way they all have ups and downs :) Also I totally agree/hate inner classes.
 
Upvote 0
Example:
Code:
public class MyActivity extends Activity implements View.OnClickListener
{
       ...
       Button button2;
       ...
       @override
       public void onCreate(Bundle savedInstanceState)
       {
               super.onCreate(savedInstanceState);
               ...
               button2 = (Button)findViewById(R.id.button2);
               button2.setOnClickListener(this);
               ...
       }

       @Override
       public void onClick(View v)
       {
            if(v == button2)
                 this.setContentView(R.layout.whitebelt);
       }
}

Since you are apparently new to Java, and likely OOP in general, I would recommend making things easy on yourself and using the 1st approach. Although it is not the best programming practice, it gets the job done and is easy to implement.
This is honestly the only app I will ever create for Android. I only started with OOP a few months ago so it is fairly new to me.

Here is what I have.
[Java] package com.example.android.apis.tests; import android.app.Activity; import - Pastebin.com

Sorry for the n00bness. :p
 
Upvote 0
OK it looks like button 2 is null...
Caused by: java.lang.NullPointerExceptionE/AndroidRuntime( 428): at com.example.android.apis.tests.EvolutionTheoryHelperActivity.onCreate(EvolutionTheoryHelperActivity.java:22
^ check line 22... then make sure R.id.button2 is the id for your second button and that it exists in the main.xml layout
 
Upvote 0
Wow. Thanks mate! Got it now. Added
Code:
    @Override
    public void onClick(View v)
    {
         if(v == button1)
              this.setContentView(R.layout.belt);
         
         button2 = (Button)findViewById(R.id.button2);
         button2.setOnClickListener(this);
         if(v == button2)
             this.setContentView(R.layout.whitebelt);
    };

What you said makes sense regarding the reset objects. Thanks again!
 
Upvote 0
Ahem :)

I do this all the time...I'm looking at an identical method in one of my apps :p


Anyways, the problem with my solution is that the compiler generates all those $access2000 static methods because it's not sure if inner classes accessing private/protected methods of the outer class is valid (even though it technically is)

One way to solve that though is to make any method called by an inner class have package level scope. A bit "dangerous" but it reduces code size and is better for performance.

The problem with your solution (#1) is you have taken a step towards making the activity the God anti-pattern. I dont like having my activities handle all the work. Making listener objects (seems at least) to make them more portable down the road for refactoring. Solution #2 is good though.

Either way they all have ups and downs :) Also I totally agree/hate inner classes.

Oops... after reconsidering what I said, I realize now that I was wrong.. In fact, the way he had it initially should have worked as well. Since the class was defined withing another class, all data members of the outer class would therefore be available to the inner class as well...

I apologize for the brain fart. haha
 
Upvote 0
Upvote 0
Oops... after reconsidering what I said, I realize now that I was wrong.. In fact, the way he had it initially should have worked as well. Since the class was defined withing another class, all data members of the outer class would therefore be available to the inner class as well...

I apologize for the brain fart. haha


No worries, I was thinking to myself when I read the OP "shouldn't this work?" But somehow was convinced since he was creating the inner class/object IN the param of a method it somehow lost scope.... but I guess it doesnt matter :)
 
Upvote 0
Upvote 0

BEST TECH IN 2023

We've been tracking upcoming products and ranking the best tech since 2007. Thanks for trusting our opinion: we get rewarded through affiliate links that earn us a commission and we invite you to learn more about us.

Smartphones