简体   繁体   中英

How to make a separate thread on each row of listview. GC_FOR_ALLOC

I can't understand how it should be, in my model-class i am using runnable that counts time and sending it to handler which was initialized in MainActivity. I suppose, what i must using the Thread class with Handler, but where i must initialize Handler, in adapter? I trying and catch ANR message;

In logcat often write something like this:(even if listview is empty)

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

Here is the fragment of code of my model:

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

Fragment of Adapter

  @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;
}

And MainActivity

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


}

Add task activity:

 Tracker tracker;
SQLiteDatabase db;
EditText name,limitHours,limitMinute;
RadioButton limitTime,unlimitTime;
RadioGroup radioGroup;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.add_track);
    name = (EditText)findViewById(R.id.edit_name);
    radioGroup = (RadioGroup)findViewById(R.id.radioGroup);
    limitHours = (EditText)findViewById(R.id.edit_Hours);
    limitMinute = (EditText)findViewById(R.id.edit_Min);
    limitTime = (RadioButton)findViewById(R.id.rdbLimit);
    unlimitTime = (RadioButton)findViewById(R.id.rdbUnlimit);
    tracker = new Tracker();
    db = RemindMe.db;//it's db.getWritableDatabase();
}

Solution was very simple, in model class put Thread class which will counts time, sending to Handler some int value, just to turn it on. The handler will change the UI uses the ViewHolder object which will be setted to each item in the listview in getView() adapter's method.

To adapter constructor I send a static List (in getView() method I pull the needed object and work with it), this is very important because, if the list is not static, after the leave Activity with listview and re-entry will be the creation of new instances activity / adapter / models.

Here is the fragment of my model class: 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;
class TrackerThread extends Thread{
    public TrackerThread() {
        super();
    }

    @Override
    public void run() {
        super.run();
        try {
            while (isStart && !isInterrupted()){
            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;
                handler.sendEmptyMessage(1);//its just for run Handler

                if(limitTime!=0 && elapsedTime > limitTime) {
                    interrupt();
                }else
                    sleep(1000);
            }
            }
        }catch (Exception ex){
            ex.printStackTrace();
        }
    }
}
Handler handler = new Handler(new Handler.Callback() {
    @Override
    public boolean handleMessage(Message msg) {
            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()));
        }
        return true;
    }
});

Here is the getView() adapter:

 @Override
public View getView(final int position, final View convertView, ViewGroup parent) {
    View row = convertView;
    final Tracker tracker = trackerList.get(position);
    final Thread thread = tracker.getThread();
    ViewHolder holder;
    long days,hours,minutes,seconds;
    long eDays,eHours,eMins,eSecs;

    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 = (ButtonFloatSmall)row.findViewById(R.id.btStart);
        holder.stop = (ButtonFloatSmall)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 и таймер без лимита
        days = tracker.getElapsedTime()/86400000;
        hours = (tracker.getElapsedTime()/3600000)%24;
        minutes = (tracker.getElapsedTime()/60000)%60;
        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()){//если таск закончен, дошел до лимита
        hours = (tracker.getLimitTime()/3600000)%24;
        minutes = (tracker.getLimitTime()/60000)%60;
        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()){//если установлен лимит, но еще не дошел до конца
        days = tracker.getLimitTime()/86400000;
        hours = (tracker.getLimitTime()/3600000)%24;
        minutes = (tracker.getLimitTime()/60000)%60;
        finalHolder.textLimit.setVisibility(View.VISIBLE);
        finalHolder.limHours.setVisibility(View.VISIBLE);
        finalHolder.limDay.setVisibility(View.VISIBLE);
        finalHolder.limMin.setVisibility(View.VISIBLE);
        finalHolder.limDay.setText(Util.concat(days <= 9 ? 0 : "", days, ":"));
        finalHolder.limHours.setText(Util.concat(hours <= 9 ? 0 : "", hours, ":"));
        finalHolder.limMin.setText(Util.concat(minutes<=9?0:"",minutes));

        eDays = (tracker.getElapsedTime() / 86400000);
        eHours = (tracker.getElapsedTime()/3600000)%24;
        eMins = (tracker.getElapsedTime()/60000)%60;
        eSecs = (tracker.getElapsedTime()/1000)%60;

        if(eSecs!=0)
            finalHolder.seconds.setText(Util.concat(eSecs<=9?0:"",eSecs));
        if(eMins!=0)
            finalHolder.minutes.setText(Util.concat(minutes<=9?0:"",eMins));
        if(eHours!=0)
            finalHolder.hours.setText(Util.concat(hours<= 9 ? 0 : "", eHours));
        if(eSecs!=0)
            finalHolder.days.setText(Util.concat(days<= 9 ? 0 : "", eDays));


    }else {
        finalHolder.textLimit.setVisibility(View.GONE);
        finalHolder.limHours.setVisibility(View.GONE);
        finalHolder.limDay.setVisibility(View.GONE);
        finalHolder.limMin.setVisibility(View.GONE);
    }

    if(tracker.getIsStart() && !tracker.getIsFinished()) {//если был стартован
        finalHolder.start.setVisibility(View.GONE);
        finalHolder.stop.setVisibility(View.VISIBLE);
    }
    tracker.setHolder(finalHolder);
    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);
                    if(tracker.getUpdateTime()==0)
                        thread.start();
                    else
                        tracker.getThread().start();

                    break;
                case R.id.btStop:
                    tracker.setLastPause(tracker.getUpdateTime());
                    finalHolder.stop.setVisibility(View.GONE);
                    finalHolder.start.setVisibility(View.VISIBLE);
                    tracker.setIsStart(false);
                    break;

            }
        }
    };
    finalHolder.start.setOnClickListener(onClickListener);
    finalHolder.stop.setOnClickListener(onClickListener);
    return row;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM