2014-01-17 24 views
0

我遇到的问题是我创建了一个简单的倒数计时器,使用AsyncTasks并使用SetRetainInstance(true)确保即使方向更改,计数器更新ui更换片段后,从包中获取正确的值AsyncTask

问题是我有一个editText,它为我提供了定时器的值,然后应该将它们传递给Task以向下计数。我必须在某处丢失某些东西,因为我似乎无法获得新的价值。

这是我使用的片段代码:

package com.example.app; 

    import android.app.Activity; 
    import android.os.AsyncTask; 
    import android.os.Bundle; 
    import android.os.SystemClock; 
    import android.support.v4.app.Fragment; 
    import android.util.Log; 

    public class TaskFragment extends Fragment { 
private static final String TAG = TaskFragment.class.getSimpleName(); 
String i; 
int counter; 
Bundle bundle; 
static interface TaskCallbacks { 
    public void onPreExecute(); 
    public void onProgressUpdate(int timer); 
    public void onCancelled(); 
    public void onPostExecute(); 
} 
private TaskCallbacks mCallbacks; 
private DummyTask mTask; 
private boolean mRunning; 
@Override 
public void onAttach(Activity activity) { 
    super.onAttach(activity); 
    if (!(activity instanceof TaskCallbacks)) { 
     throw new IllegalStateException("Activity must implement the TaskCallbacks interface."); 
    } 
    mCallbacks = (TaskCallbacks) activity; 
} 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setRetainInstance(true); 
    bundle=getArguments(); 
    i = bundle.getString("SecValue"); 
    Log.i("VertygoEclypse - TaskFragment-onCreate", i); 
    counter=Integer.parseInt(i); 
} 
@Override 
public void onDestroy() { 
    super.onDestroy(); 
    cancel(); 
} 
public void start() { 
    if (!mRunning) { 
     bundle=getArguments(); 
     i=bundle.getString("SecValue"); 
     mTask = new DummyTask(); 
     Log.i("VertygoEclypse - TaskFragment - start", i); 
     mTask.execute(); 
     mRunning = true; 
    } else{ 
     mTask.cancel(true); 
    } 
} 
public void cancel() { 
    if (mRunning) { 
     mTask.cancel(true); 
     mTask = null; 
     mRunning = false; 
    } 
} 
public boolean isRunning() { 
    return mRunning; 
} 
private class DummyTask extends AsyncTask<Void, Integer, Void> { 
    @Override 
    protected void onPreExecute() { 
     mCallbacks.onPreExecute(); 
     mRunning = true; 
     counter=Integer.parseInt(i); 
     Log.i("Vertygo Eclypse - AsyncTask - onPreExecute", i); 
    } 
    @Override 
    protected Void doInBackground(Void... ignore) { 
     do { 
      publishProgress(counter); 
      SystemClock.sleep(1000); 
      counter=counter-1; 
      if(isCancelled()){ 
       mTask.cancel(true); 
       break; 
      } 
     } while (counter>0); 
      return null; 
    } 
    @Override 
    protected void onProgressUpdate(Integer... timer) { 
     mCallbacks.onProgressUpdate(timer[0]); 
    } 
    @Override 
    protected void onCancelled() { 
     mCallbacks.onCancelled(); 
     mRunning = false; 
    } 
    @Override 
    protected void onPostExecute(Void ignore) { 
     mCallbacks.onPostExecute(); 
     mRunning = false; 
      } 
     } 
    } 

话虽这么说,我有Log.i在多个点的onCreate,开始时设置的,预执行和后执行。

从logcat的以下摘录显示了一些值显示输入的文本,但启动和preexecute持有旧值:

