2013-02-27 69 views
0

我正在做一个活动来衡量需要多长时间一个人做一个练习,但它有一个我还不能解决的错误...该变量的值已突然设置为0

TrainingFragment显示用户可点击的练习列表,然后我的ExerciseActivity启动并运行,直到变量“remainingsSets”设置为0.

当我在第一次点击任何练习时,一切正常很好,ExerciseActivity可以正确地结束返回到TrainingFragment。但是,如果我尝试点击另一个练习,ExerciseActivity就会关闭。我可以看到变量“remainingSets”带有它的正确值(remainingSets = getIntent().getIntExtra("remaining_sets", 3)),但是当单击startButton时,我不知道为什么变量“remainingSets”被设置为0,然后活动已关闭,因为此条件:if (remainingSets > 0){...}

这里是我的TrainingFragment:

public class TrainingFragment extends Fragment { 

private final static int START_EXERCISE = 1; 

private Training training; 
private String lastItemClicked; 
private String[] values; 

@Override 
public void onAttach(Activity activity) { 
    super.onAttach(activity); 

    Bundle bundle = getArguments(); 
    if (bundle != null) { 
     training = bundle.getParcelable("training"); 
    } 
} 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    return (ScrollView) inflater.inflate(R.layout.template_exercises, container, false); 
} 

@Override 
public void onActivityCreated(Bundle savedInstanceState) { 
    super.onActivityCreated(savedInstanceState); 

    LinearLayout exercisesContainer = (LinearLayout) getView().findViewById(R.id.exercises); 
    LayoutInflater inflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 

    List<Exercise> exercises = training.getExercises(); 
    values = new String[exercises.size()]; 

    if (savedInstanceState != null) { 
     values = savedInstanceState.getStringArray("values"); 
    } 

    for (int i = 0; i < exercises.size(); i++) { 
     final View exerciseView = inflater.inflate(R.layout.template_exercise, null); 

     exerciseView.setTag(String.valueOf(i)); 

     TextView remainingSets = (TextView) exerciseView.findViewById(R.id.remaining_sets); 

     if (savedInstanceState != null) { 
      remainingSets.setText(values[i]); 
     } else { 
      String sets = exercises.get(i).getSets(); 
      remainingSets.setText(sets); 
      values[i] = sets; 
     } 

     exerciseView.setOnClickListener(new OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       Intent intent = new Intent(getActivity(), ExerciseActivity.class); 
       intent.putExtra("remaining_sets", 
         Integer.valueOf(((TextView) v.findViewById(R.id.remaining_sets)).getText().toString())); 

       lastItemClicked = v.getTag().toString(); 

       startActivityForResult(intent, START_EXERCISE); 
      } 
     }); 

     exercisesContainer.addView(exerciseView); 
    } 
} 

@Override 
public void onSaveInstanceState(Bundle outState) { 
    super.onSaveInstanceState(outState); 
    outState.putStringArray("values", values); 
} 

@Override 
public void onActivityResult(int requestCode, int resultCode, Intent data) { 
    super.onActivityResult(requestCode, resultCode, data); 

    View view = ((LinearLayout) getView().findViewById(R.id.exercises)).findViewWithTag(lastItemClicked); 

    if (requestCode == START_EXERCISE) { 
     if (resultCode == Activity.RESULT_OK) { // the exercise had been 
               // finished. 
      ((TextView) view.findViewById(R.id.remaining_sets)).setText("0"); 

      view.setClickable(false); 

      values[Integer.valueOf(lastItemClicked)] = "0"; 

     } else if (resultCode == Activity.RESULT_CANCELED) { 

      String remainingSets = data.getStringExtra("remaining_sets"); 
      ((TextView) view.findViewById(R.id.remaining_sets)).setText(remainingSets); 

      values[Integer.valueOf(lastItemClicked)] = remainingSets; 
     } 
    } 
} 
} 

我ExerciseActivity:

public class ExerciseActivity extends Activity { 

private Chronometer chronometer; 
private TextView timer; 
private Button startButton; 
private Button endButton; 
private int remainingSets; 

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

    ExerciseEvents.addExerciseListener(new PopupExerciseListener()); 

    chronometer = (Chronometer) findViewById(R.id.exercise_doing_timer); 
    timer = (TextView) findViewById(R.id.timer); 

    startButton = (Button) findViewById(R.id.start_exercise); 
    startButton.setOnClickListener(new OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      ExerciseEvents.onExerciseBegin(); 
     } 
    }); 

    endButton = (Button) findViewById(R.id.end_exercise); 
    endButton.setOnClickListener(new OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      ExerciseEvents.onExerciseRest(); 
     } 
    }); 
} 

@Override 
public void onBackPressed() { 
    Intent intent = new Intent(); 
    intent.putExtra("remaining_sets", String.valueOf(remainingSets)); 
    setResult(RESULT_CANCELED, intent); 

    super.onBackPressed(); 
} 

public class PopupExerciseListener implements ExerciseListener { 

    public PopupExerciseListener() { 
     remainingSets = getIntent().getIntExtra("remaining_sets", 3); 
    } 

    @Override 
    public void onExerciseBegin() { 
     if (remainingSets > 0) { 
      chronometer.setVisibility(View.VISIBLE); 
      timer.setVisibility(View.GONE); 

      chronometer.setBase(SystemClock.elapsedRealtime()); 
      chronometer.start(); 

      startButton.setVisibility(View.GONE); 
      endButton.setVisibility(View.VISIBLE); 
     } else { 
      ExerciseEvents.onExerciseFinish(); 
     } 
    } 

    @Override 
    public void onExerciseFinish() { 
     setResult(RESULT_OK); 

     finish(); 
    } 

    @Override 
    public void onExerciseRest() { 
     chronometer.setVisibility(View.GONE); 
     endButton.setVisibility(View.GONE); 
     timer.setVisibility(View.VISIBLE); 

     long restTime = getIntent().getLongExtra("time_to_rest", 60) * 1000; 
     new CountDownTimer(restTime, 1000) { 

      @Override 
      public void onTick(long millisUntilFinished) { 
       timer.setText(String.valueOf(millisUntilFinished/1000)); 
      } 

      @Override 
      public void onFinish() { 
       ExerciseEvents.onExerciseBegin(); 
      } 
     }.start(); 

     remainingSets--; 
    } 
} 
} 

而且我ExerciseEvents:

public class ExerciseEvents { 

private static LinkedList<ExerciseListener> mExerciseListeners = new LinkedList<ExerciseListener>(); 

public static void addExerciseListener(ExerciseListener listener) { 
    mExerciseListeners.add(listener); 
} 

public static void removeExerciseListener(String listener) { 
    mExerciseListeners.remove(listener); 
} 

public static void onExerciseBegin() { 
    for (ExerciseListener l : mExerciseListeners) { 
     l.onExerciseBegin(); 
    } 
} 

public static void onExerciseRest() { 
    for (ExerciseListener l : mExerciseListeners) { 
     l.onExerciseRest(); 
    } 
} 

public static void onExerciseFinish() { 
    for (ExerciseListener l : mExerciseListeners) { 
     l.onExerciseFinish(); 
    } 
} 

public static interface ExerciseListener { 

    public void onExerciseBegin(); 

    public void onExerciseRest(); 

    public void onExerciseFinish(); 
} 
} 

任何人都可以给我任何帮助吗?

+0

你在哪里阅读''remaining_sets“',你在哪里关闭你的活动?也张贴这个代码。 – Sam 2013-02-27 21:35:31

+0

你说它只发生在第一次后..所以,你第一次运行你做你的设置和倒计数到0 ..你remainingSets现在在0.你再次点击开始..因为你不重置remainingSets到3 ,它会变成0并关闭你的应用程序。 – dymmeh 2013-02-27 21:36:06

+0

通过查看代码很难弄清楚。在'remainingSets'被分配或修改的每个地点放置一个断点。这可能会告诉你为什么它被设置为0或为什么它达到0. – 2013-02-27 21:37:58

回答

1

你更新你的代码后,我看到你在你的代码有一个很大的内存泄漏:

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

    ExerciseEvents.addExerciseListener(new PopupExerciseListener()); 
    .... 
} 

呼叫ExerciseEvents.addExerciseListener(new PopupExerciseListener())增加了一个新的PopupExerciseListener静态/全局列表:ExcerciseEvents.mExerciseListeners。由于PopupExerciseListener是内部类,因此它隐含地引用了其内部的ExcerciseActivity。这意味着你的代码永远持有每个ExcerciseActivity的实例。不好。

这也可以解释你看到的怪异行为。当调用其中一个onExcersizeXXX()方法时,它将调用链接列表中的所有ExcerciseListeners,前一个屏幕和当前屏幕中的ExcerciseListener。

在ExcerciseActivity.java试试这个:

.... 
ExerciseListener mExerciseListener; 
.... 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    .... 
    .... 
    mExerciseListener = new PopupExerciseListener() 
    ExerciseEvents.addExerciseListener(mExerciseListener); 
    .... 
    .... 
} 

@Override 
protected void onDestroy() { 
    ExerciseEvents.removeExerciseListener(mExerciseListener); 
    super.onDestroy(); 
} 

.... 

onDestroy,你注销你的听众,防止内存泄漏和防止奇数倍回调附加到不再存在的活动PopupExerciseListeners。

+0

就是这样!有效! \ o/ 非常感谢你,伙计! – mvalencaa 2013-02-28 20:22:40