2015-04-13 3 views
3

У меня есть класс ScheduleTimer, который работает с массивом дат. Вот оно:Как запустить этот класс в потоке пользовательского интерфейса?

class ScheduleTimer { 

    public TextView textView; 

    private Timer dateTimer; 

    private Timer remainderTimer; 

    private Date formatDate = new Date(); 

    private Date nextDate; 

    private boolean remainderTimerStarted; 

    private static final long REMINDER_UPDATE_INTERVAL = 1000; 

    private static String[] DATES; 

    private int currentIndex; 

    public ScheduleTimer(final TextView t) { 
     textView = t; 
     dateTimer = new Timer(); 
    } 

    public void main(String[] dates) throws ParseException { 
     checkDates(dates); 
     run(); 
    } 

    private void checkDates(String[] dates) throws ParseException { 
     List<String> list = new ArrayList<>(); 
     DateFormat format = new SimpleDateFormat("dd.MM.yyyy HH:mm", Locale.ENGLISH); 
     for(String date : dates) { 
      long current = System.currentTimeMillis() + 1000; 
      if(format.parse(date).getTime() - current > 0) { 
       list.add(date); 
      } 
     } 
     DATES = new String[list.size()]; 
     list.toArray(DATES); 
    } 

    private void run() { 
     nextDate = parseDate(DATES[currentIndex]); 
     schedule(); 
    } 

    public void schedule() { 
     runSecondsCounter(); 
     dateTimer.schedule(new TimerTask() { 

      @Override 
      public void run() { 

       System.out.println("Current date is:" + new Date()); 
       currentIndex++; 
       if (currentIndex < DATES.length) { 
        nextDate = parseDate(DATES[currentIndex]); 
        System.out.println("Next date is:" + nextDate); 
        schedule(); 
       } else { 
        remainderTimer.cancel(); 
       } 
      } 
     }, nextDate); 

    } 

    private Date parseDate(String nextDate) { 
     Date date = null; 
     DateFormat format = new SimpleDateFormat("dd.MM.yyyy HH:mm", 
       Locale.ENGLISH); 
     try { 
      date = format.parse(nextDate); 
     } catch (ParseException e) { 
      e.printStackTrace(); 
     } 
     return date; 
    } 

    private void runSecondsCounter() { 
     if (remainderTimerStarted) { 
      remainderTimer.cancel(); 
     } 

     remainderTimer = new Timer(); 
     remainderTimer.scheduleAtFixedRate(new TimerTask() { 

      @Override 
      public void run() { 
       remainderTimerStarted = true; 
       long remains = nextDate.getTime() - new Date().getTime(); 
       System.out.println("Remains: " + (remains/1000) + " seconds"); 
       formatDate.setTime(remains); 
       textView.setText(formatDate.toString()); 
      } 
     }, REMINDER_UPDATE_INTERVAL, REMINDER_UPDATE_INTERVAL); 
    } 
} 

Он отлично работает, если я запустить его так же, как приложения Java, а не андроид, и он печатает каждый подсчитывают второй в консоли. Но когда дело доходит до запуска в среде Android, он либо говорит, что поток пользовательского интерфейса не может быть затронут ни с какой другой нити, или он дает мне NullPointerException в методе run() класса ScheduleTimer.

Я использую это следующим образом: new ScheduleTimer(textView).main(new String[] {"13.04.2015 13:59", "13.04.2015 14:14", "13.04.2015 14:15"});

Я попытался с помощью AsyncTask или Handler, но, вероятно, я не делал это правильно. Как бы то ни было, мне нужно найти способ обновить мой TextView каким-то образом, используя этот класс.

Может ли кто-нибудь помочь мне в этом? Как я могу запустить его обычно в моем методе onCreateView и правильно передать нужный TextView?

+5

'runOnUiThread (новый Runnable() {...}); ' –

+0

Не могли бы вы быть более конкретными? что я должен писать в методе run() класса Runnable? –

+1

Задача Async Task будет проще для вас реализовать, она требует точных методов. Вы можете выполнить свою обработку в методе doInBackground(), передать свой конечный результат методу onPostExecute(), а для промежуточных обновлений ваших представлений вы можете использовать метод onProgressUpdate(). – Skynet

ответ

2

Полный ответ: Ваш фрагмент:

public class PlaceholderFragment extends Fragment { 

     public PlaceholderFragment() { 
     } 

     @Override 
     public View onCreateView(LayoutInflater inflater, ViewGroup container, 
           Bundle savedInstanceState) { 
      View rootView = inflater.inflate(R.layout.fragment_main, container, false); 

      TextView textView = (TextView) rootView.findViewById(R.id.tv); 

      try { 
       new ScheduleTimer(textView, getActivity()) 
         .main(new String[] {"13.04.2015 13:59", "13.04.2015 14:14", "13.04.2015 14:15"}); 
      } catch (ParseException e) { 
       e.printStackTrace(); 
      } 

      return rootView; 
     } 
    } 

