编程语言
首页 > 编程语言> > java-从IntentService调度递归处理程序以重试http调用

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

作者:互联网

我正在尝试通过每次我的请求失败时使用handler.postDelayed(…)安排线程来实现指数补偿,以重试失败的http调用.问题是我是通过IntentService来执行此操作的,该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);
            }
        }
    }
}

这只是让您正在使用的IntentService在后台处理调用,然后安排每次失败都会重新发送该意图,并在其中增加了额外的内容,包括它已被重试了多少次以及最后一次重试延迟了多长时间.是.

注意:如果您尝试向该服务发送多个意图,并且有多个失败,并且必须使用AlarmManager重新安排,则根据Intent.filterEquals(Intent intent)将意图视为相等时,只会传送最新的意图.如果您的意图与附加的意图相同,那么这将是一个问题,并且在创建PendingIntent时,必须为重新计划的每个意图使用唯一的requestCode.遵循以下原则:

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

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

标签:android-handler,multithreading,android-intentservice,java,android
来源: https://codeday.me/bug/20191028/1950969.html