Android Priority Job Queue (Job Manager)(一)



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:

  1. package zhangphil.app;  
  2.   
  3. import android.app.Application;  
  4. import android.util.Log;  
  5.   
  6. import com.birbit.android.jobqueue.JobManager;  
  7. import com.birbit.android.jobqueue.config.Configuration;  
  8. import com.birbit.android.jobqueue.log.CustomLogger;  
  9.   
  10. /** 
  11.  * Created by Phil on 2016/10/9. 
  12.  */  
  13. public class MyApplication extends Application {  
  14.     private JobManager jobManager;  
  15.   
  16.     private static MyApplication instance;  
  17.   
  18.     public MyApplication() {  
  19.         instance = this;  
  20.     }  
  21.   
  22.     public static MyApplication getInstance() {  
  23.         return instance;  
  24.     }  
  25.   
  26.     @Override  
  27.     public void onCreate() {  
  28.         super.onCreate();  
  29.         getJobManager();// ensure it is created  
  30.     }  
  31.   
  32.     public synchronized JobManager getJobManager() {  
  33.         if (jobManager == null) {  
  34.             configureJobManager();  
  35.         }  
  36.   
  37.         return jobManager;  
  38.     }  
  39.   
  40.     private void configureJobManager() {  
  41.         Configuration.Builder builder = new Configuration.Builder(this)  
  42.                 .customLogger(new CustomLogger() {  
  43.                     private static final String TAG = “zhangphil job”;  
  44.   
  45.                     @Override  
  46.                     public boolean isDebugEnabled() {  
  47.                         return true;  
  48.                     }  
  49.   
  50.                     @Override  
  51.                     public void d(String text, Object… args) {  
  52.                         Log.d(TAG, String.format(text, args));  
  53.                     }  
  54.   
  55.                     @Override  
  56.                     public void e(Throwable t, String text, Object… args) {  
  57.                         Log.e(TAG, String.format(text, args), t);  
  58.                     }  
  59.   
  60.                     @Override  
  61.                     public void e(String text, Object… args) {  
  62.                         Log.e(TAG, String.format(text, args));  
  63.                     }  
  64.   
  65.                     @Override  
  66.                     public void v(String text, Object… args) {  
  67.   
  68.                     }  
  69.                 })  
  70.                 .minConsumerCount(1)//always keep at least one consumer alive  
  71.                 .maxConsumerCount(3)//up to 3 consumers at a time  
  72.                 .loadFactor(3)//3 jobs per consumer  
  73.                 .consumerKeepAlive(120);//wait 2 minute  
  74.   
  75.         jobManager = new JobManager(builder.build());  
  76.     }  
  77. }  
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下面:

  1. <?xml version=“1.0” encoding=“utf-8”?>  
  2. <manifest xmlns:android=“http://schemas.android.com/apk/res/android”  
  3.     package=“zhangphil.app”>  
  4.   
  5.     <application  
  6.         android:name=“.MyApplication”  
  7.         android:allowBackup=“true”  
  8.         android:icon=“@mipmap/ic_launcher”  
  9.         android:label=“@string/app_name”  
  10.         android:supportsRtl=“true”  
  11.         android:theme=“@style/AppTheme”>  
  12.         <activity android:name=“.MainActivity”>  
  13.             <intent-filter>  
  14.                 <action android:name=“android.intent.action.MAIN” />  
  15.   
  16.                 <category android:name=“android.intent.category.LAUNCHER” />  
  17.             </intent-filter>  
  18.         </activity>  
  19.     </application>  
  20.   
  21. </manifest>  
<?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:

  1. package zhangphil.app;  
  2.   
  3. import android.os.SystemClock;  
  4. import android.support.annotation.NonNull;  
  5. import android.support.annotation.Nullable;  
  6. import android.util.Log;  
  7.   
  8. import com.birbit.android.jobqueue.Job;  
  9. import com.birbit.android.jobqueue.Params;  
  10. import com.birbit.android.jobqueue.RetryConstraint;  
  11.   
  12. /** 
  13.  * Created by Phil on 2016/10/9. 
  14.  */  
  15. public class MyJob extends Job {  
  16.   
  17.     private String tag;  
  18.   
  19.     public MyJob(String tag) {  
  20.         super(new Params(500).requireNetwork().persist().groupBy(tag));  
  21.         this.tag = tag;  
  22.         Log.d(tag, ”初始化”);  
  23.     }  
  24.   
  25.     @Override  
  26.     public void onAdded() {  
  27.         Log.d(tag, ”添加任务”);  
  28.     }  
  29.   
  30.     //在这里面放置耗时的后台线程化任务  
  31.     @Override  
  32.     public void onRun() throws Throwable {  
  33.         Log.d(tag, ”开始运行…”);  
  34.   
  35.         int i = 0;  
  36.         while (true) {  
  37.             i++;  
  38.   
  39.             SystemClock.sleep(2000);  
  40.             Log.d(tag, String.valueOf(i));  
  41.             if (i == 10)  
  42.                 break;  
  43.         }  
  44.   
  45.         Log.d(tag, ”完成”);  
  46.     }  
  47.   
  48.     @Override  
  49.     protected RetryConstraint shouldReRunOnThrowable(@NonNull Throwable throwable, int runCount, int maxRunCount) {  
  50.         // An error occurred in onRun.  
  51.         // Return value determines whether this job should retry or cancel. You can further  
  52.         // specify a backoff strategy or change the job’s priority. You can also apply the  
  53.         // delay to the whole group to preserve jobs’ running order.  
  54.   
  55.         Log.d(tag, ”runCount:” + runCount);  
  56.   
  57.         return RetryConstraint.createExponentialBackoff(runCount, 1000);  
  58.     }  
  59.   
  60.     @Override  
  61.     protected void onCancel(int cancelReason, @Nullable Throwable throwable) {  
  62.   
  63.     }  
  64. }  
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:

  1. package zhangphil.app;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5.   
  6. import com.birbit.android.jobqueue.JobManager;  
  7.   
  8. public class MainActivity extends Activity {  
  9.   
  10.     private JobManager jobManager;  
  11.   
  12.     @Override  
  13.     protected void onCreate(Bundle savedInstanceState) {  
  14.         super.onCreate(savedInstanceState);  
  15.         //setContentView(R.layout.activity_main);  
  16.   
  17.         jobManager=MyApplication.getInstance().getJobManager();  
  18.   
  19.         jobManager.addJobInBackground(new MyJob(“任务1”)); //启动任务,跑!  
  20.         //jobManager.addJobInBackground(new MyJob(“任务2”));  
  21.         //jobManager.addJobInBackground(new MyJob(“任务3”));  
  22.         //jobManager.addJobInBackground(new MyJob(“任务4”));  
  23.         //jobManager.addJobInBackground(new MyJob(“任务5”));  
  24.         //jobManager.addJobInBackground(new MyJob(“任务6”));  
  25.     }  
  26. }  
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.youkuaiyun.com/zhangphil/article/details/43898637 
【2】《Java线程池及Future、Callable获得线程返回结果【Java线程池系列2】》链接地址:http://blog.youkuaiyun.com/zhangphil/article/details/49701219
【3】《Java线程池之FutureTask【Java线程池系列3】》链接地址:http://blog.youkuaiyun.com/zhangphil/article/details/49702751

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值