Android Priority Job Queue (Job Manager)(一)

本文介绍了一种Android应用中用于管理后台线程任务的框架——AndroidPriorityJobQueue(JobManager),该框架能有效解决线程任务的调度管理问题,并提供了一个简单的示例来演示如何在项目中初始化并使用它。


Android Priority Job Queue (Job Manager)(一)


一、为什么要引入Android Priority Job Queue (Job Manager)?
如今的APP开发中,几乎绝大多数APP没有不需要后台线程操作和运行的任务,Android平台自身提供了一些后台线程的编程实现模型和API。比如常见的主流后台+线程处理方式:
A、 AsyncTask,
B、 Loaders,
C、 以及更复杂的Service组合线程池(Thread Pool),
D、Java的Thread结合Handler。
等等。
但是以上方式的问题很多,尤其是在耦合到Android本身的Activity或Fragment生命周期时候,要处理各种实际的场景,还有就是当在线程操作中如果处理失败,又该怎么办?有些情况,比如当用户在WIFI或者2G/3G/4G不同网络时候的不同网络加载策略。假设用户在发送一条消息到服务器,但是在线程发送过程中网络中断,在一定时延后网络又接通,此时线程又该如何决定发送任务的再次处理?如果使用Java Thread,Android本身又不允许在主线程外更新UI。如果使用Service,那么还要解决Service和,等等等诸如此类问题全部丢到线程中处理,将会额外但又不得不处理多种状态情况。
所以,为解决上述问题,就需要引入一种相对完善、可以解决后台+线程的简单易用的线程任务调度管理框架,为此引入Android Priority Job Queue (Job Manager)。
Android Priority Job Queue (Job Manager)是github上的一个Android开源项目,项目主页是:https://github.com/yigit/android-priority-jobqueue
Android Priority Job Queue (Job Manager)在其项目主页有完整的项目研究背景和作用,简单概括起来就是简化了Android涉及到的后台线程编程开发工作,使得开发者从后台线程繁琐的开发和代码维护中解脱出来,专注于业务逻辑。

二、Android Priority Job Queue (Job Manager)使用简介。

(1) Android Priority Job Queue (Job Manager)首先需要初始化和配置,在初始化和配置阶段,Android Priority Job Queue (Job Manager)类似Java线程池,写一个MyApplication继承自
Android Application,在此完成初始化。MyApplication.java:

package zhangphil.app;

import android.app.Application;
import android.util.Log;

import com.birbit.android.jobqueue.JobManager;
import com.birbit.android.jobqueue.config.Configuration;
import com.birbit.android.jobqueue.log.CustomLogger;

/**
 * Created by Phil on 2016/10/9.
 */
public class MyApplication extends Application {
    private JobManager jobManager;

    private static MyApplication instance;

    public MyApplication() {
        instance = this;
    }

    public static MyApplication getInstance() {
        return instance;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        getJobManager();// ensure it is created
    }

    public synchronized JobManager getJobManager() {
        if (jobManager == null) {
            configureJobManager();
        }

        return jobManager;
    }

    private void configureJobManager() {
        Configuration.Builder builder = new Configuration.Builder(this)
                .customLogger(new CustomLogger() {
                    private static final String TAG = "zhangphil job";

                    @Override
                    public boolean isDebugEnabled() {
                        return true;
                    }

                    @Override
                    public void d(String text, Object... args) {
                        Log.d(TAG, String.format(text, args));
                    }

                    @Override
                    public void e(Throwable t, String text, Object... args) {
                        Log.e(TAG, String.format(text, args), t);
                    }

                    @Override
                    public void e(String text, Object... args) {
                        Log.e(TAG, String.format(text, args));
                    }

                    @Override
                    public void v(String text, Object... args) {

                    }
                })
                .minConsumerCount(1)//always keep at least one consumer alive
                .maxConsumerCount(3)//up to 3 consumers at a time
                .loadFactor(3)//3 jobs per consumer
                .consumerKeepAlive(120);//wait 2 minute

        jobManager = new JobManager(builder.build());
    }
}

实际上在自己的项目中,Android Priority Job Queue (Job Manager)的初始化工作基本上不用做修改大体按照上面的写就好了,调整的地方在于任务数量这些有关系统性能开销的地方控制。
写完了记得要在Androidmainfest.xml写到application下面:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="zhangphil.app">

    <application
        android:name=".MyApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>


(2)写一个请求的任务逻辑,这是Android Priority Job Queue (Job Manager)使用的关键地方。首先需要继承自Android Priority Job Queue (Job Manager)得Job类,我写了一个测试的MyJob类,在此类中用于完成后台+线程的任务操作,Android Priority Job Queue (Job Manager)的Job有些类似于Java的Runnable,可以比照Java的Runnable理解Android Priority Job Queue (Job Manager)的Job。耗时线程任务在onRun里面做,MyJob.java:

package zhangphil.app;

import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;

import com.birbit.android.jobqueue.Job;
import com.birbit.android.jobqueue.Params;
import com.birbit.android.jobqueue.RetryConstraint;

