I'm having some issues with the old "Cannot make a static reference to a non-static method" error in my Android program. I am creating a sand falling game (similar to the Powder Game) and I created a class called Control to create a Control Bar at the bottom of the screen with a slider for brush size (that works fine) and a button to pop up a Dialog to allow users to pick the selected element. However, when I call DemoActivity.showDialog(2) from my code, it gives the static reference to non-static error (DemoActivity is the main activity of my application). I also tried changing it to just Activity.showDialog(2), but I got exactly the same error! Please help, what am I doing wrong? Here's my code and thanks in advance:
package sand.falling.opengl;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.SeekBar;
public class Control extends LinearLayout
{
private ImageButton control_button;
private SeekBar brush_size_slider;
final CharSequence[] elementslist = {"Sand", "Water", "Plant", "Wall", "Fire", "Ice", "Generator", "Oil", "Magma", "Stone", "C4"};
public Control(Context context, AttributeSet attrs)
{
super(context, attrs);
}
@Override
protected void onFinishInflate()
{
control_button = (ImageButton) findViewById(R.id.element_picker_button);
brush_size_slider = (SeekBar) findViewById(R.id.brush_size_slider);
control_button.setOnClickListener
(
new OnClickListener()
{
public void onClick(View v)
{
//THIS DOESN'T WORK!!!!
DemoActivity.showDialog(2); //Run the element picker dialog
}
}
);
control_button.setImageResource(R.drawable.palette);
brush_size_slider.setOnSeekBarChangeListener
(
new SeekBar.OnSeekBarChangeListener()
{
public void onProgressChanged(SeekBar seekbar, int progress, boolean fromTouch)
{
int p = 32 * progress/100;
DemoActivity.setBrushSize(p);
Log.v("DemoActivity", "size:" + p);
}
public void onStartTrackingTouch(SeekBar seekbar) {}
public void onStopTrackingTouch(SeekBar seekbar) {}
}
);
brush_size_slider.setProgress((int)400/32);
}
}
EDIT: I fixed it by adding the following to my Control.java code:
public class Control extends LinearLayout
{
private DemoActivity activity;
...
public void setActivity(DemoActivity act)
{
activity = act;
}
...
//Set a click listener for the button which should pop up element picker dialog when clicked
control_button.setOnClickListener
(
new OnClickListener()
{
public void onClick(View v)
{
activity.showDialog(2); //Run the element picker dialog
}
}
);
}
And then calling control.setActivity(this);
from my onResume section of DemoActivity.java! Hope it helps those of you with similar issues!!
i.e. referring a variable using static reference implies to referring using the class name. But, to access instance variables it is a must to create an object, these are not available in the memory, before instantiation. Therefore, you cannot make static reference to non-static fields(variables) in Java.
There is one simple way of solving the non-static variable cannot be referenced from a static context error. Address the non-static variable with the object name. In a simple way, we have to create an object of the class to refer to a non-static variable from a static context.
You cannot call non-static methods or access non-static fields from main or any other static method, because non-static members belong to a class instance, not to the entire class.
static methods and fields belong to classes and non- static methods and fields belong to class instances. To call a non- static method you need an instance of a class, and that's all. Hope this helps. The member functions are being called on a specific instance.
You have to call showDialog
on a DemoActivity
instance, NOT on the class itself. The only time you can call ClassName.methodName()
is if the method is defined as static. showDialog
is not a static method.
To fix this, you either need to instantiate a new DemoActivity
or get an existing one, then call showDialog
on that.
Edit: If you already have a DemoActivity
instance when you instantiate this Control
object, perhaps the following modification will work:
public class Control extends LinearLayout
{
...
// add an Activity instance
private Activity activity;
// set the Activity in your constructor
public Control(Context context, AttributeSet attrs, Activity activity)
{
super(context, attrs);
this.activity = activity;
}
@Override
protected void onFinishInflate()
{
...
// Use the instance activity here
activity.showDialog(2);
...
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With