Как вынести в отдельный поток каждый таймер в listview? Ловлю GC_FOR_ALLOC

Рейтинг: 0Ответов: 1Опубликовано: 02.05.2015

Помогите вынести работу каждого таймера в отдельный поток. Есть listview с таймером в каждой строке. Очень часто в LogCat пишет

 The application may be doing too much work on its main thread.
 GC_FOR_ALLOC freed 795K, 56% free 9998K/22280K, paused 11ms, total 12ms

В классе-модели я используя Runnable для отсчета времени и посылаю его handler'y который объявлен в MainActivity. Могу предположить что объявление его в MainActivity бессмысленно, и нужно может в адаптере что-то сделать. Какие советы по оптимизации можете дать?

Вот фрагмент кода модели:

  private String name;
private  Boolean isStart=false, isFinished=false;
private  Long elapsedTime=0L,seconds=0L,hours=0L,minutes=0L,lastPause=0L,updateTime=0L,startTime=0L,days=0L,limitTime=0L;
private Runnable updateTimeThread=new Runnable() {
    @Override
    public void run() {
        if(isStart && startTime!=0) {
            if(elapsedTime!=0 && updateTime==0)
                lastPause=elapsedTime;
            updateTime = ((System.currentTimeMillis() - startTime) + lastPause);
            seconds = updateTime / 1000;
            minutes = seconds / 60;
            hours = minutes / 60;

            seconds = seconds % 60;
            minutes = minutes % 60;
            hours = hours % 24;

            elapsedTime=updateTime;

            holder.days.setText(String.format("%04d", days));
            holder.hours.setText(String.format("%02d", hours));
            holder.minutes.setText(String.format("%02d", minutes));
            holder.seconds.setText(String.format("%02d", seconds));

            if(limitTime!=0 && elapsedTime>limitTime) {
                isFinished = true;
                holder.stop.setVisibility(View.GONE);
                holder.textFinish.setVisibility(View.VISIBLE);
                holder.limDay.setVisibility(View.GONE);
                holder.limMin.setVisibility(View.GONE);
                holder.limHours.setVisibility(View.GONE);
                holder.textLimit.setVisibility(View.GONE);
                RemindMe.db.execSQL(Util.concat("UPDATE trackers SET isFinish=1, elapsedTime=",limitTime," WHERE _id=",getId()));

            }
            if(!isFinished)
                MainActivity.handler.post(this);

        }
    }
};
MyAdapter.ViewHolder holder;
public MyAdapter.ViewHolder getHolder() {
    return holder;
}

Фрагмент кода адаптера:

  @Override
