0

In my application I have an Activity" Model" in which i get a value 'n' from an edit text , I have declared this value n as static int . So , that i can access it inside any class of the Application.

The problem is that when I restart my application without reinstalling it , the value of 'n' remains the same as it was in the first case . And this affects my output.

I cannot use intent to send values because , the value is accessed randomly in the application even in classes that are not activities.

Can u please tell , where I m wrong.??

package com.integrated.mpr;

import java.io.File;

import android.app.Activity;
import android.app.Dialog;

import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class Model extends Activity implements OnClickListener{



    EditText etPos;
    Button bmodel;


    static int n;//static variable to be used in other classes


    File folder ;
    File subfolder;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.inputpage);


        etPos = (EditText) findViewById(R.id.etpos);
        bmodel = (Button) findViewById(R.id.bModel);

        bmodel.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        switch(v.getId()){
        case R.id.bModel:


            String check = etPos.getText().toString();

            String check1 = etNs.getText().toString();
            n = Integer.parseInt(check);
            Intent openAlternative = new Intent("com.integrated.mpr.ALTERNATIVE");
            startActivity(openAlternative);


            break;
        }

    }
}

If i first install my app , and enter value in the edittext as 2 , the value of n =2 ; If second time i run my app without installing it , even if i enter 3 in the edittext , value of n remains 2 Where is the twist??

kumar piyush
  • 173
  • 2
  • 6
  • 15
  • It stays the same after you click on the button? – Barak Jun 09 '12 at 12:18
  • Exactly .. even if i press the button , go the next activity and then press the back button of emulator , and then re-enter the value in edittext , eben then it stays the same – kumar piyush Jun 09 '12 at 12:19
  • Reinitialize the variable the application first activity's onCreate function ? – Dheeresh Singh Jun 09 '12 at 12:27
  • also check that you extract the value from the correct view... verify that the XML view id is the same one you use in the code to read the value... – TacB0sS Jun 09 '12 at 12:47
  • I am sure of that.. checked it – kumar piyush Jun 09 '12 at 12:49
  • Then without debugging your project I cannot say for sure... I'm pretty positive your code should work! – TacB0sS Jun 09 '12 at 12:50
  • U may check this behaviour of static variables urself , just get an edit text and a button and print the value in logcat , i checked it , it doesnt work – kumar piyush Jun 09 '12 at 12:53
  • The rar your project and place a link here for me to download it, I'll debug it and tell you what is wrong... – TacB0sS Jun 09 '12 at 12:55
  • i m new to stackoverflow .. how do i post a rar link? can i mail the file to you? would be easier – kumar piyush Jun 09 '12 at 13:00
  • put in your public folder of drop box or somewhere in your google drive, and post a link to it... – TacB0sS Jun 09 '12 at 13:06
  • 2
    and after you are done with this, check this out: http://nu-art-software-development-tips.blogspot.co.il/2012/04/android-and-singleton-pattern.html – TacB0sS Jun 09 '12 at 13:07
  • +1 for the link. Absolutely true in every way. Luckily, the Application object IS a Singleton, but its a tightly VM managed Singleton. :) AND it counts as a Context. Another plus. You just don't want to use it for instance related data, if you can avoid it. Its great for holding application-wide data not related to instances, though. – Fuzzical Logic Jun 10 '12 at 20:04

1 Answers1

2

Kumar,

The behavior you are seeing is the result of using a static member. static members do not require an instance and are therefore set upon first access (regardless of whether an instance was created or not) and stays in memory until Android decides it is no longer valid. In essence, it is doing exactly what it was supposed to. The proper use of static variables is a topic of extensive discussion among veteran and novice programmers alike, but essentially always leads to "be choosy about where and how you use static members".

That said, your need to access this from another component is a common problem, however, and there are a number of ways to solve it. If you need to have each instance have a different value, then it should not be static. Instead you will have to find a way to pass the instance of the Activity.

If each instance need not be different, but the value need to change according to some other parameter, simply find the appropriate place to change the value. If you can access it from anywhere in your application, you may also change it from anywhere in your application.

Solution 1: Passing by Intent

This solution is useful when the information is subject to change and must be sent to another component and the classes that it uses exlusively. You may pass virtually any value via an Intent extra.

openAlternative.putExtra("MyValue", Integer.parseInt(check));

In your responding component, you may retrieve the value by:

