1 - через chronometer, лепил его в каждый item listview данные сохранялись хорошо, в onSaved и onRestore не было проблем, но после поворота экрана запускался первый элемент, и chronometer начинал лже-отсчет и брал время равное таймеру который внизу, визуально циферки тикают, но его данные никуда не заносятся.
2 - через интерфейс Runnable в связке с Handler, проблема почти та же, только в этот раз я использовал congifChanges="oriantation|screen" и оно теперь последнему элементу присваивает лже-время, которое берет с другого активного таймера.
В обоих случаях я писал свой адаптер, и я уверен что ошибка в его логике, т.к. это единственное общее между этими двумя разными приложениями. Сейчас мне кажется, что это просто нереальная задача, и я зашел в тупик и прошу помочь знающих людей.
Привожу весь код класса его много, но адаптер маленький,он - внутренний класс. Я там добавил комментарии.
Результат выполнения программы.
Нажали старт
Перевернули отсчитало и нажали Стоп.
Код: Выделить всё
public class MainActivity extends FragmentActivity implements android.support.v4.app.LoaderManager.LoaderCallbacks<Cursor>,View.OnClickListener{
MyAdapter adapter;
ListView listview;
Handler handler;
DBHelper dbHelper;
SQLiteDatabase db;
List<Tracker> trackerList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handler = new Handler();
dbHelper = new DBHelper(this);
db=dbHelper.getWritableDatabase();
trackerList = Tracker.getListAll(db);
String[] from = {Tracker.COL_NAME,Tracker.COL_ELAPSED_TIME,Tracker.COL_ELAPSED_TIME,Tracker.COL_ELAPSED_TIME,Tracker.COL_ELAPSED_TIME};
int[] to = {R.id.tvName,R.id.tvDays,R.id.tvHours,R.id.tvMinutes,R.id.tvSeconds};
listview = (ListView)findViewById(R.id.listView);
adapter = new MyAdapter(this,R.layout.row,Tracker.getAll(db),from,to,0);
listview.setAdapter(adapter);
getSupportLoaderManager().initLoader(1, null, this);
Log.d("myLog","onCreate");
}
@Override
public void onClick(View v) {
}
@Override
public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
Log.d("myTag","onCreateLoader");
return new MyLoader(this,db);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
Log.d("myTag","onFinishLoader");
adapter.swapCursor(cursor);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
}
static class MyLoader extends CursorLoader{
SQLiteDatabase db;
MyLoader(Context context,SQLiteDatabase db){
super(context);
this.db=db;
}
@Override
public Cursor loadInBackground() {
Log.d("myTag","loadInBackground");
return Tracker.getAll(db);
}
}
class MyAdapter extends SimpleCursorAdapter{
Context context;
MyAdapter(Context context,int resourceID,Cursor cursor,String[] from,int[] to,int flag){
super(context, resourceID,cursor,from,to,flag);
this.context=context;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
View row = convertView;
final Tracker tracker = trackerList.get(position);
final ViewHolder holder;
if(row == null){
holder = new ViewHolder();
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(R.layout.row,parent,false);
holder.name = (TextView)row.findViewById(R.id.tvName);
holder.days = (TextView)row.findViewById(R.id.tvDays);
holder.hours = (TextView)row.findViewById(R.id.tvHours);
holder.minutes = (TextView)row.findViewById(R.id.tvMinutes);
holder.seconds = (TextView)row.findViewById(R.id.tvSeconds);
holder.start = (Button)row.findViewById(R.id.btStart);
holder.stop = (Button)row.findViewById(R.id.btStop);
row.setTag(holder);
}else{
holder = (ViewHolder)row.getTag();
}
holder.start.setEnabled(true);
holder.stop.setEnabled(false);
holder.name.setText(tracker.getName());
final Runnable updateTimeThread = new Runnable() {
@Override
public void run() {
if (tracker.getIsStart()) {
tracker.setUpdateTime((System.currentTimeMillis() - tracker.getStartTime()) + tracker.getLastPause());
tracker.setSeconds(tracker.getUpdateTime() / 1000);
tracker.setMinutes(tracker.getSeconds() / 60);
tracker.setHours(tracker.getMinutes() / 60);
tracker.setSeconds(tracker.getSeconds() % 60);
tracker.setMinutes(tracker.getMinutes() % 60);
tracker.setHours(tracker.getHours() % 24);
holder.days.setText(String.format("%04d", tracker.getDays()));
holder.hours.setText(String.format("%02d", tracker.getHours()));
holder.minutes.setText(String.format("%02d", tracker.getMinutes()));
holder.seconds.setText(String.format("%02d", tracker.getSeconds()));
handler.post(this);
}
else{
handler.removeCallbacks(this);
}
}
};
if(tracker.getIsStart()){
holder.start.setEnabled(false);
holder.stop.setEnabled(true);
}
View.OnClickListener onClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btStart:
tracker.setStartTime(System.currentTimeMillis());
tracker.setIsStart(true);
handler.post(updateTimeThread);
holder.start.setEnabled(false);
holder.stop.setEnabled(true);
Log.d("myTag", "onClickStart");
break;
case R.id.btStop:
tracker.setLastPause(tracker.getUpdateTime());
handler.removeCallbacks(updateTimeThread);
holder.stop.setEnabled(false);
holder.start.setEnabled(true);
tracker.setIsStart(false);
break;
}
}
};
holder.start.setOnClickListener(onClickListener);
holder.stop.setOnClickListener(onClickListener);
return row;
}
class ViewHolder{
TextView name,days,hours,minutes,seconds;
Button start,stop;
}
}
}
UPDATE
Проблема не в адаптере, создал тот же адаптер только в без Loader'a все работает хорошо, только адаптер наследовался не от SimpleCursorAdapter а от BaseAdapter. Проблема стала заключаться в отсутствии отображения изменения данных в последнем элементе списка после поворота. То есть, если в портретном нажмем Старт и повернем экран, программно он будет считать но не отображать, если вернемся на портрет он будет показывать отсчет.