/**
 * Created by Phil on 2016/10/9.
 */
public class MyJob extends Job {

    private String tag;

    public MyJob(String tag) {
        super(new Params(500).requireNetwork().persist().groupBy(tag));
        this.tag = tag;
        Log.d(tag, "初始化");
    }

    @Override
    public void onAdded() {
        Log.d(tag, "添加任务");
    }

    //在这里面放置耗时的后台线程化任务
    @Override
    public void onRun() throws Throwable {
        Log.d(tag, "开始运行...");

        int i = 0;
        while (true) {
            i++;

            SystemClock.sleep(2000);
            Log.d(tag, String.valueOf(i));
            if (i == 10)
                break;
        }

        Log.d(tag, "完成");
    }

    @Override
    protected RetryConstraint shouldReRunOnThrowable(@NonNull Throwable throwable, int runCount, int maxRunCount) {
        // An error occurred in onRun.
        // Return value determines whether this job should retry or cancel. You can further
        // specify a backoff strategy or change the job's priority. You can also apply the
        // delay to the whole group to preserve jobs' running order.

        Log.d(tag, "runCount:" + runCount);

        return RetryConstraint.createExponentialBackoff(runCount, 1000);
    }

    @Override
    protected void onCancel(int cancelReason, @Nullable Throwable throwable) {

    }
}


(3)测试的MainActivity.java:

package zhangphil.app;

import android.app.Activity;
import android.os.Bundle;

import com.birbit.android.jobqueue.JobManager;

public class MainActivity extends Activity {

    private JobManager jobManager;

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

        jobManager=MyApplication.getInstance().getJobManager();

        jobManager.addJobInBackground(new MyJob("任务1")); //启动任务,跑!
        //jobManager.addJobInBackground(new MyJob("任务2"));
        //jobManager.addJobInBackground(new MyJob("任务3"));
        //jobManager.addJobInBackground(new MyJob("任务4"));
        //jobManager.addJobInBackground(new MyJob("任务5"));
        //jobManager.addJobInBackground(new MyJob("任务6"));
    }
}


附录我写的Android线程相关文章:
【1】《Java线程池:ExecutorService,Executors》链接地址:http://blog.csdn.net/zhangphil/article/details/43898637 
【2】《Java线程池及Future、Callable获得线程返回结果【Java线程池系列2】》链接地址:http://blog.csdn.net/zhangphil/article/details/49701219
【3】《Java线程池之FutureTask【Java线程池系列3】》链接地址:http://blog.csdn.net/zhangphil/article/details/49702751

### 解决 `sprio` 命令中的 Unrecognized Option 错误 当遇到类似于 OGG-10152 的错误提示时,通常表明指定的选项值不符合参数的要求。具体到 `sprio` 命令中出现的 “Unrecognized option” 错误,可以按照以下方法排查和解决问题。 #### 1. 验证命令语法 确保使用的 `sprio` 命令遵循正确的语法规则。以下是标准的 `sprio` 使用格式: ```bash sprio [-option value] ... ``` 如果命令中存在拼写错误或者不支持的选项,则会触发此错误[^1]。建议仔细核对官方文档中关于 `sprio` 的说明部分,确认所用选项的有效性和适用范围。 #### 2. 参数与选项匹配性检查 每种工具对于其子命令都有特定的支持列表。例如,在 GoldenGate 中运行某些功能可能仅接受预定义的组开关及其关联值。假如尝试传递了个未被识别的名字或超出允许集合之外的内容作为输入项之的话就会报错。因此需要对照产品手册来核实每个单独设置是否合法合规。 #### 3. 更新至最新版本 有时软件本身可能存在缺陷导致解析异常情况发生;考虑升级到较新发行版或许能够修复此类已知问题。查看是否有针对该类情形发布的补丁程序可用也是个不错的选择[^1]。 #### 示例修正后的正确调用方式如下所示: 假设我们希望调整优先级队列大小为例: ```bash sprio -queue_size 1024 ``` 上述例子展示了如何通过提供有效的 `-queue_size` 参数以及合理的数值避免潜在冲突。 --- ### 提供段 Python 脚本辅助验证配置文件合法性 下面给出了段简单的Python脚本来帮助用户初步检测是否存在非法关键字的情况: ```python def validate_sprio_config(config_file_path): invalid_options = ["unrec_option", "another_invalid"] # 替换为实际不可能存在的选项名 with open(config_file_path, 'r') as file: lines = file.readlines() errors_found = False for idx,line in enumerate(lines,start=1): parts = line.strip().split() if any(part in invalid_options for part in parts): print(f"Error at Line {idx}: Contains Invalid Option.") errors_found = True return not errors_found if __name__ == "__main__": result = validate_sprio_config("/path/to/your/config") # 修改路径为你的真实配置位置 if result: print("Configuration appears to be clean from known issues.") else: print("Please review your configuration and remove any flagged options.") ``` 以上代码片段可以帮助快速定位那些可能导致执行失败的地方,并指导进步的手动审查过程。 --- 问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhangphil

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值