public View getView(final int position, final View convertView, ViewGroup parent) {
    View row = convertView;
    final Tracker tracker = trackerList.get(position);
    final Runnable updateTimeThread=tracker.getRunnable();
    ViewHolder holder;

    if(row == null){
        holder = new ViewHolder();
        LayoutInflater inflater = ((Activity)context).getLayoutInflater();
        row = inflater.inflate(R.layout.list_item,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);
        holder.textFinish = (TextView)row.findViewById(R.id.txtFinish);
        holder.textLimit = (TextView)row.findViewById(R.id.txtLimit);
        holder.limDay = (TextView)row.findViewById(R.id.limDay);
        holder.limHours = (TextView)row.findViewById(R.id.limHours);
        holder.limMin = (TextView)row.findViewById(R.id.limMin);
        row.setTag(holder);
    }else {
        holder = (ViewHolder) row.getTag();
    }

    //изнальначальный вид
    final ViewHolder finalHolder = holder;
    finalHolder.start.setVisibility(View.VISIBLE);
    finalHolder.stop.setVisibility(View.GONE);
    finalHolder.name.setText(tracker.getName());
    if(tracker.getElapsedTime()!=0 && tracker.getLimitTime()==0){//если прошедшее время !=0 и таймер без лимита
        long days = tracker.getElapsedTime()/86400000;
        long hours = (tracker.getElapsedTime()/360000)%24;
        long minutes = (tracker.getElapsedTime()/60000)%60;
        long seconds = (tracker.getElapsedTime()/1000)%60;
        if(days!=0)
            finalHolder.days.setText(Util.concat(days<=9?0:"",days,":"));
        if(hours!=0)
            finalHolder.hours.setText(Util.concat(hours <=9 ?0:"",hours,":"));
        if(minutes!=0)
            finalHolder.minutes.setText(Util.concat(minutes<=9?0:"",minutes,":"));
        if(seconds!=0)
            finalHolder.seconds.setText(Util.concat(seconds<=9?0:"",seconds));
    }
    if(tracker.getIsFinished()){//если таск закончен, дошел до лимита
        long hours = (tracker.getLimitTime()/360000)%24;
        long minutes = (tracker.getLimitTime()/60000)%60;
        long seconds = (tracker.getLimitTime()/1000)%60;
        finalHolder.start.setVisibility(View.GONE);
        finalHolder.textFinish.setVisibility(View.VISIBLE);
        finalHolder.stop.setVisibility(View.GONE);
        if(seconds!=60)
            finalHolder.seconds.setText(Util.concat(seconds<=9?0:"",seconds));
        if(minutes!=60)
            finalHolder.minutes.setText(Util.concat(minutes<=9?0:"",minutes,":"));
        if(hours!=24)
            finalHolder.hours.setText(Util.concat(hours <= 9 ? 0 : "", hours, ":"));

    }
    if(tracker.getLimitTime()!=0 && !tracker.getIsFinished()){//если установлен лимит, но еще не дошел до конца
        long days = tracker.getLimitTime()/86400000;
        long hours = (tracker.getLimitTime()/3600000)%24;
        long minutes = (tracker.getLimitTime()/60000)%60;
        finalHolder.textLimit.setVisibility(View.VISIBLE);
        if(days!=0) {
            finalHolder.limDay.setVisibility(View.VISIBLE);
            finalHolder.limDay.setText("" + (days <= 9 ? "0" + days : days) + ":");
        }
        if(hours!=0) {
            finalHolder.limHours.setVisibility(View.VISIBLE);
            finalHolder.limHours.setText(Util.concat(hours <= 9 ? 0 : "", hours, ":"));
        }
        if(minutes!=0) {
            finalHolder.limMin.setVisibility(View.VISIBLE);
            finalHolder.limMin.setText(Util.concat(minutes<=9?0:"",minutes,":"));

        }
        if(days==0 && hours==0 & minutes!=0){
            finalHolder.limMin.setText(Util.concat(minutes,"minutes"));
        }
    }

    if(tracker.getIsStart()) {//если был стартован
        finalHolder.start.setVisibility(View.GONE);
        finalHolder.stop.setVisibility(View.VISIBLE);
    }
    onSavedList.set(position,tracker);
    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);
                    tracker.setHolder(finalHolder);
                    finalHolder.start.setVisibility(View.GONE);
                    finalHolder.stop.setVisibility(View.VISIBLE);
                    MainActivity.handler.post(updateTimeThread);
                    break;
                case R.id.btStop:
                    tracker.setLastPause(tracker.getUpdateTime());
                    MainActivity.handler.removeCallbacks(updateTimeThread);
                    finalHolder.stop.setVisibility(View.GONE);
                    finalHolder.start.setVisibility(View.VISIBLE);
                    tracker.setIsStart(false);
                    break;
            }
        }
    };
    finalHolder.start.setOnClickListener(onClickListener);
    finalHolder.stop.setOnClickListener(onClickListener);
    return row;
}

MainAcitivty

 public class MainActivity extends ActionBarActivity implements LoaderManager.LoaderCallbacks<Cursor>,View.OnClickListener {

    ListView listView;
    MyAdapter adapter;
   static Handler handler;
    SQLiteDatabase db;
    List<Tracker> trackerList;

    static final String LOG_TAG = "myTag";
    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        handler = new Handler();
        db = RemindMe.db;
        trackerList = Tracker.getListAll(db);

        listView = (ListView) findViewById(R.id.listView);
        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};
        adapter = new MyAdapter(this, R.layout.list_item, Tracker.getAll(db), from, to, 0,trackerList);
        listView.setAdapter(adapter);
        getSupportLoaderManager().initLoader(1, null, this);
    }
    @Override
    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 TrackerLoader(this, db);
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
        adapter.swapCursor(cursor);
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {

    }

    static class TrackerLoader extends android.support.v4.content.CursorLoader {
        SQLiteDatabase db;

        TrackerLoader(Context context, SQLiteDatabase db) {
            super(context);
            this.db = db;
        }

        @Override
        public Cursor loadInBackground() {
            return Tracker.getAll(db);
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
    Log.d(LOG_TAG, "onStop " + hashCode());
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.d(LOG_TAG, "onPause "+hashCode());
        for (int i = 0; i <adapter.getCount() ; i++) {
            trackerList.get(i).update(db);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d(LOG_TAG, "onResume "+hashCode());
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(LOG_TAG, "onDestroy "+hashCode());
    }


}

Ответы

Ответов пока нет.