Android开源库——Retrofit

Retrofit是什么?

一个类型安全的 HTTP 客户端,适用于 Android 和 Java

Retrofit是基于Rsetful风格用于构建网络服务的架构,Rsetful特点如下

  • 无状态性:每个请求都包含所有必要信息,服务器不保存客户端状态
  • 资源导向:通过 URI 识别和操作资源
  • 标准 HTTP 方法:使用 GET、POST、PUT、DELETE 等方法进行操作
  • 数据格式:通常使用 JSON 或 XML 进行数据传输
  • 可缓存性:响应可以被缓存以提高性能

Retrofit使用

依赖

添加retrofit

implementation 'com.squareup.retrofit2:retrofit:2.9.0'

添加GsonConverterFactory,用于将获取的Json数据转为Java对象

implementation 'com.squareup.retrofit2:converter-gson:2.9.0'

权限

<uses-permission android:name="android.permission.INTERNET" />

创建访问接口

如下BASE_URL必须以 / 结尾

public interface GitHubService {

    String BASE_URL = "https://api.github.com/";

    @GET("users/{user}/repos")
    Call<List<Repo>> listRepos(@Path("user") String user);
}

创建单例

用单例管理Retrofit并设置url和转换器

public class RetrofitManager {
    private final static RetrofitManager instance = new RetrofitManager();
    private final Retrofit mRetrofit;

    private RetrofitManager() {
        mRetrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
    }

    public static RetrofitManager getInstance() {
        return instance;
    }

    public Retrofit getRetrofit() {
        return mRetrofit;
    }
}

创建返回数据对应的对象

我们将要返回的数据是Json,格式如下

{
    "id": 132935648,
    "node_id": "MDEwOlJlcG9zaXRvcnkxMzI5MzU2NDg=",
    "name": "boysenberry-repo-1",
    "full_name": "octocat/boysenberry-repo-1",
    "private": false,
    "owner": {
      "login": "octocat",
      "id": 583231,
      "node_id": "MDQ6VXNlcjU4MzIzMQ==",
      "avatar_url": "https://avatars.githubusercontent.com/u/583231?v=4",
      "gravatar_id": "",
      "url": "https://api.github.com/users/octocat",
      "html_url": "https://github.com/octocat",
      "followers_url": "https://api.github.com/users/octocat/followers",
      "following_url": "https://api.github.com/users/octocat/following{/other_user}",
      "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
      "organizations_url": "https://api.github.com/users/octocat/orgs",
      "repos_url": "https://api.github.com/users/octocat/repos",
      "events_url": "https://api.github.com/users/octocat/events{/privacy}",
      "received_events_url": "https://api.github.com/users/octocat/received_events",
      "type": "User",
      "user_view_type": "public",
      "site_admin": false
    },
    "html_url": "https://github.com/octocat/boysenberry-repo-1",
    "description": "Testing",
    "fork": true,
    "url": "https://api.github.com/repos/octocat/boysenberry-repo-1",
    "forks_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/forks",
    "keys_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/keys{/key_id}",
    "collaborators_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/collaborators{/collaborator}",
    "teams_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/teams",
    "hooks_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/hooks",
    "issue_events_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/issues/events{/number}",
    "events_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/events",
    "assignees_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/assignees{/user}",
    "branches_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/branches{/branch}",
    "tags_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/tags",
    "blobs_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/git/blobs{/sha}",
    "git_tags_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/git/tags{/sha}",
    "git_refs_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/git/refs{/sha}",
    "trees_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/git/trees{/sha}",
    "statuses_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/statuses/{sha}",
    "languages_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/languages",
    "stargazers_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/stargazers",
    "contributors_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/contributors",
    "subscribers_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/subscribers",
    "subscription_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/subscription",
    "commits_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/commits{/sha}",
    "git_commits_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/git/commits{/sha}",
    "comments_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/comments{/number}",
    "issue_comment_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/issues/comments{/number}",
    "contents_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/contents/{+path}",
    "compare_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/compare/{base}...{head}",
    "merges_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/merges",
    "archive_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/{archive_format}{/ref}",
    "downloads_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/downloads",
    "issues_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/issues{/number}",
    "pulls_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/pulls{/number}",
    "milestones_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/milestones{/number}",
    "notifications_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/notifications{?since,all,participating}",
    "labels_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/labels{/name}",
    "releases_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/releases{/id}",
    "deployments_url": "https://api.github.com/repos/octocat/boysenberry-repo-1/deployments",
    "created_at": "2018-05-10T17:51:29Z",
    "updated_at": "2025-03-05T12:57:28Z",
    "pushed_at": "2024-05-26T07:02:05Z",
    "git_url": "git://github.com/octocat/boysenberry-repo-1.git",
    "ssh_url": "git@github.com:octocat/boysenberry-repo-1.git",
    "clone_url": "https://github.com/octocat/boysenberry-repo-1.git",
    "svn_url": "https://github.com/octocat/boysenberry-repo-1",
    "homepage": "",
    "size": 4,
    "stargazers_count": 314,
    "watchers_count": 314,
    "language": null,
    "has_issues": false,
    "has_projects": true,
    "has_downloads": true,
    "has_wiki": true,
    "has_pages": false,
    "has_discussions": false,
    "forks_count": 18,
    "mirror_url": null,
    "archived": false,
    "disabled": false,
    "open_issues_count": 1,
    "license": null,
    "allow_forking": true,
    "is_template": false,
    "web_commit_signoff_required": false,
    "topics": [],
    "visibility": "public",
    "forks": 18,
    "open_issues": 1,
    "watchers": 314,
    "default_branch": "master"
  }

