public class BaseCallback<T> implements Callback<T> {
    protected BaseEvent<T> event;                   // 事件

    public <Event extends BaseEvent<T>> BaseCallback(@NonNull Event event) {
        this.event = event;
    }

    /**
     * Invoked for a received HTTP response.
     * <p>
     * Note: An HTTP response may still indicate an application-level failure such as a 404 or 500.
     * Call {@link Response#isSuccessful()} to determine if the response indicates success.
     *
     * @param call
     * @param response
     */
    @Override
    public void onResponse(Call<T> call, Response<T> response) {
        if (response.isSuccessful())
            EventBus.getDefault().post(event.setEvent(response.code(), response.body()));
        else {
            EventBus.getDefault().post(event.setEvent(response.code(), null));
        }
    }

    /**
     * Invoked when a network exception occurred talking to the server or when an unexpected
     * exception occurred creating the request or processing the response.
     *
     * @param call
     * @param t
     */
    @Override
    public void onFailure(Call<T> call, Throwable t) {
        EventBus.getDefault().post(event.setEvent(-1, null));
    }
} public class BaseImpl<Service> {
    protected CacheUtil mCacheUtil;
    private static Retrofit mRetrofit;
    protected Service mService;

    public BaseImpl(@NonNull Context context) {
        mCacheUtil = new CacheUtil(context.getApplicationContext());
        initRetrofit();
        this.mService = mRetrofit.create(getServiceClass());
    }

    private Class<Service> getServiceClass() {
        return (Class<Service>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }

    private void initRetrofit() {
        if (null != mRetrofit)
            return;

        // 设置 Log 拦截器，可以用于以后处理一些异常情况
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

        // 为所有请求自动添加 token
        Interceptor mTokenInterceptor = new Interceptor() {
            @Override
            public okhttp3.Response intercept(Chain chain) throws IOException {
                Request originalRequest = chain.request();
                // 如果当前没有缓存 token 或者请求已经附带 token 了，就不再添加
                if (null == mCacheUtil.getToken() || alreadyHasAuthorizationHeader(originalRequest)) {
                    return chain.proceed(originalRequest);
                }
                String token = OAuth.TOKEN_PREFIX + mCacheUtil.getToken().getAccess_token();
                // 为请求附加 token
                Request authorised = originalRequest.newBuilder()
                        .header(OAuth.KEY_TOKEN, token)
                        .build();
                return chain.proceed(authorised);
            }
        };

        // 自动刷新 token
        Authenticator mAuthenticator = new Authenticator() {
            @Override
            public Request authenticate(Route route, Response response) {
                Logger.i("自动刷新 token 开始");
                TokenService tokenService = mRetrofit.create(TokenService.class);
                String accessToken = "";
                try {
                    if (null != mCacheUtil.getToken()) {
                        Call<Token> call = tokenService.refreshToken(OAuth.client_id,
                                OAuth.client_secret, OAuth.GRANT_TYPE_REFRESH,
                                mCacheUtil.getToken().getRefresh_token());
                        retrofit2.Response<Token> tokenResponse = call.execute();
                        Token token = tokenResponse.body();
                        if (null != token) {
                            mCacheUtil.saveToken(token);
                            accessToken = token.getAccess_token();
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                Logger.i("自动刷新 token 结束：" + accessToken);
                return response.request().newBuilder()
                        .addHeader(OAuth.KEY_TOKEN, OAuth.TOKEN_PREFIX + accessToken)
                        .build();
            }
        };

        // 配置 client
        OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(interceptor)                // 设置拦截器
                .retryOnConnectionFailure(true)             // 是否重试
                .connectTimeout(5, TimeUnit.SECONDS)        // 连接超时事件
                .addNetworkInterceptor(mTokenInterceptor)   // 自动附加 token
                .authenticator(mAuthenticator)              // 认证失败自动刷新token
                .build();

        // 配置 Retrofit
        mRetrofit = new Retrofit.Builder()
                .baseUrl(Constant.BASE_URL)                         // 设置 base url
                .client(client)                                     // 设置 client
                .addConverterFactory(GsonConverterFactory.create()) // 设置 Json 转换工具
                .build();
    }

    private boolean alreadyHasAuthorizationHeader(Request originalRequest) {
        // 用于 debug 时临时移除 token
        if (OAuth.getRemoveAutoTokenState()) {
            return true;
        }
        String token = originalRequest.header(OAuth.KEY_TOKEN);
        // 如果本身是请求 token 的 URL，直接返回 true
        // 如果不是，则判断 header 中是否已经添加过 Authorization 这个字段，以及是否为空
        return !(null == token || token.isEmpty() || originalRequest.url().toString().contains(Constant.OAUTH_URL));
    }

    interface TokenService {
        /**
         * 刷新 token
         */
        @POST(Constant.OAUTH_URL)
        @FormUrlEncoded
        Call<Token> refreshToken(@Field("client_id") String client_id, @Field("client_secret") String client_secret,
                                 @Field("grant_type") String grant_type, @Field("refresh_token") String refresh_token);
    }
} public class BanTopicEvent extends BaseEvent<State> {
    /**
     * @param uuid 唯一识别码
     */
    public BanTopicEvent(@Nullable String uuid) {
        super(uuid);
    }

    /**
     * @param uuid  唯一识别码
     * @param code  网络返回码
     * @param state 实体数据
     */
    public BanTopicEvent(@Nullable String uuid, @NonNull Integer code, @Nullable State state) {
        super(uuid, code, state);
    }
} public class CollectionTopicEvent extends BaseEvent<State> {
    /**
     * @param uuid 唯一识别码
     */
    public CollectionTopicEvent(@Nullable String uuid) {
        super(uuid);
    }

    /**
     * @param uuid  唯一识别码
     * @param code  网络返回码
     * @param state 实体数据
     */
    public CollectionTopicEvent(@Nullable String uuid, @NonNull Integer code, @Nullable State state) {
        super(uuid, code, state);
    }
} public class CreateTopicEvent extends BaseEvent<TopicContent> {
    /**
     * @param uuid 唯一识别码
     */
    public CreateTopicEvent(@Nullable String uuid) {
        super(uuid);
    }

    /**
     * @param uuid         唯一识别码
     * @param code         网络返回码
     * @param topicContent 实体数据
     */
    public CreateTopicEvent(@Nullable String uuid, @NonNull Integer code, @Nullable TopicContent topicContent) {
        super(uuid, code, topicContent);
    }
} public class CreateTopicReplyEvent extends BaseEvent<TopicReply> {

    /**
     * @param uuid 唯一识别码
     */
    public CreateTopicReplyEvent(@Nullable String uuid) {
        super(uuid);
    }

    /**
     * @param uuid       唯一识别码
     * @param code       网络返回码
     * @param topicReply 实体数据
     */
    public CreateTopicReplyEvent(@Nullable String uuid, @NonNull Integer code, @Nullable TopicReply topicReply) {
        super(uuid, code, topicReply);
    }
} public class DeleteTopicEvent extends BaseEvent<State> {
    /**
     * @param uuid 唯一识别码
     */
    public DeleteTopicEvent(@Nullable String uuid) {
        super(uuid);
    }

    /**
     * @param uuid  唯一识别码
     * @param code  网络返回码
     * @param state 实体数据
     */
    public DeleteTopicEvent(@Nullable String uuid, @NonNull Integer code, @Nullable State state) {
        super(uuid, code, state);
    }
} public class DeleteTopicReplyEvent extends BaseEvent<State> {
    /**
     * @param uuid 唯一识别码
     */
    public DeleteTopicReplyEvent(@Nullable String uuid) {
        super(uuid);
    }

    /**
     * @param uuid  唯一识别码
     * @param code  网络返回码
     * @param state 实体数据
     */
    public DeleteTopicReplyEvent(@Nullable String uuid, @NonNull Integer code, @Nullable State state) {
        super(uuid, code, state);
    }
} public class GetTopicEvent extends BaseEvent<TopicContent> {

    /**
     * @param uuid 唯一识别码
     */
    public GetTopicEvent(@Nullable String uuid) {
        super(uuid);
    }

    /**
     * @param uuid         唯一识别码
     * @param code         网络返回码
     * @param topicContent 实体数据
     */
    public GetTopicEvent(@Nullable String uuid, @NonNull Integer code, @Nullable TopicContent topicContent) {
        super(uuid, code, topicContent);
    }
} public class GetTopicNodeListEvent extends BaseEvent<List<Node>> {

    public GetTopicNodeListEvent(@Nullable String uuid) {
        super(uuid);
    }

    public GetTopicNodeListEvent(@Nullable String uuid, @NonNull Integer code, @Nullable List<Node> nodes) {
        super(uuid, code, nodes);
    }
} public class GetTopicRepliesListEvent extends BaseEvent<List<TopicReply>> {
    /**
     * @param uuid 唯一识别码
     */
    public GetTopicRepliesListEvent(@Nullable String uuid) {
        super(uuid);
    }

    /**
     * @param uuid         唯一识别码
     * @param code         网络返回码
     * @param topicReplies 实体数据
     */
    public GetTopicRepliesListEvent(@Nullable String uuid, @NonNull Integer code, @Nullable List<TopicReply> topicReplies) {
        super(uuid, code, topicReplies);
    }
} public class GetTopicReplyEvent extends BaseEvent<TopicReply> {

    /**
     * @param uuid 唯一识别码
     */
    public GetTopicReplyEvent(@Nullable String uuid) {
        super(uuid);
    }

    /**
     * @param uuid       唯一识别码
     * @param code       网络返回码
     * @param topicReply 实体数据
     */
    public GetTopicReplyEvent(@Nullable String uuid, @NonNull Integer code, @Nullable TopicReply topicReply) {
        super(uuid, code, topicReply);
    }
} public class GetTopicsListEvent extends BaseEvent<List<Topic>> {

    /**
     * @param uuid 唯一识别码
     */
    public GetTopicsListEvent(@Nullable String uuid) {
        super(uuid);
    }

    /**
     * @param uuid   唯一识别码
     * @param code   网络返回码
     * @param topics 实体数据
     */
    public GetTopicsListEvent(@Nullable String uuid, @NonNull Integer code, @Nullable List<Topic> topics) {
        super(uuid, code, topics);
    }
} public class UnCollectionTopicEvent extends BaseEvent<State> {
    /**
     * @param uuid 唯一识别码
     */
    public UnCollectionTopicEvent(@Nullable String uuid) {
        super(uuid);
    }

    /**
     * @param uuid  唯一识别码
     * @param code  网络返回码
     * @param state 实体数据
     */
    public UnCollectionTopicEvent(@Nullable String uuid, @NonNull Integer code, @Nullable State state) {
        super(uuid, code, state);
    }
} public class UnWatchTopicEvent extends BaseEvent<State> {
    /**
     * @param uuid 唯一识别码
     */
    public UnWatchTopicEvent(@Nullable String uuid) {
        super(uuid);
    }

    /**
     * @param uuid  唯一识别码
     * @param code  网络返回码
     * @param state 实体数据
     */
    public UnWatchTopicEvent(@Nullable String uuid, @NonNull Integer code, @Nullable State state) {
        super(uuid, code, state);
    }
} public class UpdateTopicEvent extends BaseEvent<TopicContent> {
    /**
     * @param uuid 唯一识别码
     */
    public UpdateTopicEvent(@Nullable String uuid) {
        super(uuid);
    }

    /**
     * @param uuid         唯一识别码
     * @param code         网络返回码
     * @param topicContent 实体数据
     */
    public UpdateTopicEvent(@Nullable String uuid, @NonNull Integer code, @Nullable TopicContent topicContent) {
        super(uuid, code, topicContent);
    }
} public class UpdateTopicReplyEvent extends BaseEvent<TopicReply> {

    /**
     * @param uuid 唯一识别码
     */
    public UpdateTopicReplyEvent(@Nullable String uuid) {
        super(uuid);
    }

    /**
     * @param uuid       唯一识别码
     * @param code       网络返回码
     * @param topicReply 实体数据
     */
    public UpdateTopicReplyEvent(@Nullable String uuid, @NonNull Integer code, @Nullable TopicReply topicReply) {
        super(uuid, code, topicReply);
    }
} public class WatchTopicEvent extends BaseEvent<State> {
    /**
     * @param uuid 唯一识别码
     */
    public WatchTopicEvent(@Nullable String uuid) {
        super(uuid);
    }

    /**
     * @param uuid  唯一识别码
     * @param code  网络返回码
     * @param state 实体数据
     */
    public WatchTopicEvent(@Nullable String uuid, @NonNull Integer code, @Nullable State state) {
        super(uuid, code, state);
    }
} public class UUIDGenerator {
    private UUIDGenerator() {
    }

    public static String getUUID() {
        return UUID.randomUUID().toString();
    }

    //获得指定数量的UUID  
    public static String[] getUUID(int number) {
        if (number < 1) {
            return null;
        }
        String[] ss = new String[number];
        for (int i = 0; i < number; i++) {
            ss[i] = getUUID();
        }
        return ss;
    }
}  
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.gcssloop.diycode_sdk.api.base.callback.BaseCallback;
import com.gcssloop.diycode_sdk.api.base.impl.BaseImpl;
import com.gcssloop.diycode_sdk.api.topic.event.BanTopicEvent;
import com.gcssloop.diycode_sdk.api.topic.event.CollectionTopicEvent;
import com.gcssloop.diycode_sdk.api.topic.event.CreateTopicEvent;
import com.gcssloop.diycode_sdk.api.topic.event.CreateTopicReplyEvent;
import com.gcssloop.diycode_sdk.api.topic.event.DeleteTopicEvent;
import com.gcssloop.diycode_sdk.api.topic.event.DeleteTopicReplyEvent;
import com.gcssloop.diycode_sdk.api.topic.event.GetTopicEvent;
import com.gcssloop.diycode_sdk.api.topic.event.GetTopicNodeListEvent;
import com.gcssloop.diycode_sdk.api.topic.event.GetTopicRepliesListEvent;
import com.gcssloop.diycode_sdk.api.topic.event.GetTopicReplyEvent;
import com.gcssloop.diycode_sdk.api.topic.event.GetTopicsListEvent;
import com.gcssloop.diycode_sdk.api.topic.event.UnCollectionTopicEvent;
import com.gcssloop.diycode_sdk.api.topic.event.UnWatchTopicEvent;
import com.gcssloop.diycode_sdk.api.topic.event.UpdateTopicEvent;
import com.gcssloop.diycode_sdk.api.topic.event.UpdateTopicReplyEvent;
import com.gcssloop.diycode_sdk.api.topic.event.WatchTopicEvent;
import com.gcssloop.diycode_sdk.utils.UUIDGenerator;
/*
 * Copyright 2017 GcsSloop
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Last modified 2017-03-08 01:01:18
 *
 * GitHub:  https://github.com/GcsSloop
 * Website: http://www.gcssloop.com
 * Weibo:   http://weibo.com/GcsSloop
 */

package com.gcssloop.diycode_sdk.api.topic.api;



public class TopicImpl extends BaseImpl<TopicService> implements TopicAPI {

    public TopicImpl(Context context) {
        super(context);
    }

    /**
     * 获取 topic 列表
     *
     * @param type    类型，默认 last_actived，可选["last_actived", "recent", "no_reply", "popular", "excellent"]
     * @param node_id 如果你需要只看某个节点的，请传此参数, 如果不传 则返回全部
     * @param offset  偏移数值，默认值 0
     * @param limit   数量极限，默认值 20，值范围 1..150
     * @see GetTopicsListEvent
     */
    @Override
    public String getTopicsList(String type, @Nullable Integer node_id, @Nullable Integer offset, @Nullable Integer limit) {
        final String uuid = UUIDGenerator.getUUID();
        mService.getTopicsList(type, node_id, offset, limit)
                .enqueue(new BaseCallback<>(new GetTopicsListEvent(uuid)));
        return uuid;
    }

    /**
     * 创建一个新的 topic
     *
     * @param title   话题标题
     * @param body    话题内容, Markdown 格式
     * @param node_id 节点编号
     * @see CreateTopicEvent
     */
    @Override
    public String createTopic(@NonNull String title, @NonNull String body, @NonNull Integer node_id) {
        final String uuid = UUIDGenerator.getUUID();
        mService.createTopic(title, body, node_id).enqueue(new BaseCallback<>(new CreateTopicEvent(uuid)));
        return uuid;
    }

    /**
     * 获取 topic 内容
     *
     * @param id topic 的 id
     * @see GetTopicEvent
     */
    @Override
    public String getTopic(@NonNull int id) {
        final String uuid = UUIDGenerator.getUUID();
        mService.getTopic(id).enqueue(new BaseCallback<>(new GetTopicEvent(uuid)));
        return uuid;
    }

    /**
     * 更新(修改) topic
     *
     * @param id      要修改的话题 id
     * @param title   话题标题
     * @param body    话题内容, Markdown 格式
     * @param node_id 节点编号
     * @see UpdateTopicEvent
     */
    @Override
    public String updateTopic(@NonNull int id, @NonNull String title, @NonNull String body, @NonNull Integer node_id) {
        final String uuid = UUIDGenerator.getUUID();
        mService.updateTopic(id, title, body, node_id).enqueue(new BaseCallback<>(new UpdateTopicEvent(uuid)));
        return uuid;
    }

    /**
     * 删除一个话题
     *
     * @param id 要删除的话题 id
     * @see DeleteTopicEvent
     */
    @Override
    public String deleteTopic(@NonNull int id) {
        final String uuid = UUIDGenerator.getUUID();
        mService.deleteTopic(id).enqueue(new BaseCallback<>(new DeleteTopicEvent(uuid)));
        return uuid;
    }

    /**
     * 收藏话题
     *
     * @param id 被收藏的话题 id
     * @see CollectionTopicEvent
     */
    @Override
    public String collectionTopic(@NonNull int id) {
        final String uuid = UUIDGenerator.getUUID();
        mService.collectionTopic(id).enqueue(new BaseCallback<>(new CollectionTopicEvent(uuid)));
        return uuid;
    }

    /**
     * 取消收藏话题
     *
     * @param id 被收藏的话题 id
     * @see UnCollectionTopicEvent
     */
    @Override
    public String unCollectionTopic(@NonNull int id) {
        final String uuid = UUIDGenerator.getUUID();
        mService.unCollectionTopic(id).enqueue(new BaseCallback<>(new UnCollectionTopicEvent(uuid)));
        return uuid;
    }

    /**
     * 关注话题
     *
     * @param id 话题 id
     * @see WatchTopicEvent
     */
    @Override
    public String watchTopic(@NonNull int id) {
        final String uuid = UUIDGenerator.getUUID();
        mService.watchTopic(id).enqueue(new BaseCallback<>(new WatchTopicEvent(uuid)));
        return uuid;
    }

    /**
     * 取消关注话题
     *
     * @param id 话题 id
     * @see UnWatchTopicEvent
     */
    @Override
    public String unWatchTopic(@NonNull int id) {
        final String uuid = UUIDGenerator.getUUID();
        mService.unWatchTopic(id).enqueue(new BaseCallback<>(new UnWatchTopicEvent(uuid)));
        return uuid;
    }

    /**
     * 获取 topic 回复列表
     *
     * @param id     topic 的 id
     * @param offset 偏移数值 默认 0
     * @param limit  数量极限，默认值 20，值范围 1...150
     * @see GetTopicRepliesListEvent
     */
    @Override
    public String getTopicRepliesList(@NonNull int id, @Nullable Integer offset, @Nullable Integer limit) {
        final String uuid = UUIDGenerator.getUUID();
        mService.getTopicRepliesList(id, offset, limit).enqueue(new BaseCallback<>(new GetTopicRepliesListEvent(uuid)));
        return uuid;
    }

    /**
     * 创建 topic 回帖(回复，评论)
     *
     * @param id   话题列表
     * @param body 回帖内容, Markdown 格式
     * @see CreateTopicReplyEvent
     */
    @Override
    public String createTopicReply(@NonNull int id, @NonNull String body) {
        final String uuid = UUIDGenerator.getUUID();
        mService.createTopicReply(id, body).enqueue(new BaseCallback<>(new CreateTopicReplyEvent(uuid)));
        return uuid;
    }

    /**
     * 获取回帖的详细内容（一般用于编辑回帖的时候）
     *
     * @param id id
     * @see GetTopicReplyEvent
     */
    @Override
    public String getTopicReply(@NonNull int id) {
        final String uuid = UUIDGenerator.getUUID();
        mService.getTopicReply(id).enqueue(new BaseCallback<>(new GetTopicReplyEvent(uuid)));
        return uuid;
    }

    /**
     * 更新回帖
     *
     * @param id   id
     * @param body 回帖详情
     * @see UpdateTopicReplyEvent
     */
    @Override
    public String updateTopicReply(@NonNull int id, @NonNull String body) {
        final String uuid = UUIDGenerator.getUUID();
        mService.updateTopicReply(id, body).enqueue(new BaseCallback<>(new UpdateTopicReplyEvent(uuid)));
        return uuid;
    }

    /**
     * 删除回帖
     *
     * @param id id
     * @see DeleteTopicReplyEvent
     */
    @Override
    public String deleteTopicReply(@NonNull int id) {
        final String uuid = UUIDGenerator.getUUID();
        mService.deleteTopicReply(id).enqueue(new BaseCallback<>(new DeleteTopicReplyEvent(uuid)));
        return uuid;
    }

    /**
     * 屏蔽话题，移到 NoPoint 节点 (管理员限定)
     *
     * @param id 要屏蔽的话题 id
     * @see BanTopicEvent
     */
    @Override
    public String banTopic(@NonNull int id) {
        final String uuid = UUIDGenerator.getUUID();
        mService.banTopic(id).enqueue(new BaseCallback<>(new BanTopicEvent(uuid)));