在处理订阅时取消Observable中的长时间运行任务

时间:2017-09-26 12:49:20

标签: android android-volley reactive-programming rx-java2

我正在为凌空库编写一个反应式包装器,以便在我的应用中轻松发送http请求。这是班级:

/**
 * Used to send a http GET/POST request.
 */

public class BasicRequest {
public static final String LOG_TAG = "BasicRequest";

public static final int GET_REQUEST = Request.Method.GET;
public static final int POST_REQUEST = Request.Method.POST;
private final int mRequestType;
private final String mServiceLocation;
private final Map<String, String> mParams;

/**
 * Keeps track of all the request for this object. Will be helpful when we need to cancel
 * the request when someone disposes the subscription.
 */
private List<StringRequest> mStringRequests = new ArrayList<>();

private Context mContext;

private int mRequestTimeout = BASIC_REQUEST_DEFAULT_TIMEOUT;

public BasicRequest(Context context,
                    String serviceLocation,
                    int requestType,
                    final Map<String, String> params) {
    mContext = context;
    mRequestType = requestType;
    mServiceLocation = serviceLocation;
    mParams = params;
}

private void fireRequest(final SingleEmitter<String> e) {

    StringRequest stringRequest;
    if(mRequestType == GET_REQUEST) {
        stringRequest = new StringRequest(Request.Method.GET, mServiceLocation,
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        e.onSuccess(response);

                    }
                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                e.onError(error);
            }
        });
    } else {
        stringRequest = new StringRequest(Request.Method.POST, mServiceLocation,
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        e.onSuccess(response);
                    }
                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                e.onError(error);
            }
        }) {
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                return mParams;
            }

        };
    }
    mStringRequests.add(stringRequest);
    stringRequest.setRetryPolicy(new DefaultRetryPolicy(
            mRequestTimeout,
            ConnectionUtils.BASIC_REQUEST_DEFAULT_RETRIES,
            DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
    VolleyInstance.getInstance(mContext).addToRequestQueue(stringRequest);
}


/**
 * Returns a Single observable for results. Queues the request on Subscription. Must be
 * called only once during the lifetime of object. Calling multiple times will return null.
 * Expect to get VolleyException in case of error.
 * @return Single observable for String results. If it's is used for second time, it will
 * return null.
 */
@Nullable
public Single<String> get() {

    return Single.create(new SingleOnSubscribe<String>() {
        @Override
        public void subscribe(@NonNull SingleEmitter<String> e) throws Exception {
            fireRequest(e);
        }
    }).doOnDispose(new Action() {
        @Override
        public void run() throws Exception {
            for (StringRequest stringRequest: mStringRequests) {
                stringRequest.cancel();
            }
        }
    });

}

/**
 * Set the request timeout for this request.
 * @param requestTimeout time in milliseconds.
 */
public void setRequestTimeout(int requestTimeout) {
    mRequestTimeout = requestTimeout;
}

现在的问题是当有人处理订阅时,所有与订阅相对应的请求都将被停止。有没有办法我只能停止处理订阅的请求?

我知道一旦实现它就会强制执行只能维护一个订阅,如果有人再次调用,则会返回缓存的观察者。是否有更好的方法根据订阅处理处理http请求?

1 个答案:

答案 0 :(得分:1)

您无需在fireRequest之外进行管理,SingleEmitter完全具有setCancellable方法,在那里进行取消,并且当有人处置时RxJava会确保调用它观察者。

添加fireRequest()方法,然后移除doOnDispose

e.setCancellable(()-> stringRequest.cancel());