Ваш ScheduleTimer класс:

class ScheduleTimer { 

    public TextView textView; 

    private Timer dateTimer; 

    private Timer remainderTimer; 

    private Date formatDate = new Date(); 

    private Date nextDate; 

    private boolean remainderTimerStarted; 

    private static final long REMINDER_UPDATE_INTERVAL = 1000; 

    private static String[] DATES; 

    private int currentIndex; 

    private Activity activity; 

    public ScheduleTimer(final TextView t, Activity a) { 
     textView = t; 
     activity = a; 
     dateTimer = new Timer(); 
    } 

    public void main(String[] dates) throws ParseException { 
     checkDates(dates); 
     run(); 
    } 

    private void checkDates(String[] dates) throws ParseException { 
     List<String> list = new ArrayList<>(); 
     DateFormat format = new SimpleDateFormat("dd.MM.yyyy HH:mm", Locale.ENGLISH); 
     for(String date : dates) { 
      long current = System.currentTimeMillis() + 1000; 
      if(format.parse(date).getTime() - current > 0) { 
       list.add(date); 
      } 
     } 
     DATES = new String[list.size()]; 
     list.toArray(DATES); 
    } 

    private void run() { 
     nextDate = parseDate(DATES[currentIndex]); 
     schedule(); 
    } 

    public void schedule() { 
     runSecondsCounter(); 
     dateTimer.schedule(new TimerTask() { 

      @Override 
      public void run() { 

       System.out.println("Current date is:" + new Date()); 
       currentIndex++; 
       if (currentIndex < DATES.length) { 
        nextDate = parseDate(DATES[currentIndex]); 
        System.out.println("Next date is:" + nextDate); 
        schedule(); 
       } else { 
        remainderTimer.cancel(); 
       } 
      } 
     }, nextDate); 

    } 

    private Date parseDate(String nextDate) { 
     Date date = null; 
     DateFormat format = new SimpleDateFormat("dd.MM.yyyy HH:mm", 
       Locale.ENGLISH); 
     try { 
      date = format.parse(nextDate); 
     } catch (ParseException e) { 
      e.printStackTrace(); 
     } 
     return date; 
    } 

    private void runSecondsCounter() { 
     if (remainderTimerStarted) { 
      remainderTimer.cancel(); 
     } 

     remainderTimer = new Timer(); 
     remainderTimer.scheduleAtFixedRate(new TimerTask() { 

      @Override 
      public void run() { 
       remainderTimerStarted = true; 
       long remains = nextDate.getTime() - new Date().getTime(); 
       System.out.println("Remains: " + (remains/1000) + " seconds"); 
       formatDate.setTime(remains); 

       activity.runOnUiThread(new Runnable() { 
        @Override 
        public void run() { 
         textView.setText(formatDate.toString()); 
        } 
       }); 

      } 
     }, REMINDER_UPDATE_INTERVAL, REMINDER_UPDATE_INTERVAL); 
    } 
} 
3

runOnUiThread() метод отправит ваш Runnable для выполнения на основной поток. В run(), вы можете манипулировать интерфейс управления:

@Override 
public void run() { 
    remainderTimerStarted = true; 
    long remains = nextDate.getTime() - new Date().getTime(); 
    formatDate.setTime(remains); 
    runOnUiThread(new Runnable() { // <= here! 
      @Override 
      public void run() { 
       textView.setText(formatDate.toString()); 
      } 
    }); 
} 

Check this для более подробного объяснения.

+0

Есть ли метод runOnUiThread во фрагментах? –

+1

'FragmentActivity' расширяет' Activity', который имеет этот метод, поэтому да. –

2

скелет вашего AsyncTask будет:

public class ListLoader extends AsyncTask<Void, Void, String> { 

     ProgressDialog Asycdialog = new ProgressDialog(CreateGroup.this); 
     @Override 
     protected void onPreExecute() { 
      // TODO Auto-generated method stub 
      System.out.println("Pre Execute"); 
      Asycdialog.setMessage("Working"); 
      Asycdialog.getWindow().setGravity(Gravity.CENTER_VERTICAL); 
      Asycdialog.getWindow().setGravity(Gravity.CENTER_HORIZONTAL); 
      Asycdialog.setCancelable(false); 
      Asycdialog.show(); 
      super.onPreExecute(); 
     } 

     protected void onPostExecute(String result) { 
      Asycdialog.cancel(); 

      //Play with result here - Update UI 
     } 

     @Override 
     protected String doInBackground(Context... params) { 

      //Memory intense or long running operation here 
      publishProgress(progress); //Publish your progress - update a textView 

      return "result will be sent to onPostExecute()"; 

     } 

     protected void onProgressUpdate(String... values) { 

      super.onProgressUpdate(values); 
      Asycdialog.setMessage("" + values[0]); 
     } 


    } 
Смежные вопросы