Sharing objects through the app using the Application class - java

I am trying to define global objects using the application class.
I therefore define the following class.
public class MyApplication extends Application {
private MyObject myObject=new MyObject();
public MyObject getMyObject(){
return this.myObject;
}
}
Then, I use it in an activity, but I get an error (Cannot resolve method getApplication()):
public class AnActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mood);
Button buttonMusic=(Button) findViewById(R.id.button5);
buttonMusic.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
MyApplication myApplication = ((MyApplication)this.getApplication());
Toast.makeText(MoodActivity.this, "playing music", Toast.LENGTH_SHORT).show();
}
});
}
}
I have no clue why I get this error, as it for example works when calling the getApplication() in another activity.
I'm pretty new to Android and Java, so please excuse the ingenuity of the question.
UPDATE
Then I do MyObject myObject=myApplication.getMyObject(); and I don't get any compilation issue but the app dies as soon as I get in that activity.
As I understand it is not advised to use the Application class for such use, what would be a good alternative?

You're getting this error because you call this.getApplication() inside the View.OnClickListener. Because of this, this now references the listener and not the activity.
To do what you need, just create a Context object outside of the listener in your activity's onCreate method and assign this to it. And, inside the listener, use context instead of this. Something like this :-
public class AnActivity extends Activity {
Context context;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mood);
context = this;
Button buttonMusic=(Button) findViewById(R.id.button5);
buttonMusic.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
MyApplication myApplication = ((MyApplication)context.getApplication());//Changed "the" to "context"
Toast.makeText(MoodActivity.this, "playing music", Toast.LENGTH_SHORT).show();
}
});
}
}
Edit after question update :-
Instead of using the application class, use static objects to achieve global variables. static objects are independent of objects and can be referenced using the class that they belong to. For example, if you define a static variable in your MainActivity.class and name it testObject, then it can be accessed using the following code regardless of your current activity :-
YourObject object = MainActivity.testObject;

Unless you have a specific reason for extending the Application class in Android you probably shouldn't. For reference, look at the note in the documentation for this: https://developer.android.com/reference/android/app/Application.html .
If you are trying to create an object that you can use in your Android app, simply do that as you would in Java:
public class MyObject {
//Your stuff here
}
If there is a reason that you're specifically wanting to extend the Application class then perhaps there's more that people can do to help you if you explain what you're trying to do. I just don't necessarily see a need to go through all that complexity based on your example :)

Change this to AnActivity.this.
Inside the code below the meaning of this changes from AnActivity to View.onClickListener as it is another object and inside those braces you are in the scope of the click listener class
new View.OnClickListener() {
public void onClick(View v) {
MyApplication myApplication = ((MyApplication)this.getApplication());
Toast.makeText(MoodActivity.this, "playing music", Toast.LENGTH_SHORT).show();
}
}
So the code above should become
new View.OnClickListener() {
public void onClick(View v) {
MyApplication myApplication = ((MyApplication)AnActivity.this.getApplication());
Toast.makeText(MoodActivity.this, "playing music", Toast.LENGTH_SHORT).show();
}
}
You can read a bit more about it here

Related

Android use two classes for a single layout