对应的类如下,手动为其生成toString

public class Repo {
    /**
     *
     */
    private String id;

    /**
     *
     */
    private String nodeId;

    /**
     *
     */
    private String name;

    /**
     *
     */
    private String fullName;

    /**
     *
     */
    private Boolean isPrivate;

    /**
     *
     */
    private Owner owner;

    /**
     *
     */
    private String htmlUrl;

    /**
     *
     */
    private String description;

    /**
     *
     */
    private Boolean fork;

    /**
     *
     */
    private String url;

    /**
     *
     */
    private String forksUrl;

    /**
     *
     */
    private String keysUrl;

    /**
     *
     */
    private String collaboratorsUrl;

    /**
     *
     */
    private String teamsUrl;

    /**
     *
     */
    private String hooksUrl;

    /**
     *
     */
    private String issueEventsUrl;

    /**
     *
     */
    private String eventsUrl;

    /**
     *
     */
    private String assigneesUrl;

    /**
     *
     */
    private String branchesUrl;

    /**
     *
     */
    private String tagsUrl;

    /**
     *
     */
    private String blobsUrl;

    /**
     *
     */
    private String gitTagsUrl;

    /**
     *
     */
    private String gitRefsUrl;

    /**
     *
     */
    private String treesUrl;

    /**
     *
     */
    private String statusesUrl;

    /**
     *
     */
    private String languagesUrl;

    /**
     *
     */
    private String stargazersUrl;

    /**
     *
     */
    private String contributorsUrl;

    /**
     *
     */
    private String subscribersUrl;

    /**
     *
     */
    private String subscriptionUrl;

    /**
     *
     */
    private String commitsUrl;

    /**
     *
     */
    private String gitCommitsUrl;

    /**
     *
     */
    private String commentsUrl;

    /**
     *
     */
    private String issueCommentUrl;

    /**
     *
     */
    private String contentsUrl;

    /**
     *
     */
    private String compareUrl;

    /**
     *
     */
    private String mergesUrl;

    /**
     *
     */
    private String archiveUrl;

    /**
     *
     */
    private String downloadsUrl;

    /**
     *
     */
    private String issuesUrl;

    /**
     *
     */
    private String pullsUrl;

    /**
     *
     */
    private String milestonesUrl;

    /**
     *
     */
    private String notificationsUrl;

    /**
     *
     */
    private String labelsUrl;

    /**
     *
     */
    private String releasesUrl;

    /**
     *
     */
    private String deploymentsUrl;

    /**
     *
     */
    private String createdAt;

    /**
     *
     */
    private String updatedAt;

    /**
     *
     */
    private String pushedAt;

    /**
     *
     */
    private String gitUrl;

    /**
     *
     */
    private String sshUrl;

    /**
     *
     */
    private String cloneUrl;

    /**
     *
     */
    private String svnUrl;

    /**
     *
     */
    private String homepage;

    /**
     *
     */
    private Integer size;

    /**
     *
     */
    private Integer stargazersCount;

    /**
     *
     */
    private Integer watchersCount;

    /**
     *
     */
    private Boolean hasIssues;

    /**
     *
     */
    private Boolean hasProjects;

    /**
     *
     */
    private Boolean hasDownloads;

    /**
     *
     */
    private Boolean hasWiki;

    /**
     *
     */
    private Boolean hasPages;

    /**
     *
     */
    private Boolean hasDiscussions;

    /**
     *
     */
    private Integer forksCount;

    /**
     *
     */
    private Boolean archived;

    /**
     *
     */
    private Boolean disabled;

    /**
     *
     */
    private Integer openIssuesCount;

    /**
     *
     */
    private Boolean allowForking;

    /**
     *
     */
    private Boolean isTemplate;

    /**
     *
     */
    private Boolean webCommitSignoffRequired;

    /**
     *
     */
    private String visibility;

    /**
     *
     */
    private Integer forks;

    /**
     *
     */
    private Integer openIssues;

    /**
     *
     */
    private Integer watchers;

    /**
     *
     */
    private String defaultBranch;

    public void setId(String id) {
        this.id = id;
    }

    public String getId() {
        return this.id;
    }

    public void setNodeId(String nodeId) {
        this.nodeId = nodeId;
    }

    public String getNodeId() {
        return this.nodeId;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return this.name;
    }

    public void setFullName(String fullName) {
        this.fullName = fullName;
    }

    public String getFullName() {
        return this.fullName;
    }

    public void setPrivate(Boolean isPrivate) {
        this.isPrivate = isPrivate;
    }

    public Boolean getPrivate() {
        return this.isPrivate;
    }

    public void setOwner(Owner owner) {
        this.owner = owner;
    }

    public Owner getOwner() {
        return this.owner;
    }

    public void setHtmlUrl(String htmlUrl) {
        this.htmlUrl = htmlUrl;
    }

