Как удалить повторяющиеся намерения из JobIntentService - PullRequest
4 голосов
/ 03 июля 2019

У меня есть JobIntentService, который запускается каждый раз, когда приходит push-уведомление, чтобы сообщить службе о необходимости получения большего количества данных. Пока приложение находится на переднем плане, все работает как надо.

Когда приложение работает в фоновом режиме и поступает несколько push-уведомлений, намерение ставится в очередь, и оно выполняет одно и то же намерение несколько раз, создавая ненужную нагрузку на сервер, поскольку при первом обращении к серверу будет получена вся необходимая информация. лишние ненужные намерения из push-уведомлений.

Есть ли в любом случае отменить или не добавить такое же намерение в очередь или каким-либо другим способом предотвратить дополнительные вызовы на сервер?

Ответы [ 2 ]

1 голос
/ 11 июля 2019

Итак, сначала пара уже похожих вопросов с большим количеством хороших знаний: question1 и question2 . Может быть, ваш вопрос даже дублирует подобные.

Самое чистое - получить в очередь заданий JobIntentService в вашей MyOwnJobIntentService extends JobIntentService.

В androidx.core.app.JobIntentService.java есть:

final ArrayList<CompatWorkItem> mCompatQueue;

А у тебя MyOwnJobIntentService extends JobIntentService:

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

Но, к сожалению mCompatQueue не является публичным полем .

И через 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");
    }
}

Вы можете проверить это с помощью простого действия с кнопкой:

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);
            }
        });
    }
}

Примечание: вы должны быть осторожны с многопоточностью, поскольку решение, которое я дал, не является поточно-ориентированным. Например, в androidx.core.app.JobIntentService.java касание mCompatQueue синхронизировано. РЕДАКТИРОВАТЬ: после размышления об этом -> так как onHandleWork вызывается из JobIntentService из одного потока, проблема с потоком отсутствует, и решение - потокобезопасен!

0 голосов
/ 11 июля 2019

Вы можете использовать один и тот же идентификатор уведомления для всех уведомлений, поэтому он переопределит старое уведомление и предоставит вам только самое последнее с последним намерением.

Если у вас несколько типов уведомлений для различных действий, выможет создать другую группу уведомлений с указанием намерений, которые могут работать только для особого типа действия.

А также продолжать очищать группу уведомлений, чтобы при нажатии на одно из уведомлений можно было удалить то же самоегруппа уведомлений.

...