问题
I have written a program in which I am using Timer
and controlling that timer using Toggle
states.
Toggle's
default state is OFF
, once I make changes in toggle state from OFF
to ON
Timer
starts, and when I again change to OFF
it stops the Timer
as per requirement.
But problem starts when my Timer
is ON
and I switch to other activity and then again come back
to ToggleActivity
and then do changes in toggle state from ON
to OFF
- it still runs Timer
...
Note: when I use finish()
or back
press, in place of Intent
to come back to ToggleActivity
everything works fine, but when I use Intent
facing such issues..
ToggleActivity.java:
public class ToggleActivity extends Activity implements OnCheckedChangeListener {
ToggleButton toggleButton;
TextView text;
Timer timer;
TimerTask timerTask;
final Handler handler = new Handler();
Button btnSwitchActivity;
boolean toggleState;
SharedPreferences sharedPreferences;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_toggle);
toggleButton = (ToggleButton) findViewById(R.id.toggleButton);
text = (TextView) findViewById(R.id.textView1);
btnSwitchActivity = (Button) findViewById(R.id.btnSwitchActivity);
sharedPreferences = getApplicationContext().getSharedPreferences("toggleState",0);
btnSwitchActivity.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intentSwitchActivity = new Intent(ToggleActivity.this, SwitchActivity.class);
startActivity(intentSwitchActivity);
}
});
}
@Override
public void onCheckedChanged(CompoundButton arg0, boolean isChecked) {
if(isChecked)
{
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putBoolean("toggleState", true);
editor.commit();
text.setText("ON");
startTimer();
} else
{
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putBoolean("toggleState", false);
editor.commit();
text.setText("OFF");
if (timer != null) {
timer.cancel();
timer = null;
}
}
}
public void startTimer() {
timer = new Timer();
initializeTimerTask();
timer.schedule(timerTask, 1000, 5000);
}
public void stoptimertask(View v) {
if (timer != null) {
timer.cancel();
timer = null;
}
}
public void initializeTimerTask() {
timerTask = new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
Calendar calendar = Calendar.getInstance();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd:MMMM:yyyy HH:mm:ss a");
final String strDate = simpleDateFormat.format(calendar.getTime());
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(getApplicationContext(), strDate, duration);
toast.show();
}
});
}
};
}
public void onResume() {
super.onResume();
toggleState = sharedPreferences.getBoolean("toggleState", false);
Log.v("toggleState", Boolean.toString(toggleState));
if (toggleState) {
toggleButton.setChecked(true);
text.setText("ON");
} else {
toggleButton.setChecked(false);
text.setText("OFF");
}
toggleButton.setChecked(toggleState);
toggleButton.setOnCheckedChangeListener(this);
}
@Override
protected void onPause() {
super.onPause();
toggleButton.setOnCheckedChangeListener(null);
}
}
SwitchActivity.java
public class SwitchActivity extends Activity {
Button btnToggleActivity;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_switch);
btnToggleActivity = (Button) findViewById(R.id.btnToggleActivity);
btnToggleActivity.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent(SwitchActivity.this, ToggleActivity.class);
startActivity(intent);
/**
* if i use finish instead of Intent to switch to ToggleActivity
* my Timer works fine
*/
// finish
}
});
}
}
activity_toggle.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:gravity="center"
android:background="#ffffff"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context=".ToggleActivity" >
<ToggleButton
android:id="@+id/toggleButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/toggle_selector"
android:checked="false"
android:text=""
android:textOff=""
android:textOn="" />
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginBottom="20dp"
android:text="@string/string_toggle_off"
android:textAppearance="?android:attr/textAppearanceMedium" />
<Button
android:id="@+id/btnSwitchActivity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/string_btn_switch"/>
</LinearLayout>
activity_switch.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:background="#ffffff"
android:orientation="vertical" >
<Button
android:id="@+id/btnToggleActivity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/string_btn_goback"
/>
</LinearLayout>
回答1:
"But problem starts when my Timer is ON and I switch to other activity and then again come back to Toggle activity"...
You DO not come back. As @Fabin Paul mentioned you just create a new instance of ToggleActivity
. So in the scenario when you launch the app, then move to SwitchActivity
and back by clicking the button, the back stack looks as follows:
ToggleActivity(1) -> SwitchActivity -> ToggleActivity(2)
"...and then do changes in toggle state from ON to OFF - it still runs Timer..."
You switch off the timer of the second instance of ToggleActivity. The one that is running belongs to the first ToggleActivity's instance.
"when I use finish(); or back press, in place of Intent to come back to ToggleActivity everything works fine..."
Yes, it does, because you don't create the second instance of ToggleActivity
and your logic works correctly.
The easiest way to get the desired behavior is to add android:launchMode="singleInstance" to the ToggleActivity's tag of the manifest.
回答2:
I guess the problem is because for each instance of activity an instance of timer is created. So when you press stop only one instance of timer is stopped while the background activity's timer instance is not stopped.
I got around the problem by making timer static
static Timer timer;
and starting only one instance of the timer
public void startTimer() {
if (timer == null) {
timer = new Timer();
initializeTimerTask();
timer.schedule(timerTask, 1000, 5000);
}
}
I hope it helps...
回答3:
When the ToggleActivity
switches to onPause
state, it doesn't cancel the running Timer
. You need to cancel it manually.
You can add the following code snippet within your onPause()
method:
if (timerTask != null)
timerTask.cancel();
if (timer != null) {
timer.cancel();
timer = null;
}
回答4:
here you are calling setChecked(true)
means onCheckedChangeListener
will call,then updating the preference also, you have to remove the listener and set listener to the toggle button,like this:
toggleMap.setOnCheckedChangeListener(null);
toggleMap.setChecked(isChecked);
toggleMap.setOnCheckedChangeListener(this);
EDIT
@Override
protected void onResume() {
super.onResume();
tg1pref = preferences.getBoolean("tg1pref", false);
toggleMap.setOnCheckedChangeListener(null);
toggleMap.setChecked(tg1pref);
toggleMap.setOnCheckedChangeListener(this);
if (!tg1pref) {
if (timer != null) {
timer.cancel();
timer = null;
}
}
}
and
@Override
protected void onPause() {
toggleMap.setOnCheckedChangeListener(null);
super.onPause();
}
回答5:
Assign the listener to the toggle button after checking the state.
Just remove:
toggleMap.setOnCheckedChangeListener(this);
line in onCreate
and add the same line in onResume
after updating the status.
toggleMap.setOnCheckedChangeListener(this);
and in onPause()
:
toggleMap.setOnCheckedChangeListener(null);
like this:
@Override
protected void onResume() {
super.onResume();
tg1pref = preferences.getBoolean("tg1pref", false);
if (!tg1pref) {
if (timer != null) {
timer.cancel();
timer = null;
}
}
toggleMap.setChecked(tg1pref);
toggleMap.setOnCheckedChangeListener(this);
}
and:
@Override
protected void onPause() {
super.onPause();
toggleMap.setOnCheckedChangeListener(null);
}
来源:https://stackoverflow.com/questions/28061651/handle-togglebutton-in-onresume