Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

132 рядки
3.8 KiB

  1. package com.codezjx.andlinker;
  2. import android.os.RemoteException;
  3. import static com.codezjx.andlinker.Utils.checkNotNull;
  4. /**
  5. * Created by codezjx on 2017/10/14.<br/>
  6. */
  7. final class RemoteCall implements Call<Object> {
  8. private static final String TAG = "RemoteCall";
  9. private final ITransfer mTransferService;
  10. private final ServiceMethod mServiceMethod;
  11. private final Object[] mArgs;
  12. private final Dispatcher mDispatcher;
  13. private volatile boolean mExecuted;
  14. private volatile boolean mCanceled;
  15. RemoteCall(ITransfer transferService, ServiceMethod serviceMethod, Object[] args, Dispatcher dispatcher) {
  16. mTransferService = transferService;
  17. mServiceMethod = serviceMethod;
  18. mArgs = args;
  19. mDispatcher = dispatcher;
  20. }
  21. private Object executeInternal() throws RemoteException {
  22. if (mTransferService == null) {
  23. Logger.e(TAG, "TransferService null when execute, this may occur if the client is not already bind to the service.");
  24. return null;
  25. }
  26. @SuppressWarnings("unchecked")
  27. ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) mServiceMethod.getParameterHandlers();
  28. int argumentCount = mArgs != null ? mArgs.length : 0;
  29. if (argumentCount != handlers.length) {
  30. throw new IllegalArgumentException("Argument count (" + argumentCount
  31. + ") doesn't match expected count (" + handlers.length + ")");
  32. }
  33. RequestBuilder requestBuilder = new RequestBuilder(mServiceMethod.getClassName(), mServiceMethod.getMethodName(), argumentCount, mServiceMethod.isOneWay());
  34. for (int p = 0; p < argumentCount; p++) {
  35. handlers[p].apply(requestBuilder, mArgs[p], p);
  36. }
  37. Response response = mTransferService.execute(requestBuilder.build());
  38. // May return null in one-way mode.
  39. if (response == null) {
  40. return null;
  41. }
  42. if (response.getStatusCode() != Response.STATUS_CODE_SUCCESS) {
  43. Logger.e(TAG, "Execute remote call fail: " + response.toString());
  44. }
  45. return response.getResult();
  46. }
  47. @Override
  48. public Object execute() {
  49. checkExecuted();
  50. if (mCanceled) {
  51. Logger.w(TAG, "Already canceled");
  52. return null;
  53. }
  54. Object result = null;
  55. try {
  56. result = executeInternal();
  57. } catch (RemoteException e) {
  58. e.printStackTrace();
  59. }
  60. return result;
  61. }
  62. @Override
  63. public void enqueue(Callback<Object> callback) {
  64. checkNotNull(callback, "callback == null");
  65. checkExecuted();
  66. if (mCanceled) {
  67. Logger.w(TAG, "Already canceled");
  68. return;
  69. }
  70. mDispatcher.enqueue(new AsyncCall(callback));
  71. }
  72. private void checkExecuted() {
  73. synchronized (this) {
  74. if (mExecuted) {
  75. throw new IllegalStateException("Already executed.");
  76. }
  77. mExecuted = true;
  78. }
  79. }
  80. final class AsyncCall implements Runnable {
  81. private Callback<Object> mCallback;
  82. AsyncCall(Callback<Object> callback) {
  83. mCallback = callback;
  84. }
  85. @Override
  86. public void run() {
  87. try {
  88. Object result = executeInternal();
  89. mCallback.onResponse(RemoteCall.this, result);
  90. } catch (RemoteException e) {
  91. e.printStackTrace();
  92. mCallback.onFailure(RemoteCall.this, e);
  93. }
  94. }
  95. }
  96. @Override
  97. public synchronized boolean isExecuted() {
  98. return mExecuted;
  99. }
  100. @Override
  101. public void cancel() {
  102. mCanceled = true;
  103. }
  104. @Override
  105. public boolean isCanceled() {
  106. return mCanceled;
  107. }
  108. }