Intent myIntent = getIntent();
int n = myIntent.getIntExtra("MyValue", 0); //0 is the default if no value is sent.

From here, you may easily pass the retrieved value to any class being utilized by that component. An example:

MyClass.setN(n);

Solution 2: Storing outside of the LifeCycle

A safer alternative is to move the value to an extended Application. This is not subject to UI or LifeCycle processing.

public class MyApplication extends Application
{
    static int n;
}

Adjust your AndroidManifest.xml...

<application android:name=".MyApplication" ... >
    <!-- All of your components -->
</application>

Now, you can set the variable this way:

MyApplication.n = Integer.parseInt();

And you can get it by

int myN = MyApplication.n;

This solution has gotten me through many a troubled day. However, it should really be used for non-instance related data.

Solution 3: The REALLY UNSAFE method

This solution only works if you can guarantee a single instance of the component. This requires that singleTask is set. Be very careful with this

Change n to non-static

int n;

Change Activity to Singleton

static private Model myInstance;

In OnCreate, set myInstance

myInstance = this;

Create a getter:

static public Model getStaticInstance()
{   
    return myInstance;
}

This is unreliable (at best) and can cause huge memory leaks if not managed correctly.

Hope this helps,

FuzzicalLogic

Fuzzical Logic
  • 12,947
  • 2
  • 30
  • 58
  • A nicely documented answer , but whats the way out when i have to access the variables inside different activites and intents can't be used , when it is used inside classes that are not activities – kumar piyush Jun 09 '12 at 12:32
  • How come you would say it does what it suppose to? assuming that the view id clicked is the right one, and that both assignment and reading the value of the static field are performed on the main thread, the value should be changed! other wise the field should be volatiled – TacB0sS Jun 09 '12 at 12:32
  • @TacB0sS: You are correct. Except we don't know the field hasn't changed. The code that has been shown is only how it is transmitted, not received. That is, since an Intent is being called, we can't guarantee that it is even checking for the new value. This is because the intent may be pointing to something that is already running – Fuzzical Logic Jun 09 '12 at 12:35
  • I think u guys should check it yourself , create a static variable , assign it a value and then restart the app without reinstalling , the value wont be changed – kumar piyush Jun 09 '12 at 12:35
  • @kumarpiyush I use a number of static variables (very carefully). They all change, but when the activity/service/etc reads the change is depending on the application component and where I put the read. This can sometimes mean... eventually.... – Fuzzical Logic Jun 09 '12 at 12:37
  • I've done this multiple times, and found it to be the wrong way to preserve data, eventually it caused me tremendous over work, to re-factor this static bugger, into the instances. – TacB0sS Jun 09 '12 at 12:38
  • @TacB0sS: Exactly my point. Because of the LifeCycles, etc... you can just never be sure when these things will be registered by other components/classes even in the same application. You have to be so choosy... – Fuzzical Logic Jun 09 '12 at 12:40
  • if it is any comfort, I still see this mistake with many veteran developers... :( – TacB0sS Jun 09 '12 at 12:40
  • Personally, I use statics for app-level state only anymore. Preferences, for example tend to be app-wide and not subject to too much change. – Fuzzical Logic Jun 09 '12 at 12:41
  • I'll post an alternative or two, but give me a few minutes to type up some code. – Fuzzical Logic Jun 09 '12 at 12:42
  • It should work... try to add 'volatile' to n - DID the volatile worked? – TacB0sS Jun 09 '12 at 12:42
  • Should i store all the values that are to be used and return them whenever they are to be used – kumar piyush Jun 09 '12 at 12:43
  • the question is not if you should... but where and how to save them? That depends on your project architecture – TacB0sS Jun 09 '12 at 12:45
  • so you have a setup problem, you get your value from the wrong view... that would be my guess – TacB0sS Jun 09 '12 at 12:48
  • @FuzzicalLogic i wil have a look at solution 2 , wil check it sometime later – kumar piyush Jun 09 '12 at 13:04
  • @FuzzicalLogic I was going through solution 2, can the variables can only be set values inside the class that extends the application?? – kumar piyush Jun 10 '12 at 12:13
  • 1
    The variable may be SET from anywhere that has access to it. But it is instantaneous and not affected by LifeCycle. It simply must be DECLARED in the class that extends Application – Fuzzical Logic Jun 10 '12 at 12:29