在Android中使用Retrofit

我有一个Android应用程序,有3个活动:

  1. login活动
  2. 显示与用户有关的所有任务的任务活动(使用数组适配器填充)
  3. 通过单击列表上的任务生成的task_details活动

我必须使用REST Apis。 迄今为止我所做的研究指导我使用Retrofit。 我检查了如何使用它,发现:

  1. 在主要活动中设置基本URL(我的是login活动)
  2. 我需要创build一个API类,并使用注释来定义我的function。
  3. 在活动中使用类Rest适配器并定义callback。

如果我的应用程序是一个单一的活动应用程序,我会碾碎我的MainActivity.java中的一切,但我不知道如何以及在哪里把步骤1,2,3中的所有代码放在我的3个活动中使用。通过告诉如何在我的应用程序中使用Retrofit帮助。 非常感谢。

具体来说,我需要networking电话来:1.login用户2.获取用户的所有任务。 而对于我将使用给定的REST API。

使用Retrofit非常简单直接。

首先,您需要为您的项目添加改造,例如使用Gradle构build系统。

compile 'com.squareup.retrofit:retrofit:1.7.1' | 

另一种方法,您可以下载.jar并将其放置到您的libs文件夹。

然后,您需要定义接口,这些接口将被Retrofit用于对REST端点进行API调用。 例如对于用户:

 public interface YourUsersApi { //You can use rx.java for sophisticated composition of requests @GET("/users/{user}") public Observable<SomeUserModel> fetchUser(@Path("user") String user); //or you can just get your model if you use json api @GET("/users/{user}") public SomeUserModel fetchUser(@Path("user") String user); //or if there are some special cases you can process your response manually @GET("/users/{user}") public Response fetchUser(@Path("user") String user); } 

好。 现在您已经定义了您的API接口,您可以尝试使用它。

要开始,你需要创build一个RestAdapter的实例,并设置你的API后端的基础URL。 这也很简单:

 RestAdapter restAdapter = new RestAdapter.Builder() .setEndpoint("https://yourserveraddress.com") .build(); YourUsersApi yourUsersApi = restAdapter.create(YourUsersApi.class); 

这里Retrofit会从界面读取你的信息,并且根据你提供的meta-info来创buildRestHandler ,这些信息实际上会执行HTTP请求。

然后,在收到响应之后,如果使用json api,则您的数据将使用Gson库转换为您的模型,因此您应该意识到Gson中存在的限制实际上存在于Retrofit中。

要扩展/覆盖您的串行器/反序列化您的响应数据到您的模型,您可能想要提供您的定制串行/解串器进行改造。

这里你需要实现Converter接口,并实现从Body()toBody()两个方法。

这里是例子:

 public class SomeCustomRetrofitConverter implements Converter { private GsonBuilder gb; public SomeCustomRetrofitConverter() { gb = new GsonBuilder(); //register your cursom custom type serialisers/deserialisers if needed gb.registerTypeAdapter(SomeCutsomType.class, new SomeCutsomTypeDeserializer()); } public static final String ENCODING = "UTF-8"; @Override public Object fromBody(TypedInput body, Type type) throws ConversionException { String charset = "UTF-8"; if (body.mimeType() != null) { charset = MimeUtil.parseCharset(body.mimeType()); } InputStreamReader isr = null; try { isr = new InputStreamReader(body.in(), charset); Gson gson = gb.create(); return gson.fromJson(isr, type); } catch (IOException e) { throw new ConversionException(e); } catch (JsonParseException e) { throw new ConversionException(e); } finally { if (isr != null) { try { isr.close(); } catch (IOException ignored) { } } } } @Override public TypedOutput toBody(Object object) { try { Gson gson = gb.create(); return new JsonTypedOutput(gson.toJson(object).getBytes(ENCODING), ENCODING); } catch (UnsupportedEncodingException e) { throw new AssertionError(e); } } private static class JsonTypedOutput implements TypedOutput { private final byte[] jsonBytes; private final String mimeType; JsonTypedOutput(byte[] jsonBytes, String encode) { this.jsonBytes = jsonBytes; this.mimeType = "application/json; charset=" + encode; } @Override public String fileName() { return null; } @Override public String mimeType() { return mimeType; } @Override public long length() { return jsonBytes.length; } @Override public void writeTo(OutputStream out) throws IOException { out.write(jsonBytes); } } } 

现在,您需要启用您的自定义适配器,如果需要通过在构buildRestAdapter上使用setConverter()

好。 现在您已经意识到如何将您的数据从服务器传送到您的Android应用程序。 但是你需要以某种方式pipe理你的数据,并在正确的地方调用REST调用。 在那里,我会build议使用Android服务或AsyncTask或加载器或rx.java,将后台线程查询您的数据,以不阻止您的用户界面。

所以现在你可以find最合适的地方来打电话

 SomeUserModel yourUser = yourUsersApi.fetchUser("someUsers") 

获取您的远程数据。

我刚刚使用了几个星期的改造,起初我发现很难在我的应用程序中使用。 我想与大家分享在您的应用程序中使用改造的最简单方法。 然后如果你已经对改造有了很好的把握,你可以增强你的代码(把你的用户界面和API分开,并使用callback),也许从上面的post中可以得到一些技巧。

在你的应用程序中,你有login,活动列表的任务,和活动查看详细的任务。

首先,您需要在您的应用程序中添加翻新,然后按照上面的方法添加@artemis。

改造使用接口作为您的API。 所以,创build一个接口类。

 public interface MyApi{ /*LOGIN*/ @GET("/api_reciever/login") //your login function in your api public void login(@Query("username") String username,@Query("password") String password,Callback<String> calback); //this is for your login, and you can used String as response or you can use a POJO, retrofit is very rubust to convert JSON to POJO /*GET LIST*/ @GET("/api_reciever/getlist") //a function in your api to get all the list public void getTaskList(@Query("user_uuid") String user_uuid,Callback<ArrayList<Task>> callback); //this is an example of response POJO - make sure your variable name is the same with your json tagging /*GET LIST*/ @GET("/api_reciever/getlistdetails") //a function in your api to get all the list public void getTaskDetail(@Query("task_uuid") String task_uuid,Callback<Task> callback); //this is an example of response POJO - make sure your variable name is the same with your json tagging } 

创build另一个接口类来保存你的API的所有BASE ADDRESS

 public interface Constants{ public String URL = "www.yoururl.com" } 

在您的login活动中创build一个方法来处理改造

 private void myLogin(String username,String password){ RestAdapter restAdapter = new RestAdapter.Builder() .setEndpoint(Constants.URL) //call your base url .build(); MyApi mylogin = restAdapter.create(MyApi.class); //this is how retrofit create your api mylogin.login(username,password,new Callback<String>() { @Override public void success(String s, Response response) { //process your response if login successfull you can call Intent and launch your main activity } @Override public void failure(RetrofitError retrofitError) { retrofitError.printStackTrace(); //to see if you have errors } }); } 

在你的MainActivityList中

 private void myList(String user_uuid){ RestAdapter restAdapter = new RestAdapter.Builder() .setEndpoint(Constants.URL) //call your base url .build(); MyApi mytask = restAdapter.create(MyApi.class); //this is how retrofit create your api mytask.getTaskDetail(user_uuid,new Callback<Task>>() { @Override public void success(ArrayList<Task> list, Response response) { //process your response if successful load the list in your listview adapter } @Override public void failure(RetrofitError retrofitError) { retrofitError.printStackTrace(); //to see if you have errors } }); } 

在您的详细清单

 private void myDetailed(String task_uuid){ RestAdapter restAdapter = new RestAdapter.Builder() .setEndpoint(Constants.URL) //call your base url .build(); MyApi mytask = restAdapter.create(MyApi.class); //this is how retrofit create your api mytask.getTaskList(task_uuid,new Callback<Task>() { @Override public void success(Task task, Response response) { //process your response if successful do what you want in your task } @Override public void failure(RetrofitError retrofitError) { retrofitError.printStackTrace(); //to see if you have errors } }); } 

希望这会帮助你,虽然它真的是最简单的方式来使用改造。

看看这个,与Otto一起使用Retrofit的优秀博客,这两个库都来自Square。

http://www.mdswanson.com/blog/2014/04/07/durable-android-rest-clients.html

基本的想法是你将在你的Application类中持有一个对“repository”对象的引用。 这个对象将有“订阅”restapi事件请求的方法。 当收到一个,它会做出正确的翻新调用,然后“张贴”的响应,然后可以由另一个组件(如发出请求的活动)“订阅”。

一旦你有这个设置正确,通过你的restapi访问数据变得非常容易。 例如,对数据的请求将看起来像这样:

  mBus.post(new GetMicropostsRequest(mUserId)); 

并且消费数据将如下所示:

 @Subscribe public void onGetUserProfileResponse(GetUserProfileResponse event) { mView.setUserIcon("http://www.gravatar.com/avatar/" + event.getGravatar_id()); mView.setUserName(event.getName()); } 

它需要一点点前期的努力,但最终通过Rest从后端访问任何你需要的东西变得“微不足道”。

您可以尝试在您的应用程序类中保存对您的api的引用。 然后,你可以从任何活动或片段得到它的实例,并从那里得到API。 这听起来有点奇怪,但它可能是一个简单的DI替代scheme。 如果你只会在你的应用程序类中存储引用,它不会是一种神的对象

UPD: http : //square.github.io/retrofit/ – 这里有一些文档,它可能是有用的

使用RetroFit是非常容易的。

  • 在build.gradle中添加依赖。

      compile 'com.squareup.retrofit:retrofit:1.9.0' compile 'com.squareup.okhttp:okhttp:2.4.0' 
  • 为所有http方法创build一个接口。

  • 复制你的json输出并创buildpojo类来接收你的json
    响应,你可以从JsonSchema2pojo站点创buildpojo。

  • 制作一个适配器并调用你的方法

    完整的演示试试本教程Retrofit Android示例

检出此应用程序,演示Retrofit集成到Google Tasks API。

https://github.com/sschendel/SyncManagerAndroid-DemoGoogleTasks

在MainActivity的Activity AsyncTask中使用了Retrofit api(TaskApi)的示例,以及在后台服务中的Sync Adapter中使用的示例。

从@nPn的答案发表的文章中的战略可能是一个更优雅的解决scheme,但你至less可以看看另一个工作的例子。

首先,将所有内容放在MainActivity中将是不好的做法,最终会有一个上帝的对象 。

翻新网站上的文档是非常棒的,所以我将阅读你关于如何构build项目的问题。 我写了一个非常小的应用程序用于演示目的。 它从猫的API中加载猫,并且应该相当简单地遵循所发生的事情。

它有一个使用JSON或XML来parsing服务数据的例子。 你可以在https://github.com/codepath/android_guides/wiki/Consuming-APIs-with-Retrofitfind它;

希望你能推断为什么我按照我的方式来构build它。 我很乐意回答您在评论中提出的任何问题,并更新答案。

我发现这些教程AndroidHive , CodePath很有帮助

我将简要描述我所学到的东西。

第1步:将这三个dependencies to build.gradle添加dependencies to build.gradle并将Internet permission添加到Manifest

 compile 'com.google.code.gson:gson:2.6.2' // for string to class conversion. Not Compulsory compile 'com.squareup.retrofit2:retrofit:2.1.0'// compulsory compile 'com.squareup.retrofit2:converter-gson:2.1.0' //for retrofit conversion 

将它们添加到清单中

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

第2步 Creae ApiClient和ApiInterface。

 public class ApiClient { public static final String BASE_URL = "http://yourwebsite/services/"; private static Retrofit retrofit = null; public static Retrofit getClient() { if (retrofit==null) { retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build(); } return retrofit; } } 

其中ApiInterface.class

 public interface ApiInterface { // getting same data in three different ways. @GET("GetCompanyDetailByID") Call<CompanyResponse> getDetailOfComapanies(@Query("CompanyID") int companyID); @GET("GetCompanyDetailByID") Call<ResponseBody> getRawDetailOfCompanies(@Query("CompanyID") int companyID); @GET("{pathToAdd}") Call<CompanyResponse> getDetailOfComapaniesWithPath(@Path("pathToAdd") String pathToAppend, @Query("CompanyID") int companyID); } 

并调用这个服务

 ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class); Call<CompanyResponse> companyResponseCall = apiService.getDetailOfComapanies(2); //Call<CompanyResponse> companyResponseCall = apiService.getDetailOfComapaniesWithPath("GetCompanyDetailByID",2); companyResponseCall.enqueue(new Callback<CompanyResponse>() { @Override public void onResponse(Call<CompanyResponse> call, Response<CompanyResponse> response) { CompanyResponse comapnyResponse = response.body(); Boolean status = comapnyResponse.getStatus(); } @Override public void onFailure(Call<CompanyResponse> call, Throwable t) { } }); 

获取生Jsonstring

 Call<ResponseBody> call = apiService.getRawDetailOfCompanies(2); call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { String jsonStr = response.body().string(); if(!jsonStr.isEmpty()){ Gson gson = new Gson(); JSONObject jObject = new JSONObject(jsonStr).getJSONObject("data"); //1st Method Data dataKiType = gson.fromJson(jObject.toString(), Data.class); dataKiType.getCompanyDetail(); //2nd method for creaing class or List at runTime Type listType = new TypeToken<Data>(){}.getType(); Data yourClassList = new Gson().fromJson(jObject.toString(), listType); yourClassList.getCompanyDetail(); } e.printStackTrace(); } } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { } }); 

您可以使用http://www.jsonschema2pojo.org/通过简单地粘贴json来创build您的业务对象。; 并select源types为JSON和注记风格为GSon

初学者发现学习改造的可怕性不大。 我准备了一个简化学习曲线的教程。 有关更多信息,请参阅Retrofit android教程 。

它的工作

在这里输入图像说明 包com.keshav.gmailretrofitexampleworking.network;

 import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; public class ApiClient { public static final String BASE_URL = "http://api.androidhive.info/json/"; private static Retrofit retrofit = null; public static Retrofit getClient() { if (retrofit == null) { retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build(); } return retrofit; } } ============================================== package com.keshav.gmailretrofitexampleworking.network; import com.keshav.gmailretrofitexampleworking.models.Message; import java.util.List; import retrofit2.Call; import retrofit2.http.GET; public interface ApiInterface { @GET("inbox.json") Call<List<Message>> getInbox(); } 

编译'com.google.code.gson:gson:2.6.2'

 compile 'com.squareup.retrofit2:retrofit:2.0.2' compile 'com.squareup.retrofit2:converter-gson:2.0.2' 

================================================== ===

在onCreate内调用改装2APi

 private void getInbox() { swipeRefreshLayout.setRefreshing(true); ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class); Call<List<Message>> call = apiService.getInbox(); call.enqueue(new Callback<List<Message>>() { @Override public void onResponse(Call<List<Message>> call, Response<List<Message>> response) { // clear the inbox messages.clear(); // add all the messages // messages.addAll(response.body()); // TODO - avoid looping // the loop was performed to add colors to each message Log.e("keshav","response" +response.body()); for (Message message : response.body()) { // generate a random color // TODO keshav Generate Random Color Here message.setColor(getRandomMaterialColor("400")); messages.add(message); } mAdapter.notifyDataSetChanged(); swipeRefreshLayout.setRefreshing(false); } @Override public void onFailure(Call<List<Message>> call, Throwable t) { Toast.makeText(getApplicationContext(), "Unable to fetch json: " + t.getMessage(), Toast.LENGTH_LONG).show(); swipeRefreshLayout.setRefreshing(false); } }); } 

源代码https://drive.google.com/open?id=0BzBKpZ4nzNzUVFRnVVkzc0JabUU

https://drive.google.com/open?id=0BzBKpZ4nzNzUc2FBdW00WkRfWW8

开发你自己的types安全的HTTP库来与REST API接口可能是一个真正的痛苦:你必须处理许多方面,比如进行连接,caching,重试失败的请求,线程,响应parsing,error handling等等。 另一方面,改造是一个精心策划的,logging和testing的图书馆,将为您节省大量的宝贵时间和头痛。

编译'com.google.code.gson:gson:2.6.2'

编译'com.squareup.retrofit2:翻新:2.1.0'//强制

编译'com.squareup.retrofit2:converter-gson:2.1.0'//用于翻新转换