程序性能优化之耗电优化(四)下篇

本文详细介绍了AndroidJobScheduler的工作原理,包括JobInfo的设置(如任务ID、网络条件、周期、延迟等),并展示了如何在实际项目中使用JobService和JobInfo.Builder。通过实例分析了各种约束条件对任务调度的影响。
摘要由CSDN通过智能技术生成

public abstract boolean onStartJob(JobParameters params);
/停止任务方法/
public abstract boolean onStopJob(JobParameters params);

JobInfo是为了规定任务启动的规则,通过JobScheduler的建造者模式来设置规则

// jobId每个Job任务的id
int jobId = 1;
// 指定你需要执行的JobService
ComponentName name = new ComponentName(getPackageName(), MyJobService.class.getName()));
JobInfo.Builder builder = new JobInfo.Bulider(jobId, name);
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_NONE); //设置需要的网络条件,默认NETWORK_TYPE_NONE
builder.setPeriodic(3000);//设置间隔时间,不断的触发任务的启动
builder.setMinimumLatency(3000);// 设置任务运行最少延迟时间,与setPeriodic相似,只是间隔时间不确定,不能与setPeriodic一起使用,
builder.setOverrideDeadline(50000);// 设置deadline,若到期还没有达到规定的条件则会开始执行
builder.setRequiresCharging(true);// 设置是否充电的条件,默认false
builder.setRequiresDeviceIdle(false);// 设置手机是否空闲的条件,默认false
builder.setPersisted(true);//设备重启之后你的任务是否还要继续执行
JobInfo info = builder.build();

1.3 各种使用

(1)基础代码
首先我贴出一个最基本JobSheduler API的使用代码,后面的测试代码都是通过这个段代码稍微改动而来的,大家可以边看博客,自己试一试代码的效果

MyJobService就是显示一个Toast,之所以最后是通过Handler实现,是因为想要模仿耗时任务,毕竟这是一个后台Service,使用场景很多是耗时任务。

如果要模拟的不是耗时任务,那就去掉这个Handler,然后将onStartJob的返回值设置为false。因为在onStartJob里返回false代表你任务执行完成了,他会开始计时为下一次任务的执行做准备,如果返回true,代表任务还在执行,需要我们自己调用jobFinished(param,true)函数来告诉JobService任务执行完成了

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)//API需要在21及以上
public class MyJobService extends JobService {

private Handler handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
Toast.makeText(MyJobService.this, “MyJobService”, Toast.LENGTH_SHORT).show();
JobParameters param = (JobParameters) msg.obj;
jobFinished(param, true);

return true;
}
});

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}

@Override
public boolean onStartJob(JobParameters params) {
Message m = Message.obtain();
m.obj = params;
handler.sendMessageDelayed(m, 2000);
return true;
}

@Override
public boolean onStopJob(JobParameters params) {
handler.removeCallbacksAndMessages(null);
return false;
}
}

因为是Service还需要在AndroidManifest注册,只是注册时还需要设置一个特殊的权限

activity就是设置一个按钮,点击触发任务的调度开启

public class MainActivity extends AppCompatActivity {

Button btn;
private JobScheduler mJobScheduler;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

btn = (Button) findViewById(R.id.btn);
mJobScheduler = (JobScheduler) getSystemService( Context.JOB_SCHEDULER_SERVICE );
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
JobInfo.Builder builder = new JobInfo.Builder( 1,
new ComponentName( getPackageName(), MyJobService.class.getName() ) );
builder.setMinimumLatency(2000);
if( mJobScheduler.schedule( builder.build() ) <= 0 ) {
//If something goes wrong
}
}
}
});
}
}

(2)各种使用情况
setMinimumLatency
基础代码里通过setMinimumLatency(2000)设置任务最少执行延缓,虽然是最少延缓,但是在我的测试下,发现这个延缓时间比较随机,有时候能够在两秒后开始执行任务,不过一般的都是7、8秒开始执行任务。在任务执行完成后,他们会初始化延缓时间,开始计时,准备下一次任务的执行。

setPeriodic
在基础代码里,我把setMinimumLatency(2000)代码换成setPeriodic(2000)

这里要注意setMinimumLatency和setPeriodic不能一起设置,会报错,我想是因为他们都有周期设置任务启动的特性有关。

当我运行代码,应用却没有按照两秒周期的时间触发任务,然后我在控制台看到了如下log

W/JobInfo: Specified interval for 1 is +2s0ms. Clamped to +15m0s0ms
W/JobInfo: Specified flex for 1 is +2s0ms. Clamped to +5m0s0ms

就是说你这个间隔必须在15分钟以上,这个规定是在Android7.0开始有的,所以如果需要比较频繁的调用任务,还是需要使用setMinimumLatency来完成。
setRequireNetworkType
如果我把setRequireNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)替换setMinimumLatency(2000),运行程序会报错

java.lang.IllegalArgumentException: You’re trying to build a job with no constraints, this is not allowed.