I'm trying to separate some of my java in a few different files.
I have my main class:
public class StartPage extends Activity {
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start_page);
}
...
}
And then I have this other class that I'd like to run on the same layout:
public class part_settings_session extends Activity {
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start_page);
Toast.makeText(getApplicationContext(), "This is from settings", Toast.LENGTH_SHORT).show();
}
...
}
But I'm not able to see that Toast happen anywhere or at any time. Is there a way to make both of these classes work in two separate files? This is to organize scripts for my own sake.
Two Activities can not be visible at same time and here in your code you have defined two Activities with same layout. Your code is fine but to see both activities working, you have to manually start next activity. Below code will help you. This code will start Next Activity 3 seconds after loading First Activity.
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
startActivity(new Intent(StartPage.this, NextPage.class));
finish();
}
}, 3000);
in your onCreate() for the 2nd class, put a Log.d("part_settings_session", "onCreate"); and see if the onCreate ever gets called in the first place. (Since they are using the same layout, it might be difficult to see if you are 'actually' creating an instance of THIS class.
My guess is that you might not even be creating an instance of the part_settings_session class. And without logging it is pretty hard to tell that.
Here is a nice Activity base class that will log all life-cycle events for you
https://github.com/douglascraigschmidt/CS282/blob/c5cf5c4808ea082988ab87c00eeade4837eac967/assignments/assignment1/src/edu/vandy/common/LifecycleLoggingActivity.java

How can I let another class know that a button was clicked (Android Studio)

Below is the code which I'm using to return a number which should be 1 when the button is clicked. However when I try to get that number from another class, it always stays 0.
As you might recognize, I tried to change the number in the onClickListener and returned it below.
I also tried to use the onPause command so that it will return the number onPause but it still doesn't work.
public class MainActivity extends Activity {
public int number;
Button btnAngled;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
btnAngled = (Button) findViewById(R.id.btnAngled);
final Intent intent = new Intent(this, angledForeheadActivity.class);
btnAngled.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
number = 1;
startActivity(intent);
}
});
}
#Override
protected void onPause() {
super.onPause();
}
public int getNumber() {
return number;
}
}
I try to get the code in another class with:
MainActivity a = new MainActivity();
int number = a.getNumber();
Sorry for the noob question..
declare the variable as static variable. Then you can simply obtain the result you want since there is only one copy of that variable. If you want to pass the value using intent, you can call putExtra() of intent to carry information to another activity.
Intent reference page
What you actually want is getting the number from another Class. Don't mix the job with button click together. You should setup the concept of model to store data and seperate UI and data, UI just change/get the data.
I suggest you either of the two ways
Store the number in some global model, then you can get the number from another Class.
User Android Broadcast to transfer the data
Use static variable in Activity is not a good idea, it may cause memroy leak, though it can solve your problem.

Best way to implement View.OnClickListener in Android

