如何从 JobIntentService 中删除重复的意图

How to remove duplicate intent from JobIntentService

我有一个 JobIntentService,每次推送通知进入时都会启动,告诉服务去获取更多数据。当应用程序在前台时,一切正常。

当应用程序在后台并且收到多个推送通知时,意图会排队并多次执行相同的意图会给服务器带来不必要的压力,因为对服务器的第一次调用将获得所有信息它需要使推送通知中的其他排队意图变得不必要。

是否有取消或不将相同意图添加到队列或其他一些方法来防止对服务器的额外调用?

您可以对所有通知使用相同的通知 ID,这样它将覆盖旧通知并为您提供唯一具有最新意图的最新通知。

如果您有针对不同操作的多种类型的通知,您可以创建一组不同的通知,提供仅适用于特殊类型操作的意图。

并且还不断清除通知组,因此一旦单击其中一个通知,您就可以清除同一组通知。

所以首先有几个已经很相似的问题,有很多很好的知识: and question2。也许您的问题甚至与那些相似的问题重复。

最干净的方法是在 MyOwnJobIntentService extends JobIntentService.

中获取 JobIntentService 的作业队列

androidx.core.app.JobIntentService.java中有:

final ArrayList<CompatWorkItem> mCompatQueue;

在你的MyOwnJobIntentService extends JobIntentService中:

if(mCompatQueue.isEmpty()){
  //only in this case enqueue new job   
}

但不幸的是 mCompatQueue 不是 public 字段

10 分钟后,我们得到了工作解决方案 -> SingleJobIntentService 一个 JobIntentService,如果它已经在工作,它不会排队作业。

import android.content.Context;
import android.content.Intent;
import android.support.annotation.NonNull;
import android.support.v4.app.JobIntentService;
import android.util.Log;

public class SingleJobIntentService extends JobIntentService {

    private static final String TAG = "SingleJobIntentService";

    private Intent theOnlyJobIhave = null;

    public static void enqueue(Context context, Intent work) {
        Log.d(TAG, "enqueue: someone tries to add me work " + work.hashCode());
        JobIntentService.enqueueWork(
                context,
                SingleJobIntentService.class,
                SingleJobIntentService.class.hashCode(),
                work);
    }

    @Override
    protected void onHandleWork(@NonNull final Intent theWorkIgot) {
        Log.d(TAG, "onHandleWork: " + this.hashCode());
        if (theOnlyJobIhave == null) {
            theOnlyJobIhave = theWorkIgot;
            final int extraValue = theOnlyJobIhave.getIntExtra(MainActivity.KEY, -500);
            Log.d(TAG, "onHandleWork: " + extraValue);
            try {
                Thread.sleep(7000); //this simulates fetch to server
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } else {
            Log.d(TAG, "onHandleWork I'm already busy, refuse to work >:(");
        }
        Log.d(TAG, "onHandleWork end");
    }
}

你可能想用简单的 activity 和一个按钮来测试它:

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;

public class MainActivity extends AppCompatActivity {

    public static final String KEY = "KEYKEY";

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

        findViewById(R.id.button).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(final View v) {
                final Intent theIntent = new Intent();
                theIntent.putExtra(KEY, 666);
                SingleJobIntentService.enqueue(MainActivity.this, theIntent);
            }
        });
    }
}

注意:你必须小心线程,因为我给出的解决方案不是thread-safe。例如在 androidx.core.app.JobIntentService.java 中触摸 mCompatQueue 是同步的。 编辑: 考虑之后 -> 因为 onHandleWork 是从 JobIntentService 调用的从单线程没有线程问题,解决方案是线程安全的!