简体   繁体   English

如何在UI线程中运行此类?

[英]How can I run this class in the UI thread?

I have the class ScheduleTimer that works on the array of dates. 我有类ScheduleTimer,它适用于日期数组。 Here it is: 这里是:

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

It works fine if I run it just like a Java application, not android, and it prints out every counted second in the console. 如果我像Java应用程序一样运行它,而不是android,它可以正常运行,并且它会在控制台中打印出每个计数秒。 But when it comes to run it in the android environment, it either says that the UI thread cannot be touched from any other thread, or it gives me NullPointerException in the method run() of the class ScheduleTimer . 但是当它在android环境中运行它时,它要么说不能从任何其他线程触及UI线程,要么它在ScheduleTimer类的方法run()中给我NullPointerException

I'm using it like this: new ScheduleTimer(textView).main(new String[] {"13.04.2015 13:59", "13.04.2015 14:14", "13.04.2015 14:15"}); 我正在使用它: new ScheduleTimer(textView).main(new String[] {"13.04.2015 13:59", "13.04.2015 14:14", "13.04.2015 14:15"});

I tried using AsyncTask or Handler , but probably, I didn't do it right. 我尝试使用AsyncTaskHandler ,但可能,我做得不对。 Anyway, I need to find the way to update my TextView somehow using this class. 无论如何,我需要找到使用这个类以某种方式更新我的TextView的方法。

Could anybody help me with that? 有人可以帮我吗? How can I run it normally in my onCreateView method and pass the needed TextView correctly? 如何在我的onCreateView方法中正常运行它并正确传递所需的TextView

runOnUiThread() method will send your Runnable to execute onto the main thread. runOnUiThread()方法将发送您的Runnable执行到主线程。 In run() , you can manipulate UI controls: run() ,您可以操作UI控件:

@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 for more explanation. 检查这个以获得更多解释。

A skeleton of your AsyncTask would be: 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]);
        }


    }

The complete answer is: Your fragment: 完整的答案是:你的片段:

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

Your ScheduleTimer class: 您的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);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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