【问题标题】:How can I run this class in the UI thread?如何在 UI 线程中运行此类?
【发布时间】:2015-06-18 15:55:21
【问题描述】:

我有适用于日期数组的 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 一样运行它,它会正常运行,并且它会在控制台中的每一秒打印出来。但是当它在android环境中运行时,它要么说不能从任何其他线程触及UI线程,要么在ScheduleTimer类的方法run()中给我NullPointerException

我是这样使用它的:new ScheduleTimer(textView).main(new String[] {"13.04.2015 13:59", "13.04.2015 14:14", "13.04.2015 14:15"});

我尝试使用AsyncTaskHandler,但可能我做得不对。 无论如何,我需要找到以某种方式使用此类更新我的TextView 的方法。

有人可以帮我吗?如何在我的onCreateView 方法中正常运行它并正确传递所需的TextView

【问题讨论】:

  • runOnUiThread(new Runnable(){...});
  • 您能说得更具体些吗? Runnable类的run()方法应该写什么?
  • 一个异步任务对你来说会更容易实现,它有你需要的确切方法。您可以在 doInBackground() 方法中进行处理,将最终结果传递给 onPostExecute() 方法,对于视图的中间更新,您可以使用 onProgressUpdate() 方法。
  • @Skynet,好吧,我实际上已经尝试过这样做,但我想我做错了。我所做的是从 AsyncTask 扩展我当前的类并在那里实现方法 doInBackground。在 doInBackground 方法中,我启动了 ScheduleTimer 类的方法 run()。但它没有用:(
  • doInBackground 是一个单独的线程,您不需要在那里创建单独的线程。此外,最好将 AsyncTask 作为一个独立单元单独编写 - 传递一些参数 - 在 doInBackground 中的过程在 onPostExecute() 中获取最终结果并使用 onProgressUpdate() 更新中间值

标签: java android multithreading android-asynctask


【解决方案1】:

你的 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]);
        }


    }

【讨论】:

    【解决方案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(),可以操作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 了解更多说明。

      【讨论】:

      • FragmentActivity extends Activity 有这个方法,所以是的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-02
      • 1970-01-01
      • 2017-05-20
      • 2016-01-16
      • 2015-02-17
      相关资源
      最近更新 更多