I have two classes - my main Android activity class, and my reflection class. I am using Android Studio.
In my main activity class I have one button. I want to make it so that when I press this button I should get the name of the button which is defined in strings.xml.
I don't want to use getText() so don't tell me to use it. I want to use reflection or any other good way.
In my reflection class I used reflection to get my field which I defined in my main activity class and put it into a string variable. When I show this value using a toast it's giving me a null value.
My Reflection Class
public class Reflection extends MyActivity
static public String Value;
public static void Cool() {
MyActivity myActivity=new MyActivity(); // Creating Android Main Activity Class Object
try {
Field field=myActivity.getClass().getField("btnFIRST"); //btnFirst Field Which i Defined In Android Main Activity Class
field.setAccessible(true);
Value=(String)field.get(myActivity);
}
catch (Exception E){
E.printStackTrace();
}
}
}
Android Main Activity Class
public class MyActivity extends Activity {
Reflection ref; // Here I Am Creating My Reflection Class Object
Button btnFIRST;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
btnFIRST = (Button) findViewById(R.id.btnFIRST);
ref=new Reflection(); // Reflection Class New Object
ref.Cool(); // Here I Am Calling My Cool Method Which Define In My Reflection Class
btnFIRST.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(MyActivity.this, "Found Button Name="+ref.Value, Toast.LENGTH_LONG).show();
}
});
}
}
See here: +ref.Value I want to print my button value name, which is "(Click)" defined in strings.xml. But I am getting a null value instead.
I should be getting the output "Found Button Name=Click".
When you construct an instance of MainActivity, the value of btnFIRST for the instance is null. This is because btnFIRST is assigned only in the onCreate() method, which is never called on that instance.
You might think all you have to do is call onCreate() before trying to access the field, but that won't work either: you will get an exception. This is because the instance of MainActivity has not been properly set up (e.g., it doesn't have a proper Context, it does not have a Widnow, etc), so it won't be able to inflate the layout. The Android OS is responsible for doing this setup; it's not something you can do yourself. In general it is ALWAYS a bad idea to construct Activities yourself via their constructor.
That said, I can find absolutely no reason at all you would need to use reflection to obtain the text of this button. Unless you can give us a compelling reason why this would be necessary, you should just use getText().
Alternatively, if you know the string resource ID, you can call getString(...) in your Activity.
Related
I have two classes named abc and def. Class abc has string named "paths" and function named "test". I can easily use the variable "paths" from another class "def" but can't seem to call the function "test" from class "def".
I have created an object of class abc in class def and tried to call the function but it doesn't work.
public class abc extends Activity {
String paths="path";
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
test("lol");
}
public void test(String name){
Toast.makeText(abc.this,name,Toast.LENGTH_LONG).show();
}
}
public class def extends Activity {
abc x= new abc();
String paths=x.paths;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Toast.makeText(def.this,paths,Toast.LENGTH_LONG).show();// This is
//working
x.test("hahahas"); // Not working
}
}
i want the method "test" from class abc to be used by class def passing parameter from class def.
The problem is this
abc x= new abc();
You shouldn't be creating an instance of something that extends Activity in this way. You should be using startActivity or startActivityForResult
Also, you shouldn't be holding a reference to one activity inside an instance of another one at all, because activities are created and destroyed by Android so the reference you hold to it may go stale. See Android Activity Lifecycle`. Simply rotating your device is enough to make this happen.
From the tutorial "build your first app" we have start another activity, assuming that you do infact want to launch another activity. You need to learn about intents; let me quote from that link:
An Intent is an object that provides runtime binding between separate components, such as two activities. The Intent represents an app’s "intent to do something."
Thanks for all your comments. I found the solution. In class def, instead of extending Activity i used
public class def extends abc
making class "def" child class of "abc". And after the line
super.onCreate(savedInstanceState);
in class "def" i added one line shown below which did the job.
super.test("lol123");
Are the classes in the same package? (I assumeing that they are in the same package, because you dont have public infront of String paths)
If a method is public you should be able to call it from everywhere.
So i guess you have a problem in your test case.
try with classes, that do not extend Activity and only have the methods needed to test. Then extend your testcase further and further until it stops working.
Is the path variable final?
you might want to add public static final modifier to it.
I know that keyword this refers to current instance of class. But When we implement View.OnClickListener in our class then on calling method textview.setOnClickListener(this), How does argument this(instance object of class) of setOnClickListener(this) call automatically onClick() method. Is there any code in view class which take object and call onClick method on this code or something else is going on?
I want to know what is going behind the scenes, how does android reaches from this keyword to onClick() method? That is what I want to ask?
OnClickListener is an interface in class View.
If your activity implements this interface by setting:
public class MainActivity extends AppCompatActivity implements View.OnClickListener
then you can set a listener for a view like button:
myButton.setOnClickListener(this);
and override the onClick method implementing it like this:
#Override
public void onClick(View v) {
// your code here
}
so a simple explanation is: this means that your view will use your activity's overridden onClick method.
To implement the View.setOnclickListener in your code you need to first implement the public static interface View.OnClickListener.
like this
public class MyActivity extends Activity implements View.OnClickListener {
}
The above interface contains public void abstract method "onClick(View v)" which you override to put your logics
This method is called when a view has been clicked.
for sake of simplicity i have created the code
// Create an anonymous implementation of OnClickListener
private OnClickListener mCorkyListener = new OnClickListener() {
public void onClick(View v) {
// do something when the button is clicked
}
};
protected void onCreate(Bundle savedValues) {
...
// Capture our button from layout
Button button = (Button)findViewById(R.id.corky);
// Register the onClick listener with the implementation above
button.setOnClickListener(mCorkyListener);
...
}
here OnclickListener is an interface which have object mCorkyListener
similarly you can use this keyword instead mCorkyListener
‘this’ represents the instance of the current class. You can access the properties and functions of the current class with ‘this’ keyword.
Let's have an interface ElectricityBill
public interface ElectricityBill{
public void pay(int amount);
}
now there are two ways you can pay an electricity bill either by going to nearby electricity board office
ElectricityBill bill = new ElectricityBill(){
#Override
public void pay(int amount){
}
}
payBill(bill);
or by paying the bill online
public class User implements ElectricityBill{
.....
#Override
public void pay(int amount){
}
}
.....
payBill(this);
}
in both the cases, the user has to pay XXX amount, similar is the case if you want to listen to input events you either have to pass the original View.OnClickListener object or implement it and pass this to make it work.
Edit:
when you pass this you tell the current class to handle the click events itself and has to override the onClick() to do so. And when you pass object you let the original class to handle the onClick by creating an anonymouse class and implementing onClick(). but when you pass this your current class get's the authority to listen to input events. It becomes on the type of OnClicklistener and gets the authority to listen onClick()
I'm creating an android app. I have a Dialog, and I want to handle the onCancel() event without using an anonymous class because it's cleaner and there are class variables I need access to from the main Activity class. I'm looking for a way to register for events on an object similar to .NET, where I can handle it in a separate method in the class without the need for an anonymous class.
There is a nice example here in the Event Listeners section.
The first example uses an anonymous class for the listener; the second uses a method inside the Activity. No extra class needed.
TL;DR Here is the code stolen from that page:
public class ExampleActivity extends Activity implements OnClickListener {
protected void onCreate(Bundle savedValues) {
...
Button button = (Button)findViewById(R.id.corky);
button.setOnClickListener(this);
}
// Implement the OnClickListener callback
public void onClick(View v) {
// do something when the button is clicked
}
...
}
You can modify this to use onCancel().
How do I access the method myMethod from another class?
public class controller extends Activity
{
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
int myMethod() {int id = 0; return id;} //arbitrary example, may also be static?
}
You pass in your controller Activity to the other class, the way you would with any other object in Java. Just be careful not to hold onto an Activity in places that might cause garbage collection issues (e.g., a service, a static data member, a custom Application object).
I am trying to pass a reference of the current activity to an object but can't seem to find a method that will do this easily. Previously I was able to do this simple passing with the "this" reference of the current context. I then changed my activity from implementing OnClickListener to creating an OnClickListener object so that I could pass it as a parameter. This is when I ran into trouble as I was trying to create the object after I clicked on a button, this means I can no longer pass the activity with "this" because "this" is now a reference of the OnClickListener.
public class MyActivity extends Activity {
private Object mObject;
private OnClickListener mListener = new OnClickListener() {
public void onClick(View v) {
Object mObject = new Object(this);
}
}
}
public class Object {
private Activity mActivity;
public Object(Activity a) {
mActivity = a;
mActivity.setContentView(R.layout.layout);
}
}
Seems like an easy fix but I can't find the answer...
Any help is greatly appreciated.
You are right, this now references the OnClickListener, as it references the current class, and you are working inside an anonymous class. You can reference the outer activity by passing mActivity.this:
Object mObject = new Object(mActivity.this);
Btw: I think I'd rename the mActivity class, as normal class naming convention is for it to start with an uppercase letter.
Add mActivity. to this
Object mObject = new Object(mActivity.this);
In your context, this refers to a listener instance, but you need the outer class's instance there, so you need to add class name to this