    public String getHtmlUrl() {
        return this.htmlUrl;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getDescription() {
        return this.description;
    }

    public void setFork(Boolean fork) {
        this.fork = fork;
    }

    public Boolean getFork() {
        return this.fork;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUrl() {
        return this.url;
    }

    public void setForksUrl(String forksUrl) {
        this.forksUrl = forksUrl;
    }

    public String getForksUrl() {
        return this.forksUrl;
    }

    public void setKeysUrl(String keysUrl) {
        this.keysUrl = keysUrl;
    }

    public String getKeysUrl() {
        return this.keysUrl;
    }

    public void setCollaboratorsUrl(String collaboratorsUrl) {
        this.collaboratorsUrl = collaboratorsUrl;
    }

    public String getCollaboratorsUrl() {
        return this.collaboratorsUrl;
    }

    public void setTeamsUrl(String teamsUrl) {
        this.teamsUrl = teamsUrl;
    }

    public String getTeamsUrl() {
        return this.teamsUrl;
    }

    public void setHooksUrl(String hooksUrl) {
        this.hooksUrl = hooksUrl;
    }

    public String getHooksUrl() {
        return this.hooksUrl;
    }

    public void setIssueEventsUrl(String issueEventsUrl) {
        this.issueEventsUrl = issueEventsUrl;
    }

    public String getIssueEventsUrl() {
        return this.issueEventsUrl;
    }

    public void setEventsUrl(String eventsUrl) {
        this.eventsUrl = eventsUrl;
    }

    public String getEventsUrl() {
        return this.eventsUrl;
    }

    public void setAssigneesUrl(String assigneesUrl) {
        this.assigneesUrl = assigneesUrl;
    }

    public String getAssigneesUrl() {
        return this.assigneesUrl;
    }

    public void setBranchesUrl(String branchesUrl) {
        this.branchesUrl = branchesUrl;
    }

    public String getBranchesUrl() {
        return this.branchesUrl;
    }

    public void setTagsUrl(String tagsUrl) {
        this.tagsUrl = tagsUrl;
    }

    public String getTagsUrl() {
        return this.tagsUrl;
    }

    public void setBlobsUrl(String blobsUrl) {
        this.blobsUrl = blobsUrl;
    }

    public String getBlobsUrl() {
        return this.blobsUrl;
    }

    public void setGitTagsUrl(String gitTagsUrl) {
        this.gitTagsUrl = gitTagsUrl;
    }

    public String getGitTagsUrl() {
        return this.gitTagsUrl;
    }

    public void setGitRefsUrl(String gitRefsUrl) {
        this.gitRefsUrl = gitRefsUrl;
    }

    public String getGitRefsUrl() {
        return this.gitRefsUrl;
    }

    public void setTreesUrl(String treesUrl) {
        this.treesUrl = treesUrl;
    }

    public String getTreesUrl() {
        return this.treesUrl;
    }

    public void setStatusesUrl(String statusesUrl) {
        this.statusesUrl = statusesUrl;
    }

    public String getStatusesUrl() {
        return this.statusesUrl;
    }

    public void setLanguagesUrl(String languagesUrl) {
        this.languagesUrl = languagesUrl;
    }

    public String getLanguagesUrl() {
        return this.languagesUrl;
    }

    public void setStargazersUrl(String stargazersUrl) {
        this.stargazersUrl = stargazersUrl;
    }

    public String getStargazersUrl() {
        return this.stargazersUrl;
    }

    public void setContributorsUrl(String contributorsUrl) {
        this.contributorsUrl = contributorsUrl;
    }

    public String getContributorsUrl() {
        return this.contributorsUrl;
    }

    public void setSubscribersUrl(String subscribersUrl) {
        this.subscribersUrl = subscribersUrl;
    }

    public String getSubscribersUrl() {
        return this.subscribersUrl;
    }

    public void setSubscriptionUrl(String subscriptionUrl) {
        this.subscriptionUrl = subscriptionUrl;
    }

    public String getSubscriptionUrl() {
        return this.subscriptionUrl;
    }

    public void setCommitsUrl(String commitsUrl) {
        this.commitsUrl = commitsUrl;
    }

    public String getCommitsUrl() {
        return this.commitsUrl;
    }

    public void setGitCommitsUrl(String gitCommitsUrl) {
        this.gitCommitsUrl = gitCommitsUrl;
    }

    public String getGitCommitsUrl() {
        return this.gitCommitsUrl;
    }

    public void setCommentsUrl(String commentsUrl) {
        this.commentsUrl = commentsUrl;
    }

    public String getCommentsUrl() {
        return this.commentsUrl;
    }

    public void setIssueCommentUrl(String issueCommentUrl) {
        this.issueCommentUrl = issueCommentUrl;
    }

    public String getIssueCommentUrl() {
        return this.issueCommentUrl;
    }

    public void setContentsUrl(String contentsUrl) {
        this.contentsUrl = contentsUrl;
    }

    public String getContentsUrl() {
        return this.contentsUrl;
    }

    public void setCompareUrl(String compareUrl) {
        this.compareUrl = compareUrl;
    }

    public String getCompareUrl() {
        return this.compareUrl;
    }

    public void setMergesUrl(String mergesUrl) {
        this.mergesUrl = mergesUrl;
    }

    public String getMergesUrl() {
        return this.mergesUrl;
    }

    public void setArchiveUrl(String archiveUrl) {
        this.archiveUrl = archiveUrl;
    }

    public String getArchiveUrl() {
        return this.archiveUrl;
    }

    public void setDownloadsUrl(String downloadsUrl) {
        this.downloadsUrl = downloadsUrl;
    }

    public String getDownloadsUrl() {
        return this.downloadsUrl;
    }

    public void setIssuesUrl(String issuesUrl) {
        this.issuesUrl = issuesUrl;
    }

    public String getIssuesUrl() {
        return this.issuesUrl;
    }

    public void setPullsUrl(String pullsUrl) {
        this.pullsUrl = pullsUrl;
    }

    public String getPullsUrl() {
        return this.pullsUrl;
    }

    public void setMilestonesUrl(String milestonesUrl) {
        this.milestonesUrl = milestonesUrl;
    }

    public String getMilestonesUrl() {
        return this.milestonesUrl;
    }

    public void setNotificationsUrl(String notificationsUrl) {
        this.notificationsUrl = notificationsUrl;
    }

    public String getNotificationsUrl() {
        return this.notificationsUrl;
    }

    public void setLabelsUrl(String labelsUrl) {
        this.labelsUrl = labelsUrl;
    }

    public String getLabelsUrl() {
        return this.labelsUrl;
    }

    public void setReleasesUrl(String releasesUrl) {
        this.releasesUrl = releasesUrl;
    }

    public String getReleasesUrl() {
        return this.releasesUrl;
    }

    public void setDeploymentsUrl(String deploymentsUrl) {
        this.deploymentsUrl = deploymentsUrl;
    }

    public String getDeploymentsUrl() {
        return this.deploymentsUrl;
    }

    public void setCreatedAt(String createdAt) {
        this.createdAt = createdAt;
    }

    public String getCreatedAt() {
        return this.createdAt;
    }

    public void setUpdatedAt(String updatedAt) {
        this.updatedAt = updatedAt;
    }

    public String getUpdatedAt() {
        return this.updatedAt;
    }

    public void setPushedAt(String pushedAt) {
        this.pushedAt = pushedAt;
    }

    public String getPushedAt() {
        return this.pushedAt;
    }

    public void setGitUrl(String gitUrl) {
        this.gitUrl = gitUrl;
    }

    public String getGitUrl() {
        return this.gitUrl;
    }

    public void setSshUrl(String sshUrl) {
        this.sshUrl = sshUrl;
    }

    public String getSshUrl() {
        return this.sshUrl;
    }

    public void setCloneUrl(String cloneUrl) {
        this.cloneUrl = cloneUrl;
    }

    public String getCloneUrl() {
        return this.cloneUrl;
    }

    public void setSvnUrl(String svnUrl) {
        this.svnUrl = svnUrl;
    }

    public String getSvnUrl() {
        return this.svnUrl;
    }

    public void setHomepage(String homepage) {
        this.homepage = homepage;
    }

    public String getHomepage() {
        return this.homepage;
    }

    public void setSize(Integer size) {
        this.size = size;
    }

    public Integer getSize() {
        return this.size;
    }

    public void setStargazersCount(Integer stargazersCount) {
        this.stargazersCount = stargazersCount;
    }

    public Integer getStargazersCount() {
        return this.stargazersCount;
    }

    public void setWatchersCount(Integer watchersCount) {
        this.watchersCount = watchersCount;
    }

    public Integer getWatchersCount() {
        return this.watchersCount;
    }

    public void setHasIssues(Boolean hasIssues) {
        this.hasIssues = hasIssues;
    }

    public Boolean getHasIssues() {
        return this.hasIssues;
    }

    public void setHasProjects(Boolean hasProjects) {
        this.hasProjects = hasProjects;
    }

    public Boolean getHasProjects() {
        return this.hasProjects;
    }

    public void setHasDownloads(Boolean hasDownloads) {
        this.hasDownloads = hasDownloads;
    }

    public Boolean getHasDownloads() {
        return this.hasDownloads;
    }

    public void setHasWiki(Boolean hasWiki) {
        this.hasWiki = hasWiki;
    }

    public Boolean getHasWiki() {
        return this.hasWiki;
    }

    public void setHasPages(Boolean hasPages) {
        this.hasPages = hasPages;
    }

    public Boolean getHasPages() {
        return this.hasPages;
    }

    public void setHasDiscussions(Boolean hasDiscussions) {
        this.hasDiscussions = hasDiscussions;
    }

    public Boolean getHasDiscussions() {
        return this.hasDiscussions;
    }

    public void setForksCount(Integer forksCount) {
        this.forksCount = forksCount;
    }

    public Integer getForksCount() {
        return this.forksCount;
    }

    public void setArchived(Boolean archived) {
        this.archived = archived;
    }

    public Boolean getArchived() {
        return this.archived;
    }

    public void setDisabled(Boolean disabled) {
        this.disabled = disabled;
    }

    public Boolean getDisabled() {
        return this.disabled;
    }

    public void setOpenIssuesCount(Integer openIssuesCount) {
        this.openIssuesCount = openIssuesCount;
    }

    public Integer getOpenIssuesCount() {
        return this.openIssuesCount;
    }

    public void setAllowForking(Boolean allowForking) {
        this.allowForking = allowForking;
    }

    public Boolean getAllowForking() {
        return this.allowForking;
    }

    public void setIsTemplate(Boolean isTemplate) {
        this.isTemplate = isTemplate;
    }

    public Boolean getIsTemplate() {
        return this.isTemplate;
    }

    public void setWebCommitSignoffRequired(Boolean webCommitSignoffRequired) {
        this.webCommitSignoffRequired = webCommitSignoffRequired;
    }

    public Boolean getWebCommitSignoffRequired() {
        return this.webCommitSignoffRequired;
    }

    public void setVisibility(String visibility) {
        this.visibility = visibility;
    }

    public String getVisibility() {
        return this.visibility;
    }

    public void setForks(Integer forks) {
        this.forks = forks;
    }

    public Integer getForks() {
        return this.forks;
    }

    public void setOpenIssues(Integer openIssues) {
        this.openIssues = openIssues;
    }

    public Integer getOpenIssues() {
        return this.openIssues;
    }

    public void setWatchers(Integer watchers) {
        this.watchers = watchers;
    }

    public Integer getWatchers() {
        return this.watchers;
    }

    public void setDefaultBranch(String defaultBranch) {
        this.defaultBranch = defaultBranch;
    }

    public String getDefaultBranch() {
        return this.defaultBranch;
    }
    
    @Override
    public String toString() {
        return "Repo{" +
                "id='" + id + '\'' +
                '}';
    }
}

public class Owner implements Serializable {

    /**
     * 
     */
    private String login;

    /**
     * 
     */
    private Integer id;

    /**
     * 
     */
    private String nodeId;

    /**
     * 
     */
    private String avatarUrl;

    /**
     * 
     */
    private String gravatarId;

    /**
     * 
     */
    private String url;

    /**
     * 
     */
    private String htmlUrl;

    /**
     * 
     */
    private String followersUrl;

    /**
     * 
     */
    private String followingUrl;

    /**
     * 
     */
    private String gistsUrl;

    /**
     * 
     */
    private String starredUrl;

    /**
     * 
     */
    private String subscriptionsUrl;

    /**
     * 
     */
    private String organizationsUrl;

    /**
     * 
     */
    private String reposUrl;

    /**
     * 
     */
    private String eventsUrl;

    /**
     * 
     */
    private String receivedEventsUrl;

    /**
     * 
     */
    private String type;

    /**
     * 
     */
    private String userViewType;

    /**
     * 
     */
    private Boolean siteAdmin;

    public void setLogin(String login) {
        this.login =  login;
    }

    public String  getLogin() {
        return this.login;
    }

    public void setId(Integer id) {
        this.id =  id;
    }

    public Integer  getId() {
        return this.id;
    }

    public void setNodeId(String nodeId) {
        this.nodeId =  nodeId;
    }

    public String  getNodeId() {
        return this.nodeId;
    }

    public void setAvatarUrl(String avatarUrl) {
        this.avatarUrl =  avatarUrl;
    }

    public String  getAvatarUrl() {
        return this.avatarUrl;
    }

    public void setGravatarId(String gravatarId) {
        this.gravatarId =  gravatarId;
    }

    public String  getGravatarId() {
        return this.gravatarId;
    }

    public void setUrl(String url) {
        this.url =  url;
    }

    public String  getUrl() {
        return this.url;
    }

    public void setHtmlUrl(String htmlUrl) {
        this.htmlUrl =  htmlUrl;
    }

    public String  getHtmlUrl() {
        return this.htmlUrl;
    }

    public void setFollowersUrl(String followersUrl) {
        this.followersUrl =  followersUrl;
    }

    public String  getFollowersUrl() {
        return this.followersUrl;
    }

    public void setFollowingUrl(String followingUrl) {
        this.followingUrl =  followingUrl;
    }

    public String  getFollowingUrl() {
        return this.followingUrl;
    }

    public void setGistsUrl(String gistsUrl) {
        this.gistsUrl =  gistsUrl;
    }

    public String  getGistsUrl() {
        return this.gistsUrl;
    }

    public void setStarredUrl(String starredUrl) {
        this.starredUrl =  starredUrl;
    }

    public String  getStarredUrl() {
        return this.starredUrl;
    }

    public void setSubscriptionsUrl(String subscriptionsUrl) {
        this.subscriptionsUrl =  subscriptionsUrl;
    }

    public String  getSubscriptionsUrl() {
        return this.subscriptionsUrl;
    }

    public void setOrganizationsUrl(String organizationsUrl) {
        this.organizationsUrl =  organizationsUrl;
    }

    public String  getOrganizationsUrl() {
        return this.organizationsUrl;
    }

    public void setReposUrl(String reposUrl) {
        this.reposUrl =  reposUrl;
    }

    public String  getReposUrl() {
        return this.reposUrl;
    }

    public void setEventsUrl(String eventsUrl) {
        this.eventsUrl =  eventsUrl;
    }

    public String  getEventsUrl() {
        return this.eventsUrl;
    }

    public void setReceivedEventsUrl(String receivedEventsUrl) {
        this.receivedEventsUrl =  receivedEventsUrl;
    }

    public String  getReceivedEventsUrl() {
        return this.receivedEventsUrl;
    }

    public void setType(String type) {
        this.type =  type;
    }

    public String  getType() {
        return this.type;
    }

    public void setUserViewType(String userViewType) {
        this.userViewType =  userViewType;
    }

    public String  getUserViewType() {
        return this.userViewType;
    }

    public void setSiteAdmin(Boolean siteAdmin) {
        this.siteAdmin =  siteAdmin;
    }

    public Boolean  getSiteAdmin() {
        return this.siteAdmin;
    }

}

使用过程

  • 获取Retrofit调用create()创建接口实例
  • 调用接口的方法获取Call实例
  • 调用Call中异步的enqueue()注册回调处理成功和失败情景
public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";
    List<Repo> mRepoList = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Retrofit retrofit = RetrofitManager.getInstance().getRetrofit();
        GitHubService gitHubService = retrofit.create(GitHubService.class);
        Call<List<Repo>> repos = gitHubService.listRepos("octocat");
        repos.enqueue(new Callback<List<Repo>>() {
            @Override
            public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) {
                int code = response.code();
                if (code == HttpURLConnection.HTTP_OK) {
                    mRepoList = response.body();
                    if (mRepoList == null || mRepoList.isEmpty()) {
                        Log.d(TAG, "onResponse: null or empty");
                    } else {
                        for (Repo repo : mRepoList) {
                            Log.d(TAG, "onResponse: repo = " + repo);
                        }
                    }

                } else {
                    Log.d(TAG, "onResponse: code = " + code);
                }
            }

            @Override
            public void onFailure(Call<List<Repo>> call, Throwable t) {
                Log.d(TAG, "onFailure: " + t);
            }
        });
    }
}