Suppose we have an Activity with a lot of views on which OnClickListener is to be registered.
The most common way to implement this is to let the Activity-Subclass implement the OnClickListener, something like this:
public class ActivityMain extends Activity implements View.OnClickListener
{
#Override
public void onClick(View view)
{
switch (view.getId())
{
//handle multiple view click events
}
}
}
The way I like to implement it is to create a private class inside the Activity-Subclass and let that inner class implement the OnClickListener:
public class ActivityMain extends Activity implements View.OnClickListener
{
private class ClickListener implements View.OnClickListener
{
#Override
public void onClick(View view)
{
switch (view.getId())
{
//handle multiple view click events
}
}
}
}
This way the code seems more organized and easy to maintain.
Moreover, talking about "Is-a", "Has-a" relationships, the latter seems to be a good practice because now the Activity-Subclass would have a "Has-a" relationship with the ClickListener.
While in the former method we would be saying that Our Activity-Subclass "Is-a" ClickListener, which ain't completely true.
Note that, I am not concerned with the memory overhead the latter would cause.
Also, adding onClick tag in xml is completely out of question.
So, what really is the best way to implement a ClickListener?
Please don't suggest any libraries like RoboGuice or ButterKnife etc.
UPDATE:
I would like to share the approach I finally adopted.
I directly implement the listener in Activity/Fragment.
As far as OOP design is concerned. The "HAS-A" approach doesn't offers any practical benefits and even takes up more memory. Considering the amount of nested classes (and the memory overhead) we will be creating for every similar listener we implement, this approach should clearly be avoided.
First, there is no best practice defined by Android regarding registering click listeners. It totally depends on your use case.
Implementing the View.OnClickListener interface to Activity is the way to go. As Android strongly recommends interface implementation over and over again whether it is an Activity or Fragment.
Now as you described :
public class ActivityMain extends Activity implements View.OnClickListener
{
private class ClickListener implements View.OnClickListener
{
#Override
public void onClick(View view)
{
switch (view.getId())
{
//handle multiple view click events
}
}
}
}
This is your approach. Now it is your way of implementation and there is nothing wrong with this if you are not concerned with memory overhead. But what's the benefit of creating the inner class and implementing the View.OnClickListener if you can simply implement that in the main class which can also lead to the code clarity and simplicity that you need.
So it just a discussion rather getting the best possible solution of implementing the View.OnClickListener because if you go with the practical point of everyone, you will go for a solution which is simple and memory efficient.
So I would prefer the conventional way. It keeps things simple and efficient. Check the code below:
#Override
public void onClick(View view)
{
switch (view.getId())
{
//handle multiple view click events
}
}
P.S : Your approach will definitely increase lines of code :P ;)
First of all lets get the basics clear here..
By implementing an Interface, your class doesn't become that.. like you said:
"Our Activity-Subclass "Is-a" ClickListener, which ain't completely true."
Your class can only have "Is-a" relationship if it extends, in this case an Activity. Implementing an interface means that it can behave like what interface has set its contract.
An Example:
class Peter extends Human .. means Peter is a Human..
class Peter can also implement programmer, musician, husband etc
means Peter can behave as the above.
As for best practice, you could make an entirely separate class which implements OnClickListener like this:
class MyListener implements View.OnClickListener{
#Override
public void onClick(View view) {
// do whatever you want here based on the view being passed
}
}
And in your main Activity you could instantiate MyListener and call onClick() and pass your view in it:
MyListener listener = new MyListener();
Button b = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button)findViewById(R.id.button);
listener.onClick(button);
}
I use button.setOnClickListener(this); where my Activity implements View.OnClickListener, and then get the ID of the Button in a separate method. See below for an example:
public class MyActivity extends ActionBarActivity implements View.OnClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.YOUR_LAYOUT);
...
Button myFirstButton = (Button) findViewById(R.id.YOUR_FIRST_BUTTON);
myFirstButton.setOnClickListener(this);
Button mySecondButton = (Button) findViewById(R.id.YOUR_SECOND_BUTTON);
mySecondButton.setOnClickListener(this);
...
}
...
#Override
public void onClick(View v) {
Button b = (Button) v;
switch(b.getId()) {
case R.id.YOUR_FIRST_BUTTON:
// Do something
break;
case R.id.YOUR_SECOND_BUTTON:
// Do something
break;
...
}
}
...
}
Here you can create a btnClickListner object and after that you will call that btnCLickLisner object when ever you want to perform the onCLieck actions for buttons..
Let us assume, in my activity i have a 5 to 10 buttons and writing each button separate onclick listner is bad idea. So to over come this,we can use like below..
register your buttons
Button button1 = (Button)findViewById(R.id.button1);
Button button2 = (Button)findViewById(R.id.button2);
Button button3 = (Button)findViewById(R.id.button3);
Button button4 = (Button)findViewById(R.id.button4);
Button button5 = (Button)findViewById(R.id.button5);
Here i am setting the onclick listner to my buttons after click
button1.setOnClickListener(btnClickListner);
button2.setOnClickListener(btnClickListner);
button3.setOnClickListener(btnClickListner);
button4.setOnClickListener(btnClickListner);
button5.setOnClickListener(btnClickListner);
Here is the btnClick Listner implementation
View.OnClickListener btnClickListner = new OnClickListener()
{
#Override
public void onClick( View v )
{
// TODO Auto-generated method stub
if( button1.getId() == v.getId() )
{
//Do Button1 click operations here
}
else if( button2.getId() == v.getId() )
{
// Do Button2 click operations here
}
else if( button3.getId() == v.getId() )
{
// Do Button3 click operations here
}
else if( button4.getId() == v.getId() )
{
// Do Button4 click operations here
}
else if( button5.getId() == v.getId() )
{
// Do Button5 click operations here
}
}
}
I have found using Butterknife makes for clean code. And because it uses code generation (not reflections) it has little performance overhead.
public class ActivityMain extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.inject(this);
}
#OnClick(R.id.button_foo)
void onFoodClicked() {
// Do some foo
}
#OnClick(R.id.button_bar)
void onBarClicked() {
// do some bar
}
}
For this particular case I'd say that maintain a single instance of a OnClickListener is the best approach for you. You will have a "Has-a" relationship and won't need to create several instances since you are handling the behavior using the view id in the onClick(View view) callback.
public class ActivityMain extends Activity implements View.OnClickListener {
private View.OnClickListener mClickListener = new View.OnClickListener() {
#Override
public void onClick(View view) {
switch (view.getId()) {
//handle multiple view click events
}
}
};
}
Your ClickListener is an inner non-static class the coupling of this 'has-a' is no different than if your class Activity implemented View.OnClickListener. This is because your inner ClickListener requires an instance of ActivityMain and really can't be reused. I would argue that you're over engineering and aren't actually gaining anything.
EDIT: To answer your question I like to have anonymous View.OnClickListener for each widget. I think this creates the best separation of logic. I also have methods like setupHelloWorldTextView(TextView helloWorldTextView); where I put all my logic related to that widget.
First approach is better than the other because thats why View.OnClickListener is an Interface instead of an abstract class. besides the later might leak in various situations since you are using a non-static inner class.
A small remark to this, and maybe a little bit of topic.
What, if we not just implement OnClickListener and we have a bunch of other Listeners / Callback to implement. In my Opinion it will get messy to implement all of these in the class instead of using anonymous classes / lambda. It is hard to remember wich method belongs to which interface.
So if we have to implement an interface (in this case OnClickListener) multiple times it my be a good solution to implement on class base and use the switch/case.
But if we have to implement multiple interfaces it may be a good solution to use anonymous classes / lambda
simply you using like not implements subclass or not handle a click event just do like this way .
android.view.View.OnClickListener method_name = new android.view.View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
// put your code .
}
};
and handle click event into button ya any type of click event like
button_name.setOnClickListener(method_name);
its work very simply
Thanks
public class ProfileDetail extends AppCompatActivity implements View.OnClickListener {
TextView tv_address, tv_plan;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_profile_detail);
tv_address = findViewById(R.id.tv_address);
tv_plan = findViewById(R.id.tv_plan);
tv_address.setOnClickListener(this);
tv_plan.setOnClickListener(this);
}
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.tv_plan:
startActivity(new Intent(getApplicationContext(),PlanActivity.class));
break;
case R.id.tv_address:
startActivity(new Intent(getApplicationContext(),AddressActivity.class));
break;
}
}
}
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Chronometer chronometer;
private Button startButton;
private Button stopButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
chronometer = findViewById(R.id.chronometer);
startButton =findViewById(R.id.startBtn);
stopButton = findViewById(R.id.stopBtn);
startButton.setOnClickListener(this);
stopButton.setOnClickListener(this);
}
#Override
public void onClick(View v) {
switch (v.getId()){
case R.id.startBtn:
chronometer.start();
break;
case R.id.stopBtn:`
chronometer.stop();
break;
}
}
}
It really depends on what you want to achieve. If you have e.g. a complex functionality with threading, dependencies, etc., I personally like to decouple it completely from the Activity into a separate class XyzAction, that does the heavy stuff, knows about certain Invokers and returns them results, if needed. My Invokers are basically objects, that implement OnClick/OnTouch/etc.Listeners and bind themselves to needed actions. E.g. there could be a LoginInvoker implementing OnClickListener for a Button and an ImageView and also a generic ActionListener that gets invoked when a MenuItem is clicked. The Invoker has update methods for showing progress to the user and the result of the bound action. The action posts updates to its Invokers and can be garbage collected, if all of them die, because it has no connection to the UI.
For less complex actions, I couple them directly to the Android component (i.e. Activity/Feagment/View) and also call them Actions, with the big difference of them implementing the UI callbacks directly.
In both cases I declare the actions as members, so I can see on a quick glance what specific actions the Android component supports.
If there's something trivial like "show a Toast if button is pressed", I use anonymous inner classes for the UI callbacks, because you normally don't care that much about them with regards to maintainability.
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
Button north,south,east,west;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
north.setOnClickListener(this);
south.setOnClickListener(this);
east.setOnClickListener(this);
west.setOnClickListener(this);
}
private void init(){
north = findViewById(R.id.north);
south = findViewById(R.id.south);
east = findViewById(R.id.east);
west = findViewById(R.id.west);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.north:
Toast.makeText(MainActivity.this,"NORTH",Toast.LENGTH_SHORT).show();
break;
case R.id.south:
Toast.makeText(MainActivity.this,"SOUTH",Toast.LENGTH_SHORT).show();
break;
case R.id.east:
Toast.makeText(MainActivity.this,"EAST",Toast.LENGTH_SHORT).show();
break;
case R.id.west:
Toast.makeText(MainActivity.this,"WEST",Toast.LENGTH_SHORT).show();
break;
}
}
}

Why OnClickListener interface is not implemented and passed as new in setOnClickListener() method?

I am learning JAVA for Android. I have read that Interfaces should be implemented. But i have confusion here:
final CheckBox checkbox = (CheckBox) findViewById(R.id.checkbox);
checkbox.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (checkbox.isChecked()) {
checkbox.setText("I'm checked");
} else {
checkbox.setText("I'm not checked");
}
}
});
we are passing and implementing OnClickListener interface directly here. What is exact reason for this? Please explain this concept in details.
It's because you want to implement it individually for each individual clickable widget. OnClickListener is an inner interface in the View class and logically it would not make sense to make the activity implement it as then any click on the screen even outside of this would trigger unexpected action.
Interfaces alone do not have an implementation. But here what you're actually doing is creating a new anonymous class (a class without a name) that implements the OnClickListener interface and defining the implementation of it all in one place.
As for why you would do this- for very small simple implementations it can be clean, and it prevents you from having dozens of little classes that implement 1 or 2 functions. If the implementation is long it can become difficult to read though. But its never wrong to do it the long way and use a regular class.
Normally we implement OnClickListener like below,
public class MainActivity extends Activity implement OnClickListerner
{
....
view.setOnClickListener(this); // When we are implemeting OnClickListener
#Override
public void onClick(View v)
{
....
}
}
When we implement OnClickListener in that case we set it using setOnClickListener(this), here this refers to OnClickListener listener.
However we can do same thing by declaring another way known as anonymous block as below,
CheckBox checkbox = (CheckBox) findViewById(R.id.checkbox);
checkbox.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (checkbox.isChecked()) {
checkbox.setText("I'm checked");
} else {
checkbox.setText("I'm not checked");
}
}
});

Get context of current running activity

I wonder if there is a way to get the context of current running activity on android. For example, I have an Activity Class and it is running. What I want is to call another Simple Class to run some functions which called from Activity Class. By doing this, I need to set up a context of Activity Class on Simple Class; On the other way, I need to have the context of Current Running Activity, so that my Simple Class can actually run the functions called from Current Running Activity.
Below is the soft code from my project.
public class Main1 extends Activity {
private static GetAPNsInfo getAPNsInfo = new GetAPNsInfo();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
getAPNsInfo.doSomething();
}
}
public class GetAPNsInfo {
public void doSomething() {
Button button = currentRunningActivityContext.findViewById(R.id.button1);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
}
});
}
}
Finally, my purpose of this thread is that I need a good way to get the current running activity info.
This is a solution that I found my self. But it doesn't totally solve this case. We can add a receiver in Manifest.xml. This will run a background application.
<receiver android:name=".RunningActivityCapture">
<intent-filter android:priority="-1">
<action android:name="android.intent.action.NEW_OUTGOING_CALL"></action>
</intent-filter>
</receiver>
The background application interface look like this:
public class RunningActivityCapture extends BroadcastReceiver {
#Override
public void onReceive(Context aContext, Intent intent) {
String action = intent.getAction();
if (action.equals(Intent.ACTION_ALL_APPS)) {
Activity activty = intent.getCurrentActivity();
Session session = new Session();
session.setRunningActivity(activty);
}
return;
}
}
I only get the activity from session class which setting from my background application. This is my first idea to solve this problem. But the code is not correct. So I need your help.
If you are asking how to use this MainActivity in your helper class, you can pass the Activity itself into your class, as an activity is a Context. So your constructor will be:
public GetAPNsInfo(Context context) {
...
}
where you store the context in a field and use it later. You will initialize with
private static GetAPNsInfo getAPNsInfo = new GetAPNsInfo(this);
if you are asking how to get the context for ANY activity in your application, I don't think that is recommended.

Categories