gpt4 book ai didi

java - 从 IntentService 调度递归处理程序以重试 http 调用

转载 作者:太空宇宙 更新时间:2023-11-03 13:19:32 26 4
gpt4 key购买 nike

每次我的请求失败时,我都试图通过使用 handler.postDelayed(...) 安排一个线程来实现指数退避以重试失败的 http 调用。问题是我是从 IntentService 执行此操作的,该服务在安排第一个线程后死亡,因此处理程序无法调用自身。我收到以下错误:

java.lang.IllegalStateException: Handler (android.os.Handler) {2f31b19b} sending message to a Handler on a dead thread

我的 IntentService 类:

@Override
protected void onHandleIntent(Intent intent) {

......

Handler handler = new Handler();
HttpRunnable httpRunnable = new HttpRunnable(info, handler);
handler.postDelayed(httpRunnable, 0);

}

我的自定义 Runnable:

public class HttpRunnable implements Runnable {

private String info;
private static final String TAG = "HttpRunnable";
Handler handler = null;
int maxTries = 10;
int retryCount = 0;
int retryDelay = 1000; // Set the first delay here which will increase exponentially with each retry

public HttpRunnable(String info, Handler handler) {
this.info = info;
this.handler = handler;
}

@Override
public void run() {
try {
// Call my class which takes care of the http call
ApiBridge.getInstance().makeHttpCall(info);
} catch (Exception e) {
Log.d(TAG, e.toString());
if (maxTries > retryCount) {
Log.d(TAG,"%nRetrying in " + retryDelay / 1000 + " seconds");
retryCount++;
handler.postDelayed(this, retryDelay);
retryDelay = retryDelay * 2;
}
}
}
}

有没有办法让我的处理程序保持 Activity 状态?使用指数退避来安排我的 HTTP 重试的最佳/最干净的方法是什么?

最佳答案

使用 IntentService 的主要优点是它可以在 onHandleIntent(Intent intent) 方法中为您处理所有后台线程。在这种情况下,您没有理由自己管理处理程序。

您可以使用 AlarmManager 来安排向您的服务发送 Intent 。您将在要交付的 Intent 中保留重试信息。

我是这样想的:

public class YourService extends IntentService {

private static final String EXTRA_FAILED_ATTEMPTS = "com.your.package.EXTRA_FAILED_ATTEMPTS";
private static final String EXTRA_LAST_DELAY = "com.your.package.EXTRA_LAST_DELAY";
private static final int MAX_RETRIES = 10;
private static final int RETRY_DELAY = 1000;

public YourService() {
super("YourService");
}

@Override
protected final void onHandleIntent(Intent intent) {

// Your other code obtaining your info string.

try {
// Make your http call.
ApiBridge.getInstance().makeHttpCall(info);
} catch (Exception e) {
// Get the number of previously failed attempts, and add one.
int failedAttempts = intent.getIntExtra(EXTRA_FAILED_ATTEMPTS, 0) + 1;
// if we have failed less than the max retries, reschedule the intent
if (failedAttempts < MAX_RETRIES) {
// calculate the next delay
int lastDelay = intent.getIntExtra(EXTRA_LAST_DELAY, 0);
int thisDelay;
if (lastDelay == 0) {
thisDelay = RETRY_DELAY;
} else {
thisDelay = lastDelay * 2;
}
// update the intent with the latest retry info
intent.putExtra(EXTRA_FAILED_ATTEMPTS, failedAttempts);
intent.putExtra(EXTRA_LAST_DELAY, thisDelay);
// get the alarm manager
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
// make the pending intent
PendingIntent pendingIntent = PendingIntent
.getService(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
// schedule the intent for future delivery
alarmManager.set(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + thisDelay, pendingIntent);
}
}
}
}

这只是让您正在使用的 IntentService 在后台处理调用,然后安排在每次失败时重新发送 Intent,向其添加重试次数和重试时长等额外信息上次重试延迟是。

注意:如果您尝试向此服务发送多个 Intent ,但不止一个失败并且必须使用 AlarmManager 重新安排,如果 Intent 被认为相等,则只会传送最新的 Intent 到 Intent.filterEquals(Intent intent)。如果您的 Intent 除了附加到它的额外内容之外是相同的,这将是一个问题,并且您必须在创建您的 PendingIntent 时为每个要重新安排的 Intent 使用唯一的 requestCode。沿着这些线的东西:

int requestCode = getNextRequestCode();
PendingIntent pendingIntent = PendingIntent
.getService(getApplicationContext(), requestCode, intent, 0);

我想您可以使用您的共享首选项来存储一个请求代码,每次您必须安排重试时该代码都会递增。

关于java - 从 IntentService 调度递归处理程序以重试 http 调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30650069/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com