Retrofit源码解析

Retrofit.Bulider

  • 无参Build设置Platform为子类Android
  • 通过baseUrl()设置url
  • callFactory未设置时,默认为OkHttpClient
  • callbackExecutor未设置时,默认为platform.defaultCallbackExecutor()
  • callAdapterFactories无论是否设置,都需要加上platform.defaultCallAdapterFactories()
  • converterFactories默认添加BuiltInConverters(),还有设置的converterFactories、platform.defaultConverterFactories()
public final class Retrofit {
  final okhttp3.Call.Factory callFactory;
  final HttpUrl baseUrl;
  final List<Converter.Factory> converterFactories;
  final List<CallAdapter.Factory> callAdapterFactories;
  final @Nullable Executor callbackExecutor;
  final boolean validateEagerly;
  
  Retrofit(
      okhttp3.Call.Factory callFactory,
      HttpUrl baseUrl,
      List<Converter.Factory> converterFactories,
      List<CallAdapter.Factory> callAdapterFactories,
      @Nullable Executor callbackExecutor,
      boolean validateEagerly) {
    this.callFactory = callFactory;
    this.baseUrl = baseUrl;
    this.converterFactories = converterFactories; // Copy+unmodifiable at call site.
    this.callAdapterFactories = callAdapterFactories; // Copy+unmodifiable at call site.
    this.callbackExecutor = callbackExecutor;
    this.validateEagerly = validateEagerly;
  }
  
  ......
	public static final class Builder {
    private final Platform platform;
    private @Nullable okhttp3.Call.Factory callFactory;
    private @Nullable HttpUrl baseUrl;
    private final List<Converter.Factory> converterFactories = new ArrayList<>();
    private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
    private @Nullable Executor callbackExecutor;
    private boolean validateEagerly;
	......
    public Builder() {
      this(Platform.get());
    }

    public Builder baseUrl(URL baseUrl) {
      Objects.requireNonNull(baseUrl, "baseUrl == null");
      return baseUrl(HttpUrl.get(baseUrl.toString()));
    }

    public Builder baseUrl(String baseUrl) {
      Objects.requireNonNull(baseUrl, "baseUrl == null");
      return baseUrl(HttpUrl.get(baseUrl));
    }

    public Builder baseUrl(HttpUrl baseUrl) {
      Objects.requireNonNull(baseUrl, "baseUrl == null");
      List<String> pathSegments = baseUrl.pathSegments();
      if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
        throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
      }
      this.baseUrl = baseUrl;
      return this;
    }

    public Builder addConverterFactory(Converter.Factory factory) {
      converterFactories.add(Objects.requireNonNull(factory, "factory == null"));
      return this;
    }
    ......
    public Retrofit build() {
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }

      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
      callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