我得出结论setRequireNetworkType不算主约束条件,需要依附像setMinimumLatency类似的主约束条件,那好我添加一个setMinimumLatency(2000000),再来运行,之所以把最少延缓的时间设置的这么大,是因为只要满足设置的条件之一就会启动任务。
然后运行程序,当我们连接WIFI,就会触发任务,市面很多通知栏广告就是使用这个类型的网络类型触发的,因为JobInfo规定的网络类型还有几个,我就不试了,大家可以自己试试

public static final int NETWORK_TYPE_ANY = 1;
public static final int NETWORK_TYPE_METERED = 4;
public static final int NETWORK_TYPE_NONE = 0;
public static final int NETWORK_TYPE_NOT_ROAMING = 3;
public static final int NETWORK_TYPE_UNMETERED = 2;

setRequiresChargin
setRequiresChargin不是主约束条件, 将setRequiresChargin(true)替换setRequireNetworkType(JobInfo.NETWORK_TYPE_UNMETERED),运行程序。
setRequiresChargin(true)指的是监听充电,如果给的false就不监听,所以默认就是false

setOverrideDeadline
如果jobInfo配置如下

JobInfo jobInfo = new JobInfo.Builder(1, new ComponentName(getPackageName(), MyJobService.class.getName()))
.setPeriodic(2000)
.setOverrideDeadline(10000)
.build();

运行程序会报错

java.lang.IllegalArgumentException: Can’t call setOverrideDeadline() on a periodic job.
如果我去掉setPeriodic(2000)这行代码,在运行程序,我发现点击一次按钮就会立即启动任务,也就是弹出Toast,但是后面会继续启动任务,只是间隔时间比10秒时间要长得多

现在JobInfo代码我写成如下

JobInfo jobInfo = new JobInfo.Builder(1, new ComponentName(getPackageName(), MyJobService.class.getName()))
.setOverrideDeadline(5000)
.setMinimumLatency(3000)
.build();

程序运行正常,符合预期
setPersisted
setPersisted不是一个主约束条件,当JobInfo代码如下

JobInfo jobInfo = new JobInfo.Builder(1, new ComponentName(getPackageName(), MyJobService.class.getName()))
//.setMinimumLatency(10000)
.setPersisted(true)
.build();

按下按钮,然后重启手机,没有效果。。。。。

setRequiresDeviceIdle
代码如下

JobInfo jobInfo = new JobInfo.Builder(1, new ComponentName(getPackageName(), MyJobService.class.getName()))
.setRequiresDeviceIdle(true)
.build();

额,手机空闲状态,明明其他手机程序都退出来,半天等不到,

(3)JobSheduler任务调度
之前我们在基础代码里看到了以下代码,就是判断任务是否创建成功,但是这还不是任务调度的范围

if( mJobScheduler.schedule( builder.build() ) <= 0 ) {
//If something goes wrong
}

首先我们看看cancel函数的效果,activity的代码里加一个button,为了触发cancel函数

public class MainActivity extends AppCompatActivity {

Button btn, btn_pause;
private JobScheduler mJobScheduler;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

btn = (Button) findViewById(R.id.btn);
btn_pause = (Button) findViewById(R.id.btn_pause) ;
mJobScheduler = (JobScheduler) getSystemService( Context.JOB_SCHEDULER_SERVICE );
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
JobInfo.Builder builder = new JobInfo.Builder( 1,
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

要如何成为Android架构师?

搭建自己的知识框架,全面提升自己的技术体系,并且往底层源码方向深入钻研。
大多数技术人喜欢用思维脑图来构建自己的知识体系,一目了然。这里给大家分享一份大厂主流的Android架构师技术体系,可以用来搭建自己的知识框架,或者查漏补缺;

对应这份技术大纲,我也整理了一套Android高级架构师完整系列的视频教程,主要针对3-5年Android开发经验以上,需要往高级架构师层次学习提升的同学,希望能帮你突破瓶颈,跳槽进大厂;

最后我必须强调几点:

1.搭建知识框架可不是说你整理好要学习的知识顺序,然后看一遍理解了能复制粘贴就够了,大多都是需要你自己读懂源码和原理,能自己手写出来的。
2.学习的时候你一定要多看多练几遍,把知识才吃透,还要记笔记,这些很重要! 最后你达到什么水平取决你消化了多少知识
3.最终你的知识框架应该是一个完善的,兼顾广度和深度的技术体系。然后经过多次项目实战积累经验,你才能达到高级架构师的层次。

你只需要按照在这个大的框架去填充自己,年薪40W一定不是终点,技术无止境

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!

知识才吃透,还要记笔记,这些很重要! 最后你达到什么水平取决你消化了多少知识
3.最终你的知识框架应该是一个完善的,兼顾广度和深度的技术体系。然后经过多次项目实战积累经验,你才能达到高级架构师的层次。

你只需要按照在这个大的框架去填充自己,年薪40W一定不是终点,技术无止境

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
  • 30
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值