在Android中使用Retrofit
我有一个Android应用程序,有3个活动:
- login活动
- 显示与用户有关的所有任务的任务活动(使用数组适配器填充)
- 通过单击列表上的任务生成的task_details活动
我必须使用REST Apis。 迄今为止我所做的研究指导我使用Retrofit。 我检查了如何使用它,发现:
- 在主要活动中设置基本URL(我的是login活动)
- 我需要创build一个API类,并使用注释来定义我的function。
- 在活动中使用类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'//用于翻新转换
- 如何使用Retrofit-Androidlogin请求和响应正文?
- javax.net.ssl.SSLException:读取错误:ssl = 0x9524b800:系统调用期间发生I / O错误,由对等方重置连接
- 翻新转换器工厂不能访问GsonConverterFactory
- (Retrofit)找不到类崩溃应用程序的转换器
- 添加标题的所有请求与改造2
- 使用Retrofit刷新OAuth令牌,无需修改所有调用
- CertPathValidatorException:未find证书path的信任锚 – 更新Android
- 如何在Retrofit库中设置超时?
- 不支持的操作:Android,Retrofit,OkHttp。 在OkHttpClient中添加拦截器