Java 从IntentService调度递归处理程序以重试http调用
我正试图通过在每次请求失败时使用Java 从IntentService调度递归处理程序以重试http调用,java,android,multithreading,android-handler,android-intentservice,Java,Android,Multithreading,Android Handler,Android Intentservice,我正试图通过在每次请求失败时使用handler.postDelayed(…)调度线程来实现指数退避,以重试失败的http调用。问题是,我是从一个IntentService执行此操作的,它在调度第一个线程后死亡,因此处理程序无法调用自己。我得到以下错误: java.lang.IllegalStateException: Handler (android.os.Handler) {2f31b19b} sending message to a Handler on a dead thread 我的I
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;
}
}
}
}
有没有办法让我的主人活着?使用指数退避来安排http重试的最佳/最干净的方法是什么?使用
IntentService
的主要优点是它在onHandleIntent(Intent-Intent)
方法中为您处理所有后台线程。在这种情况下,您没有理由自己管理处理程序
下面是一种方法,您可以使用AlarmManager
来计划向您的服务交付意图。您可以将重试信息保存在要传递的意图中
我是这样想的:
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);
}
}
}
}
我想您可以使用共享的首选项来存储请求代码,每次您必须计划重试时,该代码都会递增。非常好而且符合逻辑,谢谢!我不得不通过将getService的最后一个参数更改为“PendingEvent.FLAG_UPDATE_CURRENT”来进行一个小的修正
int requestCode = getNextRequestCode();
PendingIntent pendingIntent = PendingIntent
.getService(getApplicationContext(), requestCode, intent, 0);