Retrofit - Android 的 REST 客户端 (Retrofit 2.X)
使用 Retrofit 开发 Android 应用程序以连接到 API。
引言
在本教程中,我们将学习 Retrofit 的基础知识,并创建一个 Android 客户端,用于向 GitHub API 发起 HTTP 请求。
背景
Retrofit 是一个用于 Java 和 Android 的 REST 客户端。通过 Retrofit,您可以非常轻松地通过基于 REST 的 Web 服务在您的 Android 移动应用程序中检索和/或上传 JSON(或其他结构化数据)。
在本教程中,我们将学习 Retrofit 的基础知识,并创建一个 Android 客户端,用于向 GitHub API 发起 HTTP 请求。
- 以下是实现步骤
- 创建一个 Android 项目
- 定义 Gradle 依赖项
- 定义 Android 的网络权限
- 描述 API 端点
- 创建用户界面
- 配置 JSON 映射
- 创建 Retrofit 客户端
- 执行请求并显示数据
Using the Code
使用您喜欢的 IDE 创建一个 Android 项目。我将使用 Android Studio。您可以创建一个空的 Activity 项目。
在 Gradle Scripts 部分选择 build.gradle (module) 文件,并将 Retrofit 指定为项目的依赖项。
dependencies {
//Other dependencies...
// Retrofit & OkHttp dependency
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
}
添加依赖项后,点击 Sync Now 链接。
当您运行构建命令时,构建系统将下载并提供必要的库。
注意:Retrofit 2 (默认情况下) 包含 OkHttp 作为网络层。因此,您无需显式将 OkHttp 定义为项目的依赖项。但是,Retrofit 2 需要一个依赖项来自动转换请求和响应。默认的转换器是 Gson。Gson 是一个非常强大的库,用于将 JSON 表示的数据结构映射到 Java 对象。
定义 Android 的网络权限
Android 应用程序设计为在沙盒环境中运行。Retrofit 会向在 Internet 服务器上运行的 API 发起 HTTP 请求。为了从 Android 应用程序执行此类外部请求,需要 Internet 权限来打开网络套接字。因此,您需要在 AndroidManifest.xml 文件中定义这些权限。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="app.retrofit.nipunu.retrofitapp">
<uses-permission android:name="android.permission.INTERNET" />
<application
...
描述 API 端点
为了发送请求,您首先需要描述 API 端点。在本教程中,我们将描述一个简单的 GitHub API 端点。
在您的应用程序源代码集中创建一个名为 GitHubClient
的接口。
选择接口作为“种类”,然后点击 OK。
现在您应该已经创建了您的接口。
定义一个名为 UserRepositories
的方法,该方法接受一个 string
类型的参数,该参数将是用户名。此方法将返回一个 RepoList
类型的列表。
public interface GitHubClient {
List<RepoList> UserRepositories(String phrase);
}
由于我们发出一个 Get
请求来检索结果,因此我们需要像这样用端点注解我们的方法。@GET
注解声明此请求使用 HTTP GET
方法。
import retrofit2.http.GET;
public interface GitHubClient {
@GET("users/USER_NAME/repos")
List<RepoList> UserRepositories(String phrase);
}
我们可以使用 Retrofit 的路径参数替换功能,而不是硬编码用户名,如下所示:
import retrofit2.http.Path;
public interface GitHubClient {
@GET("users/{username}/repos")
List<RepoList> UserRepositories(@Path("username") String userName);
}
当前,UserRepositories
是一个同步方法,它将冻结 UI 并在 Android 4.0 或更高版本上崩溃应用程序。作为一项规则,来自 UI 线程的网络请求需要异步进行。我们可以通过将方法返回包装在 call<>
对象中来轻松地使此方法调用异步,如下所示:
public interface GitHubClient {
@GET("users/{username}/repos")
Call<List<RepoList>> UserRepositories(@Path("username") String userName);
}
完整的 GitHubClient
如下所示:
import java.util.List;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Path;
public interface GitHubClient {
@GET("users/{username}/repos")
Call<List<RepoList>> UserRepositories(@Path("username") String userName);
}
我们还没有实现 RepoList
类。让我们去为我们的应用程序添加 RepoList
类。
创建一个名为 RepoList
的类。此类用于与返回数据进行映射。在这种情况下,我们只匹配存储库的名称。
public class RepoList {
private String name;
public String getRepoName(){return name;}
}
创建用户界面
我们需要一个 UI 来显示结果。让我们使用 ListView
控件来显示我们接收到的存储库名称。
删除 activity_mail.xml 文件中的默认 Textview
,并创建一个 ID 为 repository_list
的 ListView
控件。设置约束使 ListView
填充整个 Activity 的空间。
在 MainActivity.class 文件的 onCreate
方法中引用 Listview
。
public class MainActivity extends AppCompatActivity {
private ListView repositoryList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
repositoryList = (ListView)findViewById(R.id.repository_list);
}
}
现在我们需要创建一个 Layout
来容纳 ListView
的单个项,也就是我们存储库的名称。
创建一个名为 repository_list_item.xml 的新布局。在该布局中添加一个 TextView
,并将其命名为 repository_name_text
。
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/repository_name_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
ListView
需要一个适配器来加载数据。让我们创建 adapter
类。
创建一个名为 RepoListAdapter
的类,该类扩展了 RepoList
类型的 ArrayAdapter
。
import android.widget.ArrayAdapter;
public class RepoListAdapter extends ArrayAdapter<RepoList> {
Context context;
List<RepoList> repoList;
}
为该类添加一个构造函数。
public RepoListAdapter(Context context, List<RepoList> repoList) {
super(context, R.layout.repository_list_item,repoList);
this.context = context;
this.repoList = repoList;
}
最后,重写 getView
方法以检索每个 repo 名称并将其设置为 TextView
。
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
if (row == null) {
LayoutInflater inflater =
(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.repository_list_item, parent, false);
}
TextView textView = (TextView) row.findViewById(R.id.repository_name_text);
RepoList list = repoList.get(position);
String repoName = list.getRepoName();
textView.setText(repoName);
return row;
}
现在,在 MainActivity
的 onCreate
方法中,让我们实例化 Retrofit
构建器类。此类负责为我们创建 Retrofit
对象。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
repositoryList = (ListView) findViewById(R.id.repository_list);
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.addConverterFactory(GsonConverterFactory.create());
}
接下来,在同一个 onCreate
方法中,让我们借助构建器创建 Retrofit
对象并发出 API 调用。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
repositoryList = (ListView) findViewById(R.id.repository_list);
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.build();
GitHubClient client = retrofit.create(GitHubClient.class);
Call<List<RepoList>> call = client.UserRepositories("USER_NAME");
}
上面的调用是一个异步方法调用。因此,我们需要通过 enqueue 方法将此调用异步地作为一个新的回调来实现。
call.enqueue(new Callback<List<RepoList>>() {
@Override
public void onResponse(Call<List<RepoList>> call, Response<List<RepoList>> response) {
}
@Override
public void onFailure(Call<List<RepoList>> call, Throwable t) {
}
});
作为最后一步,我们需要实现 onResponse
和 onFailure
方法。
call.enqueue(new Callback<List<RepoList>>() {
@Override
public void onResponse(Call<List<RepoList>> call, Response<List<RepoList>> response) {
List<RepoList> list = response.body();
repositoryList.setAdapter(new RepoListAdapter(MainActivity.this,list));
}
@Override
public void onFailure(Call<List<RepoList>> call, Throwable t) {
Toast.makeText(MainActivity.this, "Error...!!!", Toast.LENGTH_SHORT).show();
}
});
现在运行应用程序。
历史
- 2019年8月20日:初始版本