      List<Converter.Factory> converterFactories =
          new ArrayList<>(
              1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());

      converterFactories.add(new BuiltInConverters());
      converterFactories.addAll(this.converterFactories);
      converterFactories.addAll(platform.defaultConverterFactories());

      return new Retrofit(
          callFactory,
          baseUrl,
          unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories),
          callbackExecutor,
          validateEagerly);
    }
  }

}

Platform

根据虚拟机判断当前平台

class Platform {
  private static final Platform PLATFORM = findPlatform();

  static Platform get() {
    return PLATFORM;
  }

  private static Platform findPlatform() {
    return "Dalvik".equals(System.getProperty("java.vm.name"))
        ? new Android() //
        : new Platform(true);
  }
  ......
  
  List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
      @Nullable Executor callbackExecutor) {
    DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
    return hasJava8Types
        ? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
        : singletonList(executorFactory);
  }
}

Android

defaultCallbackExecutor()返回MainThreadExecutor(),其通过主线程Looper创建Handler将Runnable提交回主线程运行

  static final class Android extends Platform {
    Android() {
      super(Build.VERSION.SDK_INT >= 24);
    }

    @Override
    public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }

    static final class MainThreadExecutor implements Executor {
      private final Handler handler = new Handler(Looper.getMainLooper());

      @Override
      public void execute(Runnable r) {
        handler.post(r);
      }
    }
  }

Retrofit

create()通过反射创建接口的代理对象

  • 若是Java8且是默认方法则调用platform.invokeDefaultMethod()
  • 否则调用loadServiceMethod()处理注解生成ServiceMethod,再调用ServiceMethod的invoke()
public final class Retrofit {
  private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();

  public <T> T create(final Class<T> service) {
    validateServiceInterface(service);
    return (T)
        Proxy.newProxyInstance(
            service.getClassLoader(),
            new Class<?>[] {service},
            new InvocationHandler() {
              private final Platform platform = Platform.get();
              private final Object[] emptyArgs = new Object[0];

              @Override
              public @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args)
                  throws Throwable {
                if (method.getDeclaringClass() == Object.class) {
                  return method.invoke(this, args);
                }
                args = args != null ? args : emptyArgs;
                return platform.isDefaultMethod(method)
                    ? platform.invokeDefaultMethod(method, service, proxy, args)
                    : loadServiceMethod(method).invoke(args);
              }
            });
  }
  
  ServiceMethod<?> loadServiceMethod(Method method) {
    ServiceMethod<?> result = serviceMethodCache.get(method);
    if (result != null) return result;

    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        result = ServiceMethod.parseAnnotations(this, method);
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

}

