在时间选择器和当前时间之间获得时间延迟后使用postDelayed安排任务

时间:2018-03-26 14:32:17

标签: android android-handler android-timepicker

我已经在我的片段中编写了一段代码,该代码将在Toast上由用户选择的特定时间显示Time Picker消息。通过从时间选择器时间(以毫秒为单位)减去当前时间(以毫秒为单位)来计算时间延迟。 但是没有显示toast消息,我在logcat中也没有收到任何错误。 以下是代码段:

public class ManualControlsFragment extends Fragment {
    private TimePicker tp;
    private Calendar calendar;
    Handler mHandler;
    private Runnable scheduledTask;
    long pickedTimeInMillis=0;

   //some fragment methods

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        tp = (TimePicker) view.findViewById(R.id.lightTimePickerStart);
        tp.setIs24HourView(true);
        calendar = Calendar.getInstance();

        //get time picked in milliseconds
        tp.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() {
            @Override
            public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
                calendar.set(Calendar.HOUR_OF_DAY, hourOfDay);
                calendar.set(Calendar.MINUTE, minute);

                pickedTimeInMillis= calendar.getTimeInMillis();
            }
        });

        //Calendar instance to get current time
        Calendar cal = Calendar.getInstance();

        //get the difference to get the delay
        long timeDifference = pickedTimeInMillis - cal.getTimeInMillis();

        mHandler = new Handler();
        mHandler.postDelayed(scheduledTask, timeDifference);

        scheduledTask = new Runnable() {
            String text= "Bulb is now on";
            @Override
            public void run() {
                Toast.makeText(
                        getActivity(), text, Toast.LENGTH_LONG).show();
            }
        };

        return view;
    }

在阅读完评论和答案后,我编写了代码:

 getActivity().runOnUiThread(new Runnable() {
        @Override
        public void run() {
            new Handler().postDelayed(new Runnable() {
                String text= "Bulb is now on";
                @Override
                public void run() {
                    //Do something after 1 second
                    Toast.makeText(getActivity().getApplicationContext(), text, Toast.LENGTH_LONG).show();
                }
            }, timeDifference);
        }
    });

然而,只有当我启动应用程序时才会显示toast(当我启动它时,时间选择器上的时间是当前时间,这就是为什么我认为它会显示吐司的原因)。当我在应用程序运行时在时间选择器上设置时间时,不显示toast。

2 个答案:

答案 0 :(得分:1)

正如我在评论中所说,您需要更改代码中的顺序,以使其按您的意愿执行。

首先,在Handler的postDelayed()方法中初始化scheduledTask 之前,否则你所做的只是发布一个null Runnable。你的代码应该是:

scheduledTask = new Runnable() {
        String text= "Bulb is now on";
        @Override
        public void run() {
            Toast.makeText(
                    getActivity(), text, Toast.LENGTH_LONG).show();
        }
};
mHandler.postDelayed(scheduledTask, timeDifference);

其次,下面的代码(在onCreateView()方法内部):

Calendar cal = Calendar.getInstance();
//get the difference to get the delay
long timeDifference = pickedTimeInMillis - cal.getTimeInMillis();

会立即触发Toast,因为pickedTimeInMillis将 0 所以时间差将为负,这将向上舍入为0(因此立即执行)。如果你想要这个,请保留这部分代码,否则从onCreateView()中删除它。

第三,您需要在用户更改时间时发布Runnable 并调用OnTimeChangedListener侦听器。所以监听器中的代码应该是:

@Override
public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
            calendar.set(Calendar.HOUR_OF_DAY, hourOfDay);
            calendar.set(Calendar.MINUTE, minute);
            pickedTimeInMillis= calendar.getTimeInMillis();
            // at this point get the current time 
            Calendar cal = Calendar.getInstance();
            // now calculate the difference as the user actually selected a time
            long timeDifference = pickedTimeInMillis - cal.getTimeInMillis();
            // register the Runnable to run
            mHandler.postDelayed(scheduledTask, timeDifference);
        }

此外,不需要runOnUiThread(),因为您声明的Handler将在主线程上运行。

答案 1 :(得分:0)

您正在另一个线程上运行Toast,但您只能从主线程更新UI。请尝试更新Runnable run()中的代码,例如使用runOnUiThread()方法。