2

I am new to android. I'm creating an contest app in which I have a ListView which contains status of the event. Whether it is started or not. It should be updated automatically when the current time exceeds the event start time.

I'm using a AsyncTask but it is not very accurate.

@Override
public View getView(final int position, View view, ViewGroup parent) {
    LayoutInflater scheduleInflater = LayoutInflater.from(getContext());
    final Holder h;
    if(view == null){
        view = scheduleInflater.inflate(R.layout.custom_list , parent , false);
        h = new Holder();

        h.eventName=(TextView) view.findViewById(R.id.eventNameCustomList);
        h.eventStatus=(TextView) view.findViewById(R.id.eventStatus);
        h.leftTime = (TextView) view.findViewById(R.id.leftTime);
        h.rightTime= (TextView) view.findViewById(R.id.rightTime);
        view.setTag(h);

    }else{
        h = (Holder) view.getTag();
    }

    final data d = getItem(position);

    h.eventName.setText(d.getEventName());

    Date startDate= d.getStartDate();
    Date endDate = d.getEndDate();

    long stTime = startDate.getTime();
    long now = System.currentTimeMillis();

    if(now >= stTime) {h.eventStatus.setText(Html.fromHtml(startedText));}
    else {h.eventStatus.setText(Html.fromHtml(upcomingText));}


    h.eventStatus.setTag(String.valueOf(position));  // Setting Tag of each TextView to its position to avoid incorrect ayncTask update
    new go(h.eventStatus).execute(d.getStartDate()); // starting a thread to update the Text view
    return view;
}


public class go extends AsyncTask<Date, Void , Boolean> {

    String path;
    TextView status;
    public go(TextView eventStatus){
        this.status=eventStatus;
        this.path=eventStatus.getTag().toString();
    }


    @Override
    protected Boolean doInBackground(Date... params) {
        Date startDate = params[0];
        while(true){
            long curTime = System.currentTimeMillis();
            long startTime = startDate.getTime();
            if (curTime >= startTime) {return true;}
        }
    }

    @Override
    protected void onPostExecute(Boolean b) {
        if(!status.getTag().toString().equals(path)) return;
        if(b!=null && status!=null){
            if(b==true) status.setText(Html.fromHtml(startedText));
            else status.setText(Html.fromHtml(upcomingText));
        }else{
            status.setText(Html.fromHtml(upcomingText));
        }
    }

}

static class Holder{
    TextView eventName , eventStatus;
    TextView leftTime, rightTime;
}

How to Update the TextView to started when the current time exceeds the start time. Please Help and suggest a better solution.

LaurentY
  • 7,495
  • 3
  • 37
  • 55
Arun
  • 19
  • 2
  • `which contains status of the event` do you mean that the listview shows is a list of events? `but it is not very accurate` Please define accurate here. Also, does the counter keep on ticking, example 20 minutes to go, etc? – Sufian Jun 12 '16 at 07:11
  • Listview has a number of events and it has a textview in each item which shows the status . Status : Upcoming or Status : Started . Asynctask makes my app slower – Arun Jun 12 '16 at 09:18

2 Answers2

0

The reason for your app becoming slow is because you're needlessly running checks inside while(true), which is taking too much resources and making the whole device slow.

Better approach will be to execute an update operation after some delay, that is when its time comes.

Follow these steps:

  1. keep time for event to start in some sort of list/array/map (keep time relative),
  2. use android.os.Handler to execute code with delay. Something like below (replace timeInMillis with milliseconds after which the event starts):

    Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            adapter.notifyDataSetChanged();
        }
    }, timeInMillis);
    
Sufian
  • 6,405
  • 16
  • 66
  • 120
  • Where to write the timer code. Since i want to update a textview of a listItem based on time. Can you please provide where to write this as i'm new to android. Should i write these in getView ? – Arun Jun 14 '16 at 11:21
  • `Handler.postDelayed()` will fire the provided `Runnable` after the said time, please see the [docs here](https://developer.android.com/reference/android/os/Handler.html#postDelayed(java.lang.Runnable,%20long)). You will write this code after setting your `Listview`'s adapter. **DO NOT** create these things in `getView()`, because it is only called when an item is to be shown! – Sufian Jun 15 '16 at 05:20
0

It's better to use Timer and TimerTask as this:

final Handler handler = new Handler();
Timer timer = new Timer(false);
TimerTask timerTask = new TimerTask() {
    @Override
    public void run() {
        handler.post(new Runnable() {
            @Override
            public void run() {
                // My check to do every second
            }
        });
    }
};
timer.schedule(timerTask, 1000); // 1000 = 1 second. 
LaurentY
  • 7,495
  • 3
  • 37
  • 55
  • `TimerTask` has its problems (please [see this](http://stackoverflow.com/questions/20330355/timertask-or-handler)), besides you are creating 3 objects in this (including `Handler`), so it isn't any better. – Sufian Jun 15 '16 at 05:24