01-17 17:37:12.383 10261-10261/com.example.app I/VertygoEclypse - replaceFrag﹕ 35 
    01-17 17:37:12.383 10261-10261/com.example.app I/VertygoEclypse - replaceFrag﹕ 35 
    01-17 17:37:12.383 10261-10261/com.example.app I/Vertygo Eclypse - MainActivity - replaceFrag﹕ 35 
    01-17 17:37:12.403 10261-10261/com.example.app I/VertygoEclypse - TaskFragment-onCreate﹕ 35 
    01-17 17:37:17.247 10261-10261/com.example.app I/VertygoEclypse - TaskFragment - start﹕ 15 
    01-17 17:37:17.259 10261-10261/com.example.app I/Vertygo Eclypse - AsyncTask - onPreExecute﹕ 15 

我也是用捆绑到文本,从一个转移编辑文本到片段并使用getString()获取基于键的值。

以下是MainActivity到目前为止。

package com.example.app; 

    import android.annotation.TargetApi; 
    import android.os.Build; 
    import android.os.Bundle; 
    import android.support.v4.app.FragmentActivity; 
    import android.support.v4.app.FragmentManager; 
    import android.support.v4.app.FragmentTransaction; 
    import android.util.Log; 
    import android.view.Menu; 
    import android.view.MenuItem; 
    import android.view.View; 
    import android.view.View.OnClickListener; 
    import android.widget.Button; 
    import android.widget.EditText; 
    import android.widget.ProgressBar; 
    import android.widget.TextView; 
    import android.widget.Toast; 

    import java.util.concurrent.TimeUnit; 

    public class MainActivity extends FragmentActivity implements TaskFragment.TaskCallbacks { 
private static final String TAG = MainActivity.class.getSimpleName(); 
private static final String KEY_CURRENT_PROGRESS = "current_progress"; 
private static final String KEY_PERCENT_PROGRESS = "percent_progress"; 
private static final String TIME_COUNT = "time_count"; 
private TaskFragment mTaskFragment; 
private ProgressBar mProgressBar; 
private TextView mPercent, tv1; 
private Button mButton; 
private EditText secentered; 
public String sample; 
Bundle bundl; 
@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    tv1 = (TextView) findViewById(R.id.textView1); 
    secentered = (EditText) findViewById(R.id.valueentered); 
    mButton = (Button) findViewById(R.id.task_button); 
    initialfrag(); 
    mButton.setOnClickListener(new OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      if (mTaskFragment.isRunning()) { 
       mButton.setText("Start"); 
       mTaskFragment.cancel(); 
       replaceFrag(); 
      } else { 
       mButton.setText("Cancel"); 
       mTaskFragment.start(); 
      } 
     } 
    }); 
    if (savedInstanceState != null) { 
      tv1.setText(savedInstanceState.getString(TIME_COUNT)); 
    } 
} 
@Override 
public void onSaveInstanceState(Bundle outState) { 
    super.onSaveInstanceState(outState); 
     outState.putString(TIME_COUNT, tv1.getText().toString()); 
} 
@Override 
public void onPreExecute() { 
    mButton.setText(getString(R.string.cancel)); 
    Toast.makeText(this, R.string.task_started_msg, Toast.LENGTH_SHORT).show(); 
} 
@Override 
public void onProgressUpdate(int timer) { 
    long timelong = timer*1000; 
    String tval = getDurationBreakdown(timelong); 
    tv1.setText(tval); 
} 
@Override 
public void onCancelled() { 
    mButton.setText(getString(R.string.start)); 
    tv1.setText("0 seconds"); 
    mTaskFragment.cancel(); 
    replaceFrag(); 
    Toast.makeText(this, R.string.task_cancelled_msg, Toast.LENGTH_SHORT).show(); 
} 
@Override 
public void onPostExecute() { 
    mButton.setText(getString(R.string.start)); 
    tv1.setText("Completed"); 
    mTaskFragment.cancel(); 
    replaceFrag(); 
    Toast.makeText(this, R.string.task_complete_msg, Toast.LENGTH_SHORT).show(); 
} 
@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    getMenuInflater().inflate(R.menu.main, menu); 
    return true; 
} 
@TargetApi(Build.VERSION_CODES.HONEYCOMB) 
@Override 
public boolean onOptionsItemSelected(MenuItem item) { 
    switch (item.getItemId()) { 
     case R.id.menu_trigger_config_change: 
      recreate(); 
      return true; 
    } 
    return super.onOptionsItemSelected(item); 
} 
public static String getDurationBreakdown(long secondstobreak) { 
    if(secondstobreak < 0) 
    { 
     throw new IllegalArgumentException("Duration must be greater than zero!"); 
    } 
    long hours = TimeUnit.MILLISECONDS.toHours(secondstobreak); 
    secondstobreak-=TimeUnit.HOURS.toMillis(hours); 
    long minutes = TimeUnit.MILLISECONDS.toMinutes(secondstobreak); 
    secondstobreak-=TimeUnit.MINUTES.toMillis(minutes); 
    long seconds = TimeUnit.MILLISECONDS.toSeconds(secondstobreak); 
    secondstobreak-=TimeUnit.SECONDS.toMillis(seconds); 
    StringBuilder sb = new StringBuilder(64); 
    if(hours<10){ 
     sb.append("0"+hours); 
    }else { 
     sb.append(hours); 
    } 
    sb.append(" : "); 
    if(minutes<10){ 
     sb.append("0"+minutes); 
    }else{ 
     sb.append(minutes); 
    } 
    sb.append(" : "); 
    if(seconds<10){ 
     sb.append("0"+seconds); 
    } else { 
     sb.append(seconds); 
    } 
    sb.append(" remaining"); 
    return (sb.toString()); 
} 
public void replaceFrag(){ 
    Bundle bundle = new Bundle(); 
    String tester2 = secentered.getText().toString(); 
    Log.i("VertygoEclypse - replaceFrag", tester2); 
    if(tester2.matches("")){ 
     bundle.putString("SecValue", "15"); 
    } else { 
     Log.i("VertygoEclypse - replaceFrag", tester2); 
    bundle.putString("SecValue", tester2); 
    } 
    FragmentTransaction rfm = getSupportFragmentManager().beginTransaction(); 
    rfm.remove(mTaskFragment); 
    rfm.detach(mTaskFragment); 
    TaskFragment mTaskFragment = new TaskFragment(); 
    Log.i("Vertygo Eclypse - MainActivity - replaceFrag", tester2); 
    mTaskFragment.setArguments(bundle); 
    rfm.add(mTaskFragment, "task").commit(); 
} 
public void initialfrag(){ 
    bundl = new Bundle(); 
    String tester = secentered.getText().toString(); 
    Log.i("VertygoEclypse - initialFrag", tester); 
    if(tester.matches("")){ 
     bundl.putString("SecValue", "15"); 
    } else{ 
     Log.i("VertygoEclypse - initialFrag", tester); 
    bundl.putString("SecValue", tester); 
    } 
     FragmentManager fm = getSupportFragmentManager(); 
    mTaskFragment = (TaskFragment) fm.findFragmentByTag("task"); 
    if (mTaskFragment == null) { 
     mTaskFragment = new TaskFragment(); 
     mTaskFragment.setArguments(bundl); 
     fm.beginTransaction().add(mTaskFragment, "task").commit(); 
      } 
     } 
    } 

我知道该值被传递给片段,但我不能肯定,如果AsyncTask或片段被替换或刷新。我想要的是理想情况是使AsyncTask死亡,并使用Bundle中的新值创建一个新的。

任何帮助将不胜感激。

+0

感谢格式艾格尼丝。 – cchinchoy

回答

0

好吧,似乎我偶然发现了答案。问题是int counter, validcounter;似乎没有在它前面的static,变量创建它自己的实例。所以用以下static int counter, validcounter;该问题得到解决。

感谢您的探测板。

问候

cchinchoy