loadServiceMethod()先从缓存中获取,若没有则加锁,调用ServiceMethod.parseAnnotations()处理注解,并放入缓存

ServiceMethod

调用RequestFactory.parseAnnotations处理注解,返回HttpServiceMethod.parseAnnotations()

abstract class ServiceMethod<T> {
  static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
    RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
    ......
    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
  }

  abstract @Nullable T invoke(Object[] args);
}

RequestFactory

RequestFactory中Builder的build()调用parseMethodAnnotation()处理注解

  • @DELETE:从服务器中删除资源
  • @GET:从服务器中获取资源
  • @PATCH:
  • @POST:在服务器中新建资源
  • @PUT:在服务器中更新资源
  • @OPTIONS
final class RequestFactory {
  static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
    return new Builder(retrofit, method).build();
  }
  ......
  static final class Builder {
  	  ......
      Builder(Retrofit retrofit, Method method) {
      this.retrofit = retrofit;
      this.method = method;
      this.methodAnnotations = method.getAnnotations();
      this.parameterTypes = method.getGenericParameterTypes();
      this.parameterAnnotationsArray = method.getParameterAnnotations();
    }
    
    ......
    
    RequestFactory build() {
      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }
      .......

      int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) {
        parameterHandlers[p] =
            parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter);
      }

      ......
      return new RequestFactory(this);
    }

	private void parseMethodAnnotation(Annotation annotation) {
      if (annotation instanceof DELETE) {
        parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
      } else if (annotation instanceof GET) {
        parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
      } else if (annotation instanceof HEAD) {
        parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
      } else if (annotation instanceof PATCH) {
        parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
      } else if (annotation instanceof POST) {
        parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
      } else if (annotation instanceof PUT) {
        parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
      } else if (annotation instanceof OPTIONS) {
        parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
      } else if (annotation instanceof HTTP) {
        HTTP http = (HTTP) annotation;
        parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
      } else if (annotation instanceof retrofit2.http.Headers) {
        String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
        if (headersToParse.length == 0) {
          throw methodError(method, "@Headers annotation is empty.");
        }
        headers = parseHeaders(headersToParse);
      } else if (annotation instanceof Multipart) {
        if (isFormEncoded) {
          throw methodError(method, "Only one encoding annotation is allowed.");
        }
        isMultipart = true;
      } else if (annotation instanceof FormUrlEncoded) {
        if (isMultipart) {
          throw methodError(method, "Only one encoding annotation is allowed.");
        }
        isFormEncoded = true;
      }
    }

    private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
      ......
      this.httpMethod = httpMethod;
      this.hasBody = hasBody;

      if (value.isEmpty()) {
        return;
      }

      int question = value.indexOf('?');
      if (question != -1 && question < value.length() - 1) {
        String queryParams = value.substring(question + 1);
        Matcher queryParamMatcher = PARAM_URL_REGEX.matcher(queryParams);
        ......
      }

      this.relativeUrl = value;
      this.relativeUrlParamNames = parsePathParameters(value);
    }
  }
}

HttpServiceMethod

parseAnnotations()生成ServiceMethod对象,创建responseConverter,判断isKotlinSuspendFunction

  • 为false返回CallAdapted
  • 为true且continuationWantsResponse为true返回SuspendForResponse,否则返回SuspendForBody,暂不分析
abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {

  static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
    boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
    boolean continuationWantsResponse = false;
    boolean continuationBodyNullable = false;

    Annotation[] annotations = method.getAnnotations();
    Type adapterType;
    if (isKotlinSuspendFunction) {
      Type[] parameterTypes = method.getGenericParameterTypes();
      Type responseType =
          Utils.getParameterLowerBound(
              0, (ParameterizedType) parameterTypes[parameterTypes.length - 1]);
      if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) {
        
        responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType);
        continuationWantsResponse = true;
      } else {
       
      }

      adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
      annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
    } else {
      adapterType = method.getGenericReturnType();
    }

    CallAdapter<ResponseT, ReturnT> callAdapter =
        createCallAdapter(retrofit, method, adapterType, annotations);
    Type responseType = callAdapter.responseType();
    ......

    Converter<ResponseBody, ResponseT> responseConverter =
        createResponseConverter(retrofit, method, responseType);

    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    if (!isKotlinSuspendFunction) {
      return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
    } else if (continuationWantsResponse) {
      return (HttpServiceMethod<ResponseT, ReturnT>)
          new SuspendForResponse<>(
              requestFactory,
              callFactory,
              responseConverter,
              (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
    } else {
      return (HttpServiceMethod<ResponseT, ReturnT>)
          new SuspendForBody<>(
              requestFactory,
              callFactory,
              responseConverter,
              (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
              continuationBodyNullable);
    }
  }
  ......
  
  @Override
  final @Nullable ReturnT invoke(Object[] args) {
    Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
    return adapt(call, args);
  }
  protected abstract @Nullable ReturnT adapt(Call<ResponseT> call, Object[] args);
}

HttpServiceMethod的invoke()生成OkHttpCall作为参数,并调用子类的adapt()

CallAdapted

将CallAdapter适配为HttpServiceMethod

  static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
    private final CallAdapter<ResponseT, ReturnT> callAdapter;

    CallAdapted(
        RequestFactory requestFactory,
        okhttp3.Call.Factory callFactory,
        Converter<ResponseBody, ResponseT> responseConverter,
        CallAdapter<ResponseT, ReturnT> callAdapter) {
      super(requestFactory, callFactory, responseConverter);
      this.callAdapter = callAdapter;
    }

    @Override
    protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
      return callAdapter.adapt(call);
    }
  }

