JobService 7.0 定时任务不生效
代码
// 构建JobInfo对象,传递给JobSchedulerService
JobInfo.Builder builder = new JobInfo.Builder(JOB_ID,new ComponentName(mContext, AliveJobService.class));
builder.setPeriodic(5000);
builder.setPersisted(true);
builder.setRequiresCharging(true);
JobInfo info = builder.build();
mJobScheduler.schedule(info);
这段定时任务在每隔5秒执行一次任务,Android 5.0和6.0系统能够正常运行.但是在Android7.0不能正常工作了。
https://stackoverflow.com/questions/38344220/job-scheduler-not-running-on-android-n/38774104
看万两片关于JobService 7.0(Nougat) 看完有几个疑问
1.如果想到在小于15分钟间隔执行为什么要设置setMinimumLatency()?
2.setBackoffCriteria(youtime, JobInfo.BACKOFF_POLICY_LINEAR)这个是有什么作用,如果不设置会怎么样?
3.如果设置obFinished(parameters, true)和obFinished(parameters, false)有什么区别?
4.如果想重复执行怎么操作?
想知道这些问题的答案肯定要看源码
package android.app.job; public class JobInfo implements Parcelable {
//... /**
* Amount of backoff a job has initially by default, in milliseconds.
*/
public static final long DEFAULT_INITIAL_BACKOFF_MILLIS = 30000L; // 30 seconds. /**
* Maximum backoff we allow for a job, in milliseconds.
*/
public static final long MAX_BACKOFF_DELAY_MILLIS = 5 * 60 * 60 * 1000; // 5 hours. public static final int BACKOFF_POLICY_LINEAR = 0; public static final int BACKOFF_POLICY_EXPONENTIAL = 1;
//默认指数
public static final int DEFAULT_BACKOFF_POLICY = BACKOFF_POLICY_EXPONENTIAL; /* Minimum interval for a periodic job, in milliseconds. */
private static final long MIN_PERIOD_MILLIS = 15 * 60 * 1000L; // 15 minutes /* Minimum flex for a periodic job, in milliseconds. */
private static final long MIN_FLEX_MILLIS = 5 * 60 * 1000L; // 5 minutes /**
* Specify that this job should be delayed by the provided amount of time.
* Because it doesn't make sense setting this property on a periodic job, doing so will
* throw an {@link java.lang.IllegalArgumentException} when
* {@link android.app.job.JobInfo.Builder#build()} is called.
* @param minLatencyMillis Milliseconds before which this job will not be considered for
* execution.
*/ public Builder setMinimumLatency(long minLatencyMillis) {
mMinLatencyMillis = minLatencyMillis;
mHasEarlyConstraint = true;
return this;
} /**
* 最小15分钟
*/
public static final long getMinPeriodMillis() {
return MIN_PERIOD_MILLIS;
} public Builder setPeriodic(long intervalMillis, long flexMillis) {
mIsPeriodic = true;
mIntervalMillis = intervalMillis;
mFlexMillis = flexMillis;
mHasEarlyConstraint = mHasLateConstraint = true;
return this;
} /**
* 最小15分钟 如果值比15分钟大取大的值
*/
public long getIntervalMillis() {
return intervalMillis >= getMinPeriodMillis() ? intervalMillis : getMinPeriodMillis();
} /**
* 最小5分钟
*/
public static final long getMinFlexMillis() {
return MIN_FLEX_MILLIS;
} /**
* Math.max(percentClamp, getMinFlexMillis())最小15分钟
* flexMillis 是setPeriodic(long intervalMillis, long flexMillis)第二参数,默认这个和intervalMillis
* clampedFlex的值最小值15分钟
*/
public long getFlexMillis() {
long interval = getIntervalMillis();//最小15分钟
long percentClamp = 5 * interval / 100; //取时间间隔的5%
//先取getMinFlexMillis()五分钟 和getIntervalMillis()的5%的取最大值
//然后和设置的setPeriodic(long intervalMillis, long flexMillis)中的flexMillis取最大值
//所有这里最小的值15分钟
long clampedFlex = Math.max(flexMillis, Math.max(percentClamp, getMinFlexMillis()));
//如果这个值比间隔小,去这个值,如果比间隔大去间隔值
return clampedFlex <= interval ? clampedFlex : interval;
} /**
* The amount of time the JobScheduler will wait before rescheduling a failed job. This value
* will be increased depending on the backoff policy specified at job creation time. Defaults
* to 5 seconds.
*/
public long getInitialBackoffMillis() {
return initialBackoffMillis;
} public Builder setBackoffCriteria(long initialBackoffMillis, int backoffPolicy) {
mBackoffPolicySet = true;
mInitialBackoffMillis = initialBackoffMillis;
mBackoffPolicy = backoffPolicy;
return this;
} //... }
JobInfo这里
看完这个类可以回答这个问题
1.如果想到在小于15分钟间隔执行为什么要设置.setMinimumLatency()
在7.0调用setPeriodic()之后在获取间隔时间getIntervalMillis() 强制使用了最小时间15分钟。所以想通过setPeriodic()来设置小于15分钟间隔是不行的。所以如果小于15分钟需要通过设置setMinimumLatency ()
public Builder setMinimumLatency(long minLatencyMillis) {
mMinLatencyMillis = minLatencyMillis;
mHasEarlyConstraint = true;
return this;
} /**
* 最小15分钟
*/
public static final long getMinPeriodMillis() {
return MIN_PERIOD_MILLIS;
} public Builder setPeriodic(long intervalMillis, long flexMillis) {
mIsPeriodic = true;
mIntervalMillis = intervalMillis;
mFlexMillis = flexMillis;
mHasEarlyConstraint = mHasLateConstraint = true;
return this;
} /**
* 最小15分钟 如果值比15分钟大取大的值
*/
public long getIntervalMillis() {
return intervalMillis >= getMinPeriodMillis() ? intervalMillis : getMinPeriodMillis();
}
1.getIntervalMillis()最小值15分钟
2.getFlexMillis()最小值15分钟
3.getMinFlexMillis最小值5分钟
andorid 7.1NJobSchedulerService源码
public final class JobSchedulerService extends com.android.server.SystemService
implements StateChangedListener, JobCompletedListener {
//... 862 /**
863 * Called when we have a job status object that we need to insert in our
864 * {@link com.android.server.job.JobStore}, and make sure all the relevant controllers know
865 * about.
866 */
867 private void startTrackingJob(JobStatus jobStatus, JobStatus lastJob) {
868 synchronized (mLock) {
869 final boolean update = mJobs.add(jobStatus);
870 if (mReadyToRock) {
871 for (int i = 0; i < mControllers.size(); i++) {
872 StateController controller = mControllers.get(i);
873 if (update) {
874 controller.maybeStopTrackingJobLocked(jobStatus, null, true);
875 }
876 controller.maybeStartTrackingJobLocked(jobStatus, lastJob);
877 }
878 }
879 }
880 } 882 /**
883 * Called when we want to remove a JobStatus object that we've finished executing. Returns the
884 * object removed.
先从 JobStore 中移除这个 job,因为 writeBack 为 true,则需要更新 jobxs.xml 文件,通知控制器,取消 track!
885 */ 886 private boolean stopTrackingJob(JobStatus jobStatus, JobStatus incomingJob,
887 boolean writeBack) {
888 synchronized (mLock) {
889 // Remove from store as well as controllers. 先从 JobStore 中移除这个 job,因为 writeBack 为 true,则需要更新 jobxs.xml 文件!
890 final boolean removed = mJobs.remove(jobStatus, writeBack);
891 if (removed && mReadyToRock) {
892 for (int i=0; i<mControllers.size(); i++) {
893 StateController controller = mControllers.get(i);//通知控制器,取消 track!
894 controller.maybeStopTrackingJobLocked(jobStatus, incomingJob, false);
895 }
896 }
897 return removed;
898 }
899 } 1026 /**
1027 * A job just finished executing. We fetch the
1028 * {@link com.android.server.job.controllers.JobStatus} from the store and depending on
1029 * whether we want to reschedule we readd it to the controllers.
1030 * @param jobStatus Completed job.
1031 * @param needsReschedule Whether the implementing class should reschedule this job.
1032 */
1033 @Override
1034 public void onJobCompleted(JobStatus jobStatus, boolean needsReschedule) {
1035 if (DEBUG) {
1036 Slog.d(TAG, "Completed " + jobStatus + ", reschedule=" + needsReschedule);
1037 }
1038 // Do not write back immediately if this is a periodic job. The job may get lost if system
1039 // shuts down before it is added back.
1040 if (!stopTrackingJob(jobStatus, null, !jobStatus.getJob().isPeriodic())) {//调用了 stopTrackingJob 将这个 job 从 JobStore 和 controller 中移除:
1041 if (DEBUG) {
1042 Slog.d(TAG, "Could not find job to remove. Was job removed while executing?");
1043 }
1044 // We still want to check for jobs to execute, because this job may have
1045 // scheduled a new job under the same job id, and now we can run it.
1046 mHandler.obtainMessage(MSG_CHECK_JOB_GREEDY).sendToTarget();
1047 return;
1048 }
1049 // Note: there is a small window of time in here where, when rescheduling a job,
1050 // we will stop monitoring its content providers. This should be fixed by stopping
1051 // the old job after scheduling the new one, but since we have no lock held here
1052 // that may cause ordering problems if the app removes jobStatus while in here.
1053 if (needsReschedule) {
1054 JobStatus rescheduled = getRescheduleJobForFailure(jobStatus);
1055 startTrackingJob(rescheduled, jobStatus);
1056 } else if (jobStatus.getJob().isPeriodic()) {//如果JobInfo调用setPeriodic会设置true
1057 JobStatus rescheduledPeriodic = getRescheduleJobForPeriodic(jobStatus);
1058 startTrackingJob(rescheduledPeriodic, jobStatus);
1059 }
1060 reportActive();
1061 mHandler.obtainMessage(MSG_CHECK_JOB_GREEDY).sendToTarget();//发送 MSG_CHECK_JOB_GREEDY 给 JobSchedulerService.JobHandler
1062 } 947 /**
948 * Reschedules the given job based on the job's backoff policy. It doesn't make sense to
949 * specify an override deadline on a failed job (the failed job will run even though it's not
950 * ready), so we reschedule it with {@link JobStatus#NO_LATEST_RUNTIME}, but specify that any
951 * ready job with {@link JobStatus#numFailures} > 0 will be executed.
952 *
953 * @param failureToReschedule Provided job status that we will reschedule.
954 * @return A newly instantiated JobStatus with the same constraints as the last job except
955 * with adjusted timing constraints.
956 *
957 * @see JobHandler#maybeQueueReadyJobsForExecutionLockedH
958 */
959 private JobStatus getRescheduleJobForFailure(JobStatus failureToReschedule) {
960 final long elapsedNowMillis = SystemClock.elapsedRealtime();
961 final JobInfo job = failureToReschedule.getJob();
962
963 final long initialBackoffMillis = job.getInitialBackoffMillis();
964 final int backoffAttempts = failureToReschedule.getNumFailures() + 1;
965 long delayMillis;
966
967 switch (job.getBackoffPolicy()) {
968 case JobInfo.BACKOFF_POLICY_LINEAR:
969 delayMillis = initialBackoffMillis * backoffAttempts;
970 break;
971 default:
972 if (DEBUG) {
973 Slog.v(TAG, "Unrecognised back-off policy, defaulting to exponential.");
974 }
975 case JobInfo.BACKOFF_POLICY_EXPONENTIAL:
976 delayMillis =
977 (long) Math.scalb(initialBackoffMillis, backoffAttempts - 1);
978 break;
979 }
980 delayMillis =
981 Math.min(delayMillis, JobInfo.MAX_BACKOFF_DELAY_MILLIS);//和5小时比较
982 JobStatus newJob = new JobStatus(failureToReschedule, elapsedNowMillis + delayMillis,
983 JobStatus.NO_LATEST_RUNTIME, backoffAttempts);//构建新的JobStatu 设置下次时间 设置backoff次数
984 for (int ic=0; ic<mControllers.size(); ic++) {
985 StateController controller = mControllers.get(ic);
986 controller.rescheduleForFailure(newJob, failureToReschedule);
987 }
988 return newJob;
989 } 991 /**
992 * Called after a periodic has executed so we can reschedule it. We take the last execution
993 * time of the job to be the time of completion (i.e. the time at which this function is
994 * called).
995 * This could be inaccurate b/c the job can run for as long as
996 * {@link com.android.server.job.JobServiceContext#EXECUTING_TIMESLICE_MILLIS}, but will lead
997 * to underscheduling at least, rather than if we had taken the last execution time to be the
998 * start of the execution.
999 * @return A new job representing the execution criteria for this instantiation of the
1000 * recurring job.
1001 */
1002 private JobStatus getRescheduleJobForPeriodic(JobStatus periodicToReschedule) {
1003 final long elapsedNow = SystemClock.elapsedRealtime();
1004 // Compute how much of the period is remaining.
1005 long runEarly = 0L;
1006
1007 // If this periodic was rescheduled it won't have a deadline.
1008 if (periodicToReschedule.hasDeadlineConstraint()) {
1009 runEarly = Math.max(periodicToReschedule.getLatestRunTimeElapsed() - elapsedNow, 0L);
1010 }
1011 long flex = periodicToReschedule.getJob().getFlexMillis();
1012 long period = periodicToReschedule.getJob().getIntervalMillis();//间隔时间
1013 long newLatestRuntimeElapsed = elapsedNow + runEarly + period;
1014 long newEarliestRunTimeElapsed = newLatestRuntimeElapsed - flex;
1015
1016 if (DEBUG) {
1017 Slog.v(TAG, "Rescheduling executed periodic. New execution window [" +
1018 newEarliestRunTimeElapsed/1000 + ", " + newLatestRuntimeElapsed/1000 + "]s");
1019 }
1020 return new JobStatus(periodicToReschedule, newEarliestRunTimeElapsed,
1021 newLatestRuntimeElapsed, 0 /* backoffAttempt */);
1022 }
//...
}
3.如果设置obFinished(parameters, true)和obFinished(parameters, false)有什么区别?
这里关键在onJobCompleted
首先调用了 stopTrackingJob 将这个 job 从 JobStore 和 controller 中移除,因为之前已经移除过了,所以这个 stopTrackingJob 的返回值为 false
@Override
public void onJobCompleted(JobStatus jobStatus, boolean needsReschedule) {
if (DEBUG) {
Slog.d(TAG, "Completed " + jobStatus + ", reschedule=" + needsReschedule);
}
// Do not write back immediately if this is a periodic job. The job may get lost if system
// shuts down before it is added back.
// 再次停止 track 这个 job,这里 stopTrackingJob 的返回值为 false!
if (!stopTrackingJob(jobStatus, null, !jobStatus.getJob().isPeriodic())) {
if (DEBUG) {
Slog.d(TAG, "Could not find job to remove. Was job removed while executing?");
}
// We still want to check for jobs to execute, because this job may have
// scheduled a new job under the same job id, and now we can run it.
// 发送 MSG_CHECK_JOB_GREEDY,继续执行其他的 job,然后直接 return
mHandler.obtainMessage(MSG_CHECK_JOB_GREEDY).sendToTarget();
return;
}
// Note: there is a small window of time in here where, when rescheduling a job,
// we will stop monitoring its content providers. This should be fixed by stopping
// the old job after scheduling the new one, but since we have no lock held here
// that may cause ordering problems if the app removes jobStatus while in here.
if (needsReschedule) {
JobStatus rescheduled = getRescheduleJobForFailure(jobStatus);
startTrackingJob(rescheduled, jobStatus);
} else if (jobStatus.getJob().isPeriodic()) {
JobStatus rescheduledPeriodic = getRescheduleJobForPeriodic(jobStatus);
startTrackingJob(rescheduledPeriodic, jobStatus);
}
reportActive();
mHandler.obtainMessage(MSG_CHECK_JOB_GREEDY).sendToTarget();
}
如果是true那么needsReschedule的也是true执行就是这段代码
if (needsReschedule) {
JobStatus rescheduled = getRescheduleJobForFailure(jobStatus);
startTrackingJob(rescheduled, jobStatus);
}
这段点主要调用getRescheduleJobForFailure
private JobStatus getRescheduleJobForFailure(JobStatus failureToReschedule) {
final long elapsedNowMillis = SystemClock.elapsedRealtime();
final JobInfo job = failureToReschedule.getJob(); final long initialBackoffMillis = job.getInitialBackoffMillis();//获取setBackoffCriteria设置的值,如果没有设置默认是30秒
final int backoffAttempts = failureToReschedule.getNumFailures() + 1;
long delayMillis; switch (job.getBackoffPolicy()) {//是线性还是指数级别策略
case JobInfo.BACKOFF_POLICY_LINEAR:
delayMillis = initialBackoffMillis * backoffAttempts;//随着失败的次数越多这个值也越大
break;
default:
if (DEBUG) {
Slog.v(TAG, "Unrecognised back-off policy, defaulting to exponential.");
}
case JobInfo.BACKOFF_POLICY_EXPONENTIAL:
delayMillis =
(long) Math.scalb(initialBackoffMillis, backoffAttempts - 1);
break;
}
//getNumFailures值越大这个值也越大间隔时间会越来越长
delayMillis =
Math.min(delayMillis, JobInfo.MAX_BACKOFF_DELAY_MILLIS);//和5小时比较
JobStatus newJob = new JobStatus(failureToReschedule, elapsedNowMillis + delayMillis,
JobStatus.NO_LATEST_RUNTIME, backoffAttempts);//构建新的JobStatu 设置下次时间 设置backoff次数
for (int ic=0; ic<mControllers.size(); ic++) {
StateController controller = mControllers.get(ic);
controller.rescheduleForFailure(newJob, failureToReschedule);
}
return newJob;
}
看完这段代码可以回答
2.setBackoffCriteria(youtime, JobInfo.BACKOFF_POLICY_LINEAR)这个是有什么作用,如果不设置会怎么样?
这个代码可以看出如果不想默认的时间是30秒,默认指数DEFAULT_BACKOFF_POLICY = BACKOFF_POLICY_EXPONENTIAL
就必须通过setBackoffCriteria()来设置时间 和线性或者指数增长策略
如果是false 那么needsReschedule的也是false 执行就是这段代码
这段如果设置了setPeriodic()被调用那么isPeriodic()是true则下面代码被执行
else if (jobStatus.getJob().isPeriodic()) {
JobStatus rescheduledPeriodic = getRescheduleJobForPeriodic(jobStatus);
startTrackingJob(rescheduledPeriodic, jobStatus);
}
这段代码主要调用getRescheduleJobForPeriodic方法
private JobStatus getRescheduleJobForPeriodic(JobStatus periodicToReschedule) {
final long elapsedNow = SystemClock.elapsedRealtime();
// Compute how much of the period is remaining.
long runEarly = 0L; // If this periodic was rescheduled it won't have a deadline.
if (periodicToReschedule.hasDeadlineConstraint()) {
runEarly = Math.max(periodicToReschedule.getLatestRunTimeElapsed() - elapsedNow, 0L);
}
long flex = periodicToReschedule.getJob().getFlexMillis();//最小15分钟
long period = periodicToReschedule.getJob().getIntervalMillis();//最小15分钟
long newLatestRuntimeElapsed = elapsedNow + runEarly + period;
long newEarliestRunTimeElapsed = newLatestRuntimeElapsed - flex; return new JobStatus(periodicToReschedule, newEarliestRunTimeElapsed,
newLatestRuntimeElapsed, 0 /* backoffAttempt */);
}
//...
}
4.如果想重复执行怎么操作?
1.设置jobFinished((JobParameters) msg.obj, true);设置true
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
jobFinished((JobParameters) msg.obj, true);
} else {
jobFinished((JobParameters) msg.obj, false);
}
2.在jobFinished在jobFinished之前重新调用startJobScheduler
以下是android7.0怎么设置startJobScheduler执行的
public void startJobScheduler() {
if (DEBUG) {
Log.i(TAG, "startJobScheduler");
}
int id = JOB_ID;
if (DEBUG) {
Log.i(TAG, "开启AstJobService id=" + id);
}
mJobScheduler.cancel(id);
JobInfo.Builder builder = new JobInfo.Builder(id, new ComponentName(mContext, AstJobService.class));
if (Build.VERSION.SDK_INT >= 24) {
builder.setMinimumLatency(JobInfo.DEFAULT_INITIAL_BACKOFF_MILLIS); //执行的最小延迟时间
builder.setOverrideDeadline(JobInfo.DEFAULT_INITIAL_BACKOFF_MILLIS); //执行的最长延时时间
builder.setMinimumLatency(JobInfo.DEFAULT_INITIAL_BACKOFF_MILLIS);
builder.setBackoffCriteria(JobInfo.DEFAULT_INITIAL_BACKOFF_MILLIS, JobInfo.BACKOFF_POLICY_LINEAR);//线性重试方案
} else {
builder.setPeriodic(JobInfo.DEFAULT_INITIAL_BACKOFF_MILLIS);
}
builder.setPersisted(true); // 设置设备重启时,执行该任务
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
builder.setRequiresCharging(true); // 当插入充电器,执行该任务
JobInfo info = builder.build();
mJobScheduler.schedule(info); //开始定时执行该系统任务
}
JobService 7.0 定时任务不生效的更多相关文章
- Linux 定时任务不生效的问题
Linux 中定时任务不生效的问题屡见不鲜, 本质原因是: 登录式 shell & 非登录式 shell. 登录式 shell & 非登录式 shell 登录式 shell 有: su ...
- ECSTORE2.0 定时任务配置
今天在配置ecstore2.0的定时任务时候,发现ECOS后台每30秒通过JS调用 http://localhost/ecstore-bugfix/index.php/shopadmin/index. ...
- jenkins定时任务未生效解决
近期在配置jenkins定时任务时,发现未生效,并没有按时触发任务 解决思路: 1.先查看下我们的定时任务有没有选择正确,如下说明: Poll SCM:定时检查源码变更,如果有更新就checkout最 ...
- 转:Selenium2.0 click()不生效的解决办法
除了http://573301735.com/?p=5126讲的,昨天又发现一个让我1个小时生不如死的问题,就是使用两个不同的配置文件来初始化driver,findelement方法获取到的坐标居然不 ...
- SpringBoot2.0+ DataSourceInitializer不生效的问题
1.在url后声明时区 2.更换mysql6.0+的驱动 3.配置属性initialization-mode 为 always 我就是这样解决问题的,如果没解决的话,请在留言处指出错误.谢谢
- Servlet4.0 注解不生效解决
当我们创建好一个4.0的servlet 生成的注解大概是这样 name=xxxxx 默认的是不具有效果的 你可以有两种方式 1.去掉属性name,3.0就是这样子的 2.非要有name属性 请加上u ...
- Kerberos kinit crontab定时任务不生效的问题解决
问题 有这样一个定时任务 1 */12 * * * kinit -kt xxxxxx.keytab principle 这样写每天 12点,执行一次. 但是服务器的应用程序报错: GSS initia ...
- Quartz3.0定时任务学习之异步调度器
前言 Quartz3与Quartz2的主要区别有两点: 1,Quartz3将它的资源类库拆的更细了,比如,想使用Quartz3开发,最少要引用Quartz,Quartz.Jobs,Quartz.Plu ...
- CSS中margin: 0 auto;样式没有生效
问题:有两个元素: A, B.两则是嵌套关系,A是B的父节点.A和B都是块元素.当在A上设置:margin: 0 auto的时候,B并没有在页面中居中. margin: 0 auto 为什么没有生效? ...
随机推荐
- 关于用Date类计算活了多少天和用Calendar类计算闰年的demo
在javaSE阶段,Date类和Calendar类以后会经常用到 这两个类当中的一些常用方法 通过两个demo 进行学习和练习 第一个要求如下:让用户自己输入yyyy-MM-dd 格式的年月日 然后得 ...
- 利用using和try/finally语句来清理资源
使用非托管资源的类型必须实现IDisposable接口的Dispose()方法来精确的释放系统资源..Net环境的这一规则使得释放资源代码的职责 是类型的使用者,而不是类型或系统.因此,任何时候你在使 ...
- 修改Oracle游标数及排查游标问题相关SQL
查看当前游标数show parameter open_cursors; 修改游标最大数 ; commit; 查看游标消费情况 select o.sid, osuser, machine, count( ...
- ArcGIS Server GP服务使用常见错误总结
ArcGIS GP服务问题列表 输入参数错误 在使用GP服务时,从创建模型到发布服务,再到调用服务,整个过程都需要注意输入参数和输出参数的问题.GP服务支持的输入和输出参数可详见 http://hel ...
- C#实现远程开机(局域网测试通过)
首先介绍相关知识. UDP协议 UDP 是User Datagram Protocol的简称, 中文名是用户数据报协议,是OSI(Open System Interconnection,开放式系统互联 ...
- 利用excel制作二维码
1 将想要通过扫描二维码访问的目标网址放入A1单位格 2 在excel 编辑区右击选择“自定义功能区” 3 然后将“开发者工具”选上 4 点击菜单栏的“开发者工具---插入--->其他控件” 5 ...
- 搭建TensorFlow
网上有许多在线安装TensorFlow框架的,我试了好多,结果安装时间长先不说,还总是出现一些问题,然后我就想着离线安装,成功了,与大家分享! (1)首先,需要下载离线安装的TensorFlow包,可 ...
- C++基础学习10:继承
继承是类与类之间的关系,是一个很简单很直观的概念,与现实世界中的继承(例如儿子继承父亲财产)类似. 继承可以理解为一个类从另一个类获取方法(函数)和属性(成员变量)的过程.如果类B继承于类A,那么B就 ...
- 对状压dp的见解
看了好几篇博客,终于对一些简单的状压dp有了点了解.就像HDU1074. 有个博客:https://blog.csdn.net/bentutut/article/details/70147989 感觉 ...
- Django2.0以上版本的URL的正则匹配问题
正则表达式形式的URL匹配问题: 1.导入re_path from django.urls import path,re_path 2.进行正则匹配 re_path('detail-(\d+).htm ...