【问题标题】:Cannot call GItHub search user API with Retrofit无法使用 Retrofit 调用 GItHub 搜索用户 API
【发布时间】:2020-05-08 19:56:03
【问题描述】:

我正在试验GitHub search users API。我的目标是编写一个简单的应用程序:输入用户名,任何与之相关的 GitHub 用户名都将显示在 RecyclerView 上(使用 MVVM 模式)。

例如,搜索用户名clive的方法如下:

https://api.github.com/search/users?q=clive

以下是代码的相关部分:

APIConfig.java

public class APIConfig {

    public static final String BASE_URL = "https://api.github.com";
    public static final String END_POINT_SEARCH_USERS = "/search/users";

}

APIEndPoint.java

import com.divbyzero.app.githubusersearch.model.User;

import java.util.List;

import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Query;

public interface APIEndPoint {

    @GET(APIConfig.END_POINT_SEARCH_USERS)
    Call<List<User>> getSearchResult(@Query("q") String param);

}

User.java

    package com.divbyzero.app.githubusersearch.model;

    import com.google.gson.annotations.Expose;
    import com.google.gson.annotations.SerializedName;

    public class User {

        @SerializedName("login")
        @Expose
        private String login;

        @SerializedName("avatar_url")
        @Expose
        private String avatar_url;

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

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

        public String getLogin(){
            return login;
        }

        public String getAvatarUrl(){
            return avatar_url;
        }

        public User(String login, String url){
            this.login = login;
            this.avatar_url = url;
        }
    }

UserViewModel.java

  package com.divbyzero.app.githubusersearch.viewmodel;

    import android.util.Log;

    import androidx.lifecycle.LiveData;
    import androidx.lifecycle.MutableLiveData;
    import androidx.lifecycle.ViewModel;

    import com.divbyzero.app.githubusersearch.api.APIEndPoint;
    import com.divbyzero.app.githubusersearch.api.APIService;
    import com.divbyzero.app.githubusersearch.model.User;

    import java.util.ArrayList;
    import java.util.List;

    import retrofit2.Call;
    import retrofit2.Callback;
    import retrofit2.Response;
    import retrofit2.Retrofit;

    public class UserViewModel extends ViewModel {

        private MutableLiveData<ArrayList<User>> mutableLiveData = new MutableLiveData<>();

        public void setSearchResult(String param){
            Retrofit retrofit = APIService.getRetrofitService();
            APIEndPoint apiEndpoint = retrofit.create(APIEndPoint.class);
            Call<List<User>> call = apiEndpoint.getSearchResult(param);
            call.enqueue(new Callback<List<User>>() {
                @Override
                public void onResponse(Call<List<User>> call, Response<List<User>> response) {
                    mutableLiveData.setValue((ArrayList<User>) response.body());
                    Log.d("DBG", "OK");
                }

                @Override
                public void onFailure(Call<List<User>> call, Throwable t) {
                    Log.d("DBG", "Failed");
                }
            });
        }

        public LiveData<ArrayList<User>> getSearchResult(){
            return mutableLiveData;
        }
    }

完整源代码:https://github.com/anta40/GithubUserSearch

当我在 SearchView 上键入任何用户名并按 ENTER 键时,不会显示任何搜索结果(recyclerview 仍为空)。经过进一步检查,我发现logcat上显示“DBG:Failed”,这意味着GitHub API没有正确调用。如何解决这个问题?

【问题讨论】:

    标签: android retrofit android-mvvm


    【解决方案1】:

    错误

    您的视图模型中出现的错误是:

    Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
    

    所以解析您的回复时出现问题。您正在接收它,但解析错误。

    原因

    调用此 GET 请求(您正在使用)后:

    https://api.github.com/search/users?q=some_name
    

    我收到了:

    {
      "total_count": 0,
      "incomplete_results": false,
      "items": [
    
      ]
    }
    

    问题出在哪里

    基于接收.json 我知道,作为根元素的是JSON OBJECT。在您的 ViewModel 中,您期望 List&lt;User&gt; (JSON ARRAY) 这是不正确的。您正在接收具有 3 个字段的对象。此字段之一是您的List&lt;User&gt;

    修复 - 描述

    您必须创建新的模型类来描述您收到的数据。要解析(从 json 到 Java)所有接收到的数据,它应该包含 3 个字段。

    修复 - 代码

    您的新课程示例:

    public class GitHubResponse {
        private long totalCount;
        private boolean incompleteResults;
        private List<User> items;
    }
    

    并在 ViewModel 和 APIEndPoint.java 的任何地方使用此类。访问数据 - 此类的广告获取者。

    一般项目提示/提示

    • 重新格式化代码(Ctrl + Alt + L

    • 添加“start”状态(因为启动后app view是空的)

    • 添加空状态(当接收到的数据为空时)

    • 添加加载状态(当您正在加载数据并等待响应时)

    • 添加错误状态(连接失败或解析数据出现问题时)

    【讨论】:

    • 好的,谢谢。现在它起作用了。无论如何,我仍然对这种 MVVM 模式不太熟悉。清除mutableLiveData 的惯用方法是什么,因此以前的搜索结果不会显示在recyclerView 中?我想通过在setSearchResult() 的开头添加mutableLiveData.setValue(new ArrayList&lt;User&gt;());
    • 没有。您应该创建新的 LiveData 说明当前视图的“状态”。您可以创建如下状态:no internetfirst runshow dataempty data... 等。表示您可以使用对象或简单的enum 创建新类。所以片段/活动网站上没有逻辑。所有的状态都应该在 ViewModel 中设置。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-27
    • 2011-07-22
    • 2016-10-03
    • 1970-01-01
    • 2020-03-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多