在获得时间选择器和当前时间之间的时间延迟后使用 postDelayed 安排任务
Scheduling a task using postDelayed after getting time delay between time picker and current time
我在我的片段中写了一段代码,它将在用户在 Time Picker
上选择的特定时间显示 Toast
消息。时间延迟是通过从时间选择器时间(以毫秒为单位)中减去当前时间(以毫秒为单位)来计算的。
但是,没有显示 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
,但您只能从主线程更新 UI。例如,尝试更新 Runnable run()
中的代码以使用 runOnUiThread()
方法。
正如我在评论中所说,您需要更改代码中的顺序以使其按您的意愿执行。
首先,在 Handler 的 postDelayed() 方法中使用它之前 初始化 scheduledTask,否则您所做的只是 post 一个空的 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() 中删除。
第三,您需要 post 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);
}
此外,不需要 运行OnUiThread(),因为您声明的处理程序将 运行 在主线程上。
我在我的片段中写了一段代码,它将在用户在 Time Picker
上选择的特定时间显示 Toast
消息。时间延迟是通过从时间选择器时间(以毫秒为单位)中减去当前时间(以毫秒为单位)来计算的。
但是,没有显示 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
,但您只能从主线程更新 UI。例如,尝试更新 Runnable run()
中的代码以使用 runOnUiThread()
方法。
正如我在评论中所说,您需要更改代码中的顺序以使其按您的意愿执行。
首先,在 Handler 的 postDelayed() 方法中使用它之前 初始化 scheduledTask,否则您所做的只是 post 一个空的 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() 中删除。
第三,您需要 post 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);
}
此外,不需要 运行OnUiThread(),因为您声明的处理程序将 运行 在主线程上。