2

I have two activities, my MainActivity runs TimerTask which increments "counter" value.

public class MainActivity extends AppCompatActivity {

    public static int counter = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final Handler handler = new Handler();

        Timer timer = new Timer();
        TimerTask timerTask = new TimerTask() {
            public void run() {
                handler.post(new Runnable() {
                    public void run() {
                        counter++;
                    }
                });
            }
        };

        timer.schedule(timerTask, 0, 1000);

        Intent intent = new Intent(this, MapActivity.class);
        startActivity(intent);
    }
}

My MapActivity is supposed to read this value upon button click.

public class MapActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_map);
    }

    public void readCounter(View view){
        Log.d("counter:", Integer.toString(MainActivity.counter));
    }
}

Currently counter is declared as public static variable but since static variables are bad practice, what would be proper and elegant way to do it?

Michał Witanowski
  • 602
  • 3
  • 8
  • 22
  • Seems to be answered here, `Intent` should be used: http://stackoverflow.com/a/7325248/6911095 – ldz Oct 05 '16 at 19:16
  • and it is better if you call timer.cancel() when u re done. Because it will keep running in the background – ugur Oct 05 '16 at 19:19
  • I think I didn't make myself clear, I want timer to be running and i want to read constantly updated value of counter. So in this case Intent won't work. – Michał Witanowski Oct 05 '16 at 19:32
  • Aha ok now I got ur point and updated my answer accordingly – ugur Oct 05 '16 at 20:41

2 Answers2

1

Bundles are used to add extra parameters to pass to the called activity. So you can get and use this extra parameter as you wish.

Here is how to do it:

in MainActivity:

Intent intent = new Intent(this, MapActivity.class);
intent.putExtra("counter", counter);  
startActivity(intent);

in MapActivity:

Bundle extras = getIntent().getExtras(); 
int counter = extras.getIntExtra("counter");

EDIT 1: For continuous update use custom listener interface

public class MainActivity extends AppCompatActivity {

    public static int counter = 0;
    private MyCounterUtil util;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final Handler handler = new Handler();

        util = MyCounterUtil.getInstance();


        Timer timer = new Timer();
        TimerTask timerTask = new TimerTask() {
            public void run() {
                handler.post(new Runnable() {
                    public void run() {
                        counter++;
                        util.notifyUpdate(counter);
                    }
                });
            }
        };

        timer.schedule(timerTask, 0, 1000);

        Intent intent = new Intent(this, MapActivity.class);
        startActivity(intent);
    }

}

Create this class

public class MyCounterUtil {

private static MyCounterUtil mInstance;
private MyCounterListener mListener;

private MyCounterUtil() {}

public static MyCounterUtil getInstance() {
        if(mInstance == null) {
            mInstance = new MyCounterUtil();
        }
        return mInstance;
    }


 public void setListener(MyCounterListener listener) {
        mListener = listener;
    }

private void notifyUpdate(int count) {
    if(mListener != null)
        mListener.onUpdate(count);
    }

public interface MyCounterListener{

      public void onUpdate(int count);

  }
}

Implement listener interface in MapActivity

public class MapActivity extends AppCompatActivity implements MyCounterListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_map);

        MyCounterUtil.getInstance().setListener(this);
    }
/*
    public void readCounter(View view){
        Log.d("counter:", Integer.toString(MainActivity.counter));
    }
*/
    @Override
    public void onUpdate(int count){
       Log.d("counter:", Integer.toString(count));
    }

}

EDIT 2: Another clean and simple approach without TimerTask is using system time as counter and pass its first value with intent or sharedpreferences.

in MainActivity

public class MainActivity extends AppCompatActivity {


        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

/*
            SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
            SharedPreferences.Editor editor = preferences.edit();
            editor.putLong("startTime", System.currentTimeMillis());
            editor.apply();
      */

            Intent intent = new Intent(this, MapActivity.class);
            intent.putExtra("startTime", System.currentTimeMillis()); 
            startActivity(intent);
        }

    }

in MapActivity:

public class MapActivity extends AppCompatActivity {

    private long startTime;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_map);
        /* in case use of sharedpref        
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
        startTime = preferences.getLong("startTime", 0);
        */

        //in case use of bundle
        startTime = getIntent().getExtras().getLongExtra("startTime", 0);

    }

    public void readCounter(View view){
        long counter = (System.currentTimeMillis() - startTime)/1000;
        Log.d("counter:", "" + counter);
    }

}
ugur
  • 3,604
  • 3
  • 26
  • 57
1

There's nothing wrong with static values. In face if you want to make it MVC and use model, you should probably wrap this value with a Singleton Model class.

But to simplify things I would only recommend to make sure you reset the value on MainActivity onCreate.

The android way to do it would be using services or startActivityForResult.

Ilya Gazman
  • 31,250
  • 24
  • 137
  • 216
  • I guess startactivityforresult has nothing to do here. it is useful when u call another activity and return with some result. but here it requires passing data to another activity, i.e. one way – ugur Oct 05 '16 at 19:22
  • 1
    @uguboz You are correct! I mentioned it just in case OP can use it, you never know... – Ilya Gazman Oct 05 '16 at 19:35