The task is to write a listView with chronometers and when turning to save the state of each timer. But when I start the timer / timers and turn the screen, no matter what timer I start from, the first list item starts the report. It is not formally launched, but the report begins. Here is the code snippet:
public class MainActivity extends ActionBarActivity implements LoaderManager.LoaderCallbacks<Cursor>{ ListView listView; MyAdapter myAdapter; private final int LOADER_ID =1; SQLiteDatabase db; Bundle bundle; List<Long> lastPauseList; List<Integer> positionnList; List<Boolean> startList; List<Long> basesList; List<Long> tested; List<Long> elapsed; List<Tracker> trackerList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bundle = savedInstanceState; db = RemindMe.db; trackerList = Tracker.getListAll(db); String[] from = {Tracker.COL_NAME,Tracker.COL_ELAPSED_TIME}; int[]to={R.id.row_name,R.id.row_chronometer}; startList = new ArrayList<Boolean>(trackerList.size()); lastPauseList = new ArrayList<Long>(trackerList.size()); for (int i = 0; i <trackerList.size() ; i++) { startList.add(false); lastPauseList.add((long)0); } if(bundle!=null) { for (int i = 0; i < trackerList.size(); i++) { startList.set(i,savedInstanceState.getBoolean("start " + i)); lastPauseList.set(i,bundle.getLong("lastPause "+i)); Log.d("myTag", "OnCreate-----------------------------------------"); Log.d("myTag", "position " + i); Log.d("myTag", "elapsedTime "+ getTime(savedInstanceState.getLong("elapsedTime " + i))); Log.d("myTag", "base " + getTime(savedInstanceState.getLong("base " + i))); Log.d("myTag", "lastPause "+ getTime(savedInstanceState.getLong("lastPause "+i))); Log.d("myTag", "start "+ savedInstanceState.getBoolean("start " + i)); Log.d("myTag", "------------------------------------------end onCreate"); } } listView=(ListView)findViewById(R.id.listView); myAdapter = new MyAdapter(this,R.layout.list_item, Tracker.getAll(db),from,to,0); listView.setAdapter(myAdapter); getSupportLoaderManager().initLoader(LOADER_ID,null,this); } public void onCLick(View v){ Intent intent = new Intent(this,AddTrack.class); startActivity(intent); } @Override public Loader<Cursor> onCreateLoader(int i, Bundle bundle) { return new TrackLoader(this,db); } @TargetApi(Build.VERSION_CODES.HONEYCOMB) @Override public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { myAdapter.swapCursor(cursor); } @Override public void onLoaderReset(Loader<Cursor> loader) { } static class TrackLoader extends CursorLoader { SQLiteDatabase db; public TrackLoader(Context context,SQLiteDatabase db){ super(context); this.db = db; } @Override public Cursor loadInBackground() { return Tracker.getAll(db); } } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); for (int i = 0; i <elapsed.size() ; i++) { if(basesList.get(i)>1000){ outState.putLong("elapsedTime " + i, elapsed.get(i)); } outState.putLong("base "+i,basesList.get(i)); outState.putLong("lastPause "+i,lastPauseList.get(i)); outState.putBoolean("start " + i, startList.get(i)); Log.d("myTag", "OnSavedInstanceState-----------------------------------------"); Log.d("myTag", "position " + i); Log.d("myTag", "elapsedTime " + getTime(outState.getLong("elapsedTime "+i))); Log.d("myTag", "base "+ getTime(outState.getLong("base "+i))); Log.d("myTag", "lastPause "+ getTime(outState.getLong("lastPause "+i))); Log.d("myTag", "start "+ outState.getBoolean("start " + i)); Log.d("myTag","------------------------------------------end onSavedInstanceState"); } } String getTime(long time){ int hours = (int)(time/3600000); int minutes = (int)(time -hours*3600000)/60000; int seconds = (int)(time-hours*3600000-minutes*60000)/1000; String hour = (hours<9?"0"+hours:hours).toString(); String min = (minutes<9?"0"+minutes:minutes).toString(); String sec = (seconds<9?"0"+seconds:seconds).toString(); return ""+hour+":"+min+":"+sec; } public class MyAdapter extends SimpleCursorAdapter{ Context context; int resorceID; @TargetApi(Build.VERSION_CODES.HONEYCOMB) public MyAdapter(Context context,int resourceID,Cursor c,String[] from,int[]to,int flags){ super(context,resourceID,c,from,to,flags); this.context=context; this.resorceID =resourceID; elapsed = new ArrayList<Long>(trackerList.size()); basesList = new ArrayList<Long>(trackerList.size()); for (int i = 0; i <trackerList.size() ; i++) { elapsed.add((long) 0); basesList.add((long)0); } } @Override public View getView(final int position, View convertView, final ViewGroup parent) { View row = convertView; TrackHolder holder=null; final Tracker tracker = trackerList.get(position); final long[] lastPause = new long[1]; long elapsedTime; final long base; boolean bundleIsItStart; if(row==null){ LayoutInflater inflater = ((Activity)context).getLayoutInflater(); row = inflater.inflate(resorceID,parent,false); holder = new TrackHolder(); holder.name = (TextView)row.findViewById(R.id.row_name); holder.chronometer = (Chronometer)row.findViewById(R.id.row_chronometer); holder.start = (Button)row.findViewById(R.id.btStart); holder.stop = (Button)row.findViewById(R.id.btStop); row.setTag(holder); }else{ holder = (TrackHolder)row.getTag(); } if(!trackerList.isEmpty()) { final TrackHolder finalHolder = holder; holder.start.setEnabled(true); holder.stop.setEnabled(false); if(bundle!=null){ holder.name.setText(tracker.getName()); elapsedTime = bundle.getLong("elapsedTime "+position);//получеаем значение прошедшего времени после поворота экрана base = bundle.getLong("base " + position);//получаем, сохраненную на пред экране. lastPause[0]=bundle.getLong("lastPause " + position);//получаем разницу во времени(паузу) с SavedInstanceState bundleIsItStart=bundle.getBoolean("start " + position);//получаем статус: запущен/остановлен basesList.set(position,base); if(elapsedTime>elapsed.get(position))//если время, полученое после поворота больше, которое насчитает в onTick, запишется в список, но такого никогда не будет elapsed.set(position, elapsedTime); if(startList.get(position)==bundleIsItStart)//по аналогии как выше, если если текущий элемент == статусу, пишем в список статус, иначе элемент остается в списке startList.set(position,bundleIsItStart); if(lastPauseList.get(position)>lastPause[0]) lastPauseList.set(position,lastPause[0]); if(bundleIsItStart){ holder.stop.setEnabled(true); holder.start.setEnabled(false); holder.chronometer.setBase(base); holder.chronometer.start(); } if(!bundleIsItStart && base>1000){ holder.chronometer.setBase(base+(SystemClock.elapsedRealtime()-base+lastPause[0])); holder.stop.setEnabled(false); holder.start.setEnabled(true); } }else{ holder.name.setText(tracker.getName()); holder.start.setEnabled(true); holder.stop.setEnabled(false); } holder.start.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { finalHolder.chronometer.setBase(SystemClock.elapsedRealtime() + lastPause[0]); finalHolder.chronometer.start(); finalHolder.stop.setEnabled(true); finalHolder.start.setEnabled(false); basesList.set(position, finalHolder.chronometer.getBase()); startList.set(position,true); } }); holder.stop.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { lastPause[0]=finalHolder.chronometer.getBase()-SystemClock.elapsedRealtime(); finalHolder.chronometer.stop(); finalHolder.start.setEnabled(true); finalHolder.stop.setEnabled(false); lastPauseList.set(position,lastPause[0]); startList.set(position,false); } }); holder.chronometer.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener() { @Override public void onChronometerTick(Chronometer chronometer) { elapsed.set(position, SystemClock.elapsedRealtime() - finalHolder.chronometer.getBase()); Log.d("myTag", "elapsedTime = " + getTime(elapsed.get(position)) + " position = " + position); } }); } return row; } String getTime(long time){ int hours = (int)(time/3600000); int minutes = (int)(time -hours*3600000)/60000; int seconds = (int)(time-hours*3600000-minutes*60000)/1000; String hour = (hours<9?"0"+hours:hours).toString(); String min = (minutes<9?"0"+minutes:minutes).toString(); String sec = (seconds<9?"0"+seconds:seconds).toString(); return ""+hour+":"+min+":"+sec; } class TrackHolder{ TextView name; Chronometer chronometer; Button start,stop; } } } Debug many times, after this line, let's say on element 2, we go into onTick and there, if you hover the cursor in debug-mode on position , it shows 0 element and writes elapsedTime . I removed the onTick method, but still the first element counts down the time.
if(bundleIsItStart){ holder.stop.setEnabled(true); holder.start.setEnabled(false); holder.chronometer.setBase(base); --- после нее holder.chronometer.start(); }
setRetainInstance(true)is created just for such cases. - Silento