SuspendForResponse(暂不分析)

  static final class SuspendForResponse<ResponseT> extends HttpServiceMethod<ResponseT, Object> {
    private final CallAdapter<ResponseT, Call<ResponseT>> callAdapter;

    SuspendForResponse(
        RequestFactory requestFactory,
        okhttp3.Call.Factory callFactory,
        Converter<ResponseBody, ResponseT> responseConverter,
        CallAdapter<ResponseT, Call<ResponseT>> callAdapter) {
      super(requestFactory, callFactory, responseConverter);
      this.callAdapter = callAdapter;
    }

    @Override
    protected Object adapt(Call<ResponseT> call, Object[] args) {
      call = callAdapter.adapt(call);

      Continuation<Response<ResponseT>> continuation =
          (Continuation<Response<ResponseT>>) args[args.length - 1];

      try {
        return KotlinExtensions.awaitResponse(call, continuation);
      } catch (Exception e) {
        return KotlinExtensions.suspendAndThrow(e, continuation);
      }
    }
  }

SuspendForBody(暂不分析)

  static final class SuspendForBody<ResponseT> extends HttpServiceMethod<ResponseT, Object> {
    private final CallAdapter<ResponseT, Call<ResponseT>> callAdapter;
    private final boolean isNullable;

    SuspendForBody(
        RequestFactory requestFactory,
        okhttp3.Call.Factory callFactory,
        Converter<ResponseBody, ResponseT> responseConverter,
        CallAdapter<ResponseT, Call<ResponseT>> callAdapter,
        boolean isNullable) {
      super(requestFactory, callFactory, responseConverter);
      this.callAdapter = callAdapter;
      this.isNullable = isNullable;
    }

    @Override
    protected Object adapt(Call<ResponseT> call, Object[] args) {
      call = callAdapter.adapt(call);

      Continuation<ResponseT> continuation = (Continuation<ResponseT>) args[args.length - 1];

      try {
        return isNullable
            ? KotlinExtensions.awaitNullable(call, continuation)
            : KotlinExtensions.await(call, continuation);
      } catch (Exception e) {
        return KotlinExtensions.suspendAndThrow(e, continuation);
      }
    }
  }

CallAdapter

具体的CallAdapter由Factory的get()返回

public interface CallAdapter<R, T> {
 
  Type responseType();

  T adapt(Call<R> call);
  
  abstract class Factory {

    public abstract @Nullable CallAdapter<?, ?> get(
        Type returnType, Annotation[] annotations, Retrofit retrofit);

    protected static Type getParameterUpperBound(int index, ParameterizedType type) {
      return Utils.getParameterUpperBound(index, type);
    }

    protected static Class<?> getRawType(Type type) {
      return Utils.getRawType(type);
    }
  }
}

DefaultCallAdapterFactory

  • 在Retrofit.Build的build()中,若未设置callAdapterFactories,则默认为platform.defaultCallAdapterFactories(),其返回DefaultCallAdapterFactory
  • 参数callbackExecutor为Platform的子类Android的内部类MainThreadExecutor
final class DefaultCallAdapterFactory extends CallAdapter.Factory {
  private final @Nullable Executor callbackExecutor;

  DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
    this.callbackExecutor = callbackExecutor;
  }

  @Override
  public @Nullable CallAdapter<?, ?> get(
      Type returnType, Annotation[] annotations, Retrofit retrofit) {
    if (getRawType(returnType) != Call.class) {
      return null;
    }
    .....
    final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);

    final Executor executor =
        Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
            ? null
            : callbackExecutor;

    return new CallAdapter<Object, Call<?>>() {
      @Override
      public Type responseType() {
        return responseType;
      }

      @Override
      public Call<Object> adapt(Call<Object> call) {
        return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
      }
    };
  }

  static final class ExecutorCallbackCall<T> implements Call<T> {
    final Executor callbackExecutor;
    final Call<T> delegate;

    ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
      this.callbackExecutor = callbackExecutor;
      this.delegate = delegate;
    }

    @Override
    public void enqueue(final Callback<T> callback) {
      Objects.requireNonNull(callback, "callback == null");

      delegate.enqueue(
          new Callback<T>() {
            @Override
            public void onResponse(Call<T> call, final Response<T> response) {
              callbackExecutor.execute(
                  () -> {
                    if (delegate.isCanceled()) {
                      // Emulate OkHttp's behavior of throwing/delivering an IOException on
                      // cancellation.
                      callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
                    } else {
                      callback.onResponse(ExecutorCallbackCall.this, response);
                    }
                  });
            }

            @Override
            public void onFailure(Call<T> call, final Throwable t) {
              callbackExecutor.execute(() -> callback.onFailure(ExecutorCallbackCall.this, t));
            }
          });
    }

    @Override
    public boolean isExecuted() {
      return delegate.isExecuted();
    }

    @Override
    public Response<T> execute() throws IOException {
      return delegate.execute();
    }

    @Override
    public void cancel() {
      delegate.cancel();
    }

    @Override
    public boolean isCanceled() {
      return delegate.isCanceled();
    }
    ......
  }
}

当客户端调用Calle的enqueue()时

  • 将委托给DefaultCallAdapterFactory中匿名内部类ExecutorCallbackCall中的delegate,其是在HttpServiceMethod的invoke()中创建并传入的OkHttpCall
  • 当OkHttpCall的enqueue()结束后通过Callback回调callbackExecutor.execute()创建Runnable回调onFailure()和onResponse(),而callbackExecutor.execute()委托给了主线程的handler.post()
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值