替换片段保存AsyncTask后从Bundle获取正确的值

时间:2014-01-17 17:59:34

标签: android android-fragments android-asynctask bundle

我遇到的问题是我创建了一个简单的倒计时器,使用AsyncTasks并使用SetRetainInstance(true)确保即使更改了ui上的计数器更新

问题是我有一个editText给我定时器的值,然后应该将它们传递给任务倒计时。我必须在某处遗漏某些东西,因为我似乎无法获得新的价值。

这是我用作片段的代码:

    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.ionCreate,开始,预执行和后执行等多个位置设置了 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

以下来自logcat的摘录显示,某些值显示输入的文本,但start和preexecute保留旧值:

    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();
            }
        }
    }

我也使用Bundle将文本从EditText传输到片段,并使用getString()根据键获取值。

到目前为止,下面是MainActivity。

AsyncTask

我知道该值正在传递给片段,但我不确定AsyncTask或片段是否被替换或刷新。我想要的理想情况是使用Bundle中的新值来杀死{{1}}并创建一个新的。

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

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

感谢发声板。

问候

cchinchoy