I am creating an expert system engine with a custom scripting engine, and some of the commands are integrated with the main xml gui. As an example, there is a 'respond' command that accepts strings and sets them in an EditText. The respond command is essential to the functionality of the app, but I cannot access the EditText with findViewById because the command routine resides in another class. Even if it is bad form, how can I access GUI elements from other classes?
Thank you.
how can I access GUI elements from other classes?
If the other class is an Activity, you cannot. You should pass the EditText's contents in an Intent or by some other means.
If the other class isn't an Activity, simply make the EditText a public field variable. Or you can pass this other class a reference to your Activity or the root View and use methods like findViewById() without much fuss.
Provide the EditText object to 'the other class' by using a custom method (like public void setEditText(EditText myEditText), or something similar), or as a parameter in its constructor (depending on your situation).
Another possibility is to send the complete Activity that defined the EditText, so you can use findViewById() to grab the EditText. But I would not recommend it (bad practice, I think) unless you have lots of objects that you need to access.
I had this same problem. My code in my activity had too much code, and I wanted to create external classes to do some of the processing in there. However, one process included using an EditText, and you can't instantiate that in a class that has no UI. So the easiest solution is to make your EditText myEditText variable public and static in the activity, and then when you use it in your external class, just use dot notation with the original activity it came from, and it should work. The static keyword is what makes it a global variable, accessible by other classes/activities.
public static EditText myEditText; // put this in your Activity
ActivityName.myEditText.someMethod(); // use of EditText in your external class
Related
I understand professionals use the former to tailor the onClick method to their exact specification, but cant I just use the onClick attribute and specify the same desired actions within a method.
i.e. [In xml file:] onClick="doSomething" & then
[in MainActivity.java:]
public void doSomething(View view){
//define and start intent
//Show a toast, etc
}
Why not just use the latter option? Thanks
Why not just use the latter option?
Go right ahead.
On bigger projects, it is unlikely that the activity will be managing the button directly:
You might be using fragments, in which case the fragment is more likely to manage the button than is the activity
You might be using MVP, MVVM, MVI, etc. GUI architectures, in which case some other "presenter" object is more likely to manage the button than is the activity
You might be using the data binding framework, in which case you might still be using android:onClick in a layout resource, but directing the event to something other than the activity (e.g., a fragment, a presenter)
And so on
Yes you can do so,both are doing the same thing but using the onClickListener is a better choice ,you can set the listener when you want that button to be active thus your Button and Activity are in cooordinaton.
If you use onClick in your xml file ,it will always call that method doesn't matter what is happening in your activity.
Currently I have an AsyncTask declared both in my main activity class and in my widget class. The code is the same except for the result handling in onPostExecute (in activity the result retrieved goes to a textview within activity and in the widget it goes to a textview in my widget).
I'd like to move the AsyncTask to an external java file (to avoid code duplication) and somehow call it from other different classes (like my widget and main activity) with different result handling. I guess I can't just pass a method name as a parameter to call it from onPostExecute, but is there something else I can do?
The short answer to your question is NO, you cannot do anything about this. In general, AsyncTasks are Activity-specific, and are defined as inner classes inside different Activitys so that they have access to methods defined in that Activity.
You can go ahead and define the same AsyncTask inside the Activity and the widget.
I'm not PRO in JAVA , but I found myself of getting crazy with Android activities getting too large.
After a few pages of code length I found myself of permanently scrolling back and forth!
Not only OnClickhandlers can grow huge, just a lot of code tends to sum up in a bigger activity.
Fragments were no solution for me.
In general Java does not allow to split up a class into several files so a hack is needed.
I browsed through a lot of stackoverflow threads regarding that, not one had a solution.
I solved it anyway, maybe this helps others.
This is a bit Android focused as I got anoyed by my huge onClick Handlers for all the menus and buttons but I guess it will work for other general Java problems as well the same way.
A simple approach that I follow is to move the View concerns into a separate class (let's call it ViewManager) and make the Activity/Fragment work only as a controller.
A ViewManager is generally responsible for -
Inflating the layout
Getting references to all the views
Displaying data in the views
Handling click/touch events
Animations
The Activity/Fragment is only responsible for -
Fetching data and passing it to the ViewManager to display it
Handling navigation
Posting data to a server/DB
For UI controls that trigger an action that the controller is responsible for, say launching a new activity when a button is clicked, the ViewManager receives the click and calls a method in the controller that takes care of the navigation.
If you want to further eliminate boilerplate code (click handlers, findViewById() calls, etc), consider using libraries like ButterKnife.
One solution is simple, you can make the main class fields public
However that will mess up your code, you should keep the fields private when possible.
Aside from better code completion of your IDE it's also protecting the classes from illegal outside manipulation.
Now the trick for me was inner classes.
An inner class can access the private fields of it's parent, however Java does also not allow to put an inner class into another file.
It has to be defined INSIDE the parent class.
This is where I started to dig and found a solution which might be considered to be acceptible.
If this hurts java experts, I'd appreciate not to be downvoted ;)
The trick is to create an "abstract class" in an own java file.
I named it a bit outside conventions to make it stand out: InnerMainActivity_onClickHandlers.java
MainActivity is my main class (the parent of the new inner class)
In my Parentclass I have this field defined, a normal inner class but extending the new class:
private class inner extends InnerMainActivity_onClickHandlers{
public inner(MainActivity mainActivity)
{
super(mainActivity);
}
};
In my MainActivity.onCreate:
Button.setOnClickListener(new inner(this));
As you can see, as you can see it passes the MainActivity (Parent) to the Inner class.
Now the Inner class iteself:
public abstract class InnerMainActivity_onClickHandlers implements View.OnClickListener
{
private final MainActivity main;
public InnerMainActivity_onClickHandlers(MainActivity mainActivity)
{
this.main = mainActivity;
}
#Override
public void onClick(View view)
{
// here implement the listener
}
}
To make this work as advertised you need to change the private properties of your MainActivity/Parent to protected.
Now the extended inner class has access rights to the parent fields, however any external class can still not access it.
In this case I have a dedicated class for all onclick listeners, a second class could be used for other things.
When a new object is made, it often goes:
TextView textView = new TextView(this)
Here, should we always use "this" pointer (an instance of an Activity, normally) as the Context of TextView? For me it seems that any Context would work in many circumstances, such as the following method.
TextView textView = new TextView(this);
textView.setTextSize(textSize);
textView.setTextColor(textColor);
textView.setText(text);
tableRow.addView(textView);
And my assertion is, as I am not adopting any resources, any Context could replace "this." (I assume it is wrong.) Why should we use "this" instead of any other Contexts?
Here, should we always use "this" pointer (an instance of an Activity, normally) as the Context of TextView?
Occasionally, there is a better choice, but that's usually in obvious circumstances:
You are using Presentation to route stuff to an external display, and so you use the Context associated with that Display
You are writing an InputMethodService and need to return the View in onCreateInputView()
You are writing a DreamService and need to call setContentView() and choose to create your widgets in Java code rather than use a layout
Etc.
I am not adopting any resources
Your code is not. Your app is, in the form of framework classes accessing style/theme resources for your activity (or app).
The blog post by Dave Smith in laalto's comment is an excellent starting point for choosing the right Context for the right situation.
As documentation says
Name of the method in this View's context to invoke when the view is clicked.
Perfect, but is it "somehow" possible to create a static method and use it everywhere I need, not to define inside each Activity class. And yes I'm aware of defining the method inside base Activity class. All I'm looking for is to just write full name of method and let it uses it. Possible ?
Thanks
You cannot assign a static method to the onClick xml property. You'll have to add the method you specify there to any activity that consumes the layout. You can have that method in each activity call a static method that actually handles the click, but there's no way to avoid having the instance methods altogether.
It's not possible. Android searches for this method in an activity instance. That is why it must belong to an instance.
My suggestion is you create a class that handles all the functions that the buttons does
and call that function on the Activity's onClick method.
Example
public class AppModel {
public static void button1Function(){
//do something
}
}
then on your activities
public void button1Clicked(View view){
AppModel.button1Function();
}
I think this looks like the MVC design paradigm. Click here for further reading.
Why don't you create an entire new class having your static method?
You can load this class wherever you want then...