当前位置: 首页 > news >正文

做礼品的网站linux做网站哪个版本好

做礼品的网站,linux做网站哪个版本好,电商无货源怎么做,网站做icp备案需要多久最好用的网络库#xff1a;Retrofit 文章目录 最好用的网络库#xff1a;RetrofitRetrofit的基本用法Retrofit的使用逻辑Retrofit的基本操作处理复杂的接口地址类型进阶删除提交header中指定参数 Retrofit构建器的最佳写法Retrofit的使用封装 用户网络请求的接口配置繁琐Retrofit 文章目录 最好用的网络库RetrofitRetrofit的基本用法Retrofit的使用逻辑Retrofit的基本操作处理复杂的接口地址类型进阶删除提交header中指定参数 Retrofit构建器的最佳写法Retrofit的使用封装 用户网络请求的接口配置繁琐尤其是需要配置复杂请求body请求头参数的时候; 数据解析过程需要用户手动拿到responsbody进行解析不能复用 无法适配自动进行线程的切换 万一我们的存在嵌套网络请求就会陷入“回调陷阱 Retrofit的基本用法 Retrofit是一款由Square公司开发的网络库但是它和OkHttp的定位完全不同。 OkHttp侧重的是底层通信的实现而Retrofit侧重的是上层接口的封装。事实上Retrofit就是Square公司在OkHttp的基础上进一步开发出来的应用层网络通信库使得我们可以用更加面向对象的思维进行网络操作。Retrofit的项目主页地址是https://github.com/square/retrofit。 Retrofit的设计基于以下几个事实。同一款应用程序中所发起的网络请求绝大多数指向的是同一个服务器域名。这个很好理解因为任何公司的产品客户端和服务器都是配套的很难想象一个客户端一会去这个服务器获取数据一会又要去另外一个服务器获取数据吧 另外服务器提供的接口通常是可以根据功能来归类的。比如新增用户、修改用户数据、查询用户数据这几个接口就可以归为一类上架新书、销售图书、查询可供销售图书这几个接口也可以归为一类。 将服务器接口合理归类能够让代码结构变得更加合理从而提高可阅读性和可维护性。最后开发者肯定更加习惯于调用一个接口获取它的返回值”这样的编码方式但当调用的是服务器接口时却很难想象该如何使用这样的编码方式。 其实大多数人并不关心网络的具体通信细节但是传统网络库的用法却需要编写太多网络相关的代码。 retrofit的作用是优化网络请求的 《使用》 Retrofit的使用逻辑 而Retrofit的用法就是基于以上几点来设计的首先我们可以配置好一个根路径然后在指定服务器接口地址时只需要使用相对路径即可这样就不用每次都指定完整的URL地址了。 另外Retrofit允许我们对服务器接口进行归类将功能同属一类的服务器接口定义到同一个接口文件当中从而让代码结构变得更加合理。 最后我们也完全不用关心网络通信的细节只需要在接口文件中声明一系列方法和返回值然后通过注解的方式指定该方法对应哪个服务器接口以及需要提供哪些参数。 当我们在程序中调用该方法时Retrofit会自动向对应的服务器接口发起请求并将响应的数据解析成返回值声明的类型。这就使得我们可以用更加面向对象的思维来进行网络操作。 Retrofit的基本操作 要想使用Retrofit我们需要先在项目中添加必要的依赖库。编辑app/build.gradle文件在dependencies闭包中添加如下内容 implementation com.squareup.retrofit2:retrofit:2.6.1 implementation com.squareup.retrofit2:converter-gson:2.6.1由于Retrofit是基于OkHttp开发的因此添加上述第一条依赖会自动将Retrofit、OkHttp和Okio这几个库一起下载我们无须再手动引入OkHttp库。另外Retrofit还会将服务器返回的JSON数据自动解析成对象因此上述第二条依赖就是一个Retrofit的转换库它是借助GSON来解析JSON数据的所以会自动将GSON库一起下载下来这样我们也不用手动引入GSON库了。除了GSON之外Retrofit还支持各种其他主流的JSON解析库包括Jackson、Moshi等不过毫无疑问GSON是最常用的。 由于Retrofit会借助GSON将J将JSON数据转换成对象因此这里同样需要新增一个App类并加入id、name和version这3个字段如下所示 public class App {private String id;private String name;private String version;// 构造函数public App(String id, String name, String version) {this.id id;this.name name;this.version version;}// Getter和Setter方法public String getId() {return id;}public void setId(String id) {this.id id;}public String getName() {return name;}public void setName(String name) {this.name name;}public String getVersion() {return version;}public void setVersion(String version) {this.version version;}// toString方法用于打印对象信息Overridepublic String toString() {return App{ id id \ , name name \ , version version \ };} }接下来我们可以根据服务器接口的功能进行归类创建不同种类的接口文件并在其中定义对应具体服务器接口的方法。不过由于这里只需要定义一个接口文件并包含一个方法即可。新建AppService接口代码如下所示 import retrofit2.Call; import retrofit2.http.GET; import java.util.List;public interface AppService {// 使用HTTP GET方法请求get_data.json路径GET(get_data.json)CallListApp getAppData(); }通常Retrofit的接口文件建议以具体的功能种类名开头并以Service结尾这是一种比较好的命名习惯。上述代码中有两点需要我们注意。 第一就是在getAppData()方法上面添加的注解这里使用了一个GET注解表示当调用getAppData()方法时Retrofit会发起一条GET请求请求的地址就是我们在GET注解中传入的具体参数。注意这里只需要传入请求地址的相对路径即可根路径我们会在稍后设置。第二就是getAppData()方法的返回值必须声明成Retrofit中内置的Call类型并通过泛型来指定服务器响应的数据应该转换成什么对象。由于服务器响应的是一个包含App数据的JSON数组因此这里我们将泛型声明成List。 当然Retrofit还提供了强大的Call Adapters功能来允许我们自定义方法返回值的类型比如Retrofit结合RxJava使用就可以将返回值声明成Observable、Flowable等类型 增加一个button用来测试功能 之后开始使用 import android.os.Bundle; import androidx.appcompat.app.AppCompatActivity; import android.widget.Button; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; import java.util.List; public class MainActivity extends AppCompatActivity {private Button getAppDataBtn;private AppService appService;Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);getAppDataBtn findViewById(R.id.get_app_data_btn); // 假设按钮的ID是get_app_data_btngetAppDataBtn.setOnClickListener(view - {Retrofit retrofit new Retrofit.Builder().baseUrl(http://10.0.2.2/).addConverterFactory(GsonConverterFactory.create()).build();appService retrofit.create(AppService.class);appService.getAppData().enqueue(new CallbackListApp() {Overridepublic void onResponse(CallListApp call, ResponseListApp response) {ListApp list response.body();if (list ! null) {for (App app : list) {//do}}}Overridepublic void onFailure(CallListApp call, Throwable t) {t.printStackTrace();}});});} }可以看到在“Get App Data”按钮的点击事件当中 首先使用了Retrofit.Builder来构建一个Retrofit对象其中baseUrl()方法用于指定所有Retrofit请求的根路径addConverterFactory()方法用于指定Retrofit在解析数据时所使用的转换库这里指定成GsonConverterFactory。 注意这两个方法都是必须调用的。有了Retrofit对象之后我们就可以调用它的create()方法并传入具体Service接口所对应的Class类型创建一个该接口的动态代理对象。如果你并不熟悉什么是动态代理也没有关系你只需要知道有了动态代理对象之后我们就可以随意调用接口中定义的所有方法而Retrofit会自动执行具体的处理就可以了。 对应到上述的代码当中当调用了AppService的getAppData()方法时会返回一个CallList对象这时我们再调用一下它的enqueue()方法Retrofit就会根据注解中配置的服务器接口地址去进行网络请求了服务器响应的数据会回调到enqueue()方法中传入的Callback实现里面。需要注意的是当发起请求的时候Retrofit会自动在内部开启子线程当数据回调到Callback中之后Retrofit又会自动切换回主线程整个操作过程中我们都不用考虑线程切换问题。在Callback的onResponse()方法中调用response.body()方法将会得到Retrofit解析后的对象也就是List类型的数据最后遍历List将其中的数据打印出来即可。 处理复杂的接口地址类型 为了方便举例这里先定义一个Data类并包含id和content这两个字段如下所示 public class Data {private String id;private String content;// 构造函数public Data(String id, String content) {this.id id;this.content content;}// id的getter和setterpublic String getId() {return id;}public void setId(String id) {this.id id;}// content的getter和setterpublic String getContent() {return content;}public void setContent(String content) {this.content content;}// toString方法用于打印对象信息Overridepublic String toString() {return Data{ id id \ , content content \ };} }然后我们先从最简单的看起比如服务器的接口地址如下所示GET http://example.com/get_data.json 这是最简单的一种情况接口地址是静态的永远不会改变。 但是显然服务器不可能总是给我们提供静态类型的接口在很多场景下接口地址中的部分内容可能会是动态变化的比如如下的接口地址 GET http://example.com/page/get_data.json在这个接口当中部分代表页数我们传入不同的页数服务器返回的数据也会不同。这种接口地址对应到Retrofit当中应该怎么写呢其实也很简单如下所示 import retrofit2.Call; import retrofit2.http.GET; import retrofit2.http.Path; public interface ExampleService {// 使用HTTP GET方法请求{page}/get_data.json路径// 其中{page}是一个动态的路径参数GET({page}/get_data.json)CallData getData(Path(page) int page); }在GET注解指定的接口地址当中这里使用了一个{page}的占位符然后又在getData()方法中添加了一个page参数并使用Path(“page”)注解来声明这个参数。 这样当调用getData()方法发起请求时Retrofit就会自动将page参数的值替换到占位符的位置从而组成一个合法的请求地址。 另外很多服务器接口还会要求我们传入一系列的参数格式如下 GET http://example.com/get_data.json?uuserttoken这是一种标准的带参数GET请求的格式。接口地址的最后使用问号来连接参数部分每个参数都是一个使用等号连接的键值对多个参数之间使用“”符号进行分隔。那么很显然在上述地址中服务器要求我们传入user和token这两个参数的值。对于这种格式的服务器接口我们可以使用刚才所学的Path注解的方式来解决但是这样会有些麻烦Retrofit针对这种带参数的GET请求专门提供了一种语法支持 import retrofit2.Call; import retrofit2.http.GET; import retrofit2.http.Query;public interface ExampleService {// 使用HTTP GET方法请求get_data.json路径// 并带有查询参数u和tGET(get_data.json)CallData getData(Query(u) String user, Query(t) String token); }这里在getData()方法中添加了user和token这两个参数并使用Query注解对它们进行声明。这样当发起网络请求的时候Retrofit就会自动按照带参数GET请求的格式将这两个参数构建到请求地址当中。 进阶 HTTP并不是只有GET请求这一种类型而是有很多种其中比较常用的有GET、POST、PUT、PATCH、DELETE这几种。它们之间的分工也很明确简单概括的话GET请求用于从服务器获取数据POST请求用于向服务器提交数据PUT和PATCH请求用于修改服务器上的数据DELETE请求用于删除服务器上的数据。 删除 而Retrofit对所有常用的HTTP请求类型都进行了支持使用GET、POST、PUT、PATCH、DELETE注解就可以让Retrofit发出相应类型的请求了。比如服务器提供了如下接口地址 DELETE http://example.com/data/id这种接口通常意味着要根据id删除一条指定的数据而我们在Retrofit当中想要发出这种请求就可以这样写 import retrofit2.Call; import retrofit2.http.DELETE; import retrofit2.http.Path; import okhttp3.ResponseBody;public interface ExampleService {// 使用HTTP DELETE方法请求data/{id}路径// 其中{id}是一个动态的路径参数DELETE(data/{id})CallResponseBody deleteData(Path(id) String id); }这里使用了DELETE注解来发出DELETE类型的请求并使用了Path注解来动态指定id这些都很好理解。但是在返回值声明的时候我们将Call的泛型指定成了ResponseBody这是什么意思呢 由于POST、PUT 、PATCH、DELETE这几种请求类型与GET请求不同它们更多是用于操作服务器上的数据而不是获取服务器上的数据所以通常它们对于服务器响应的数据并不关心。这个时候就可以使用ResponseBody表示Retrofit能够接收任意类型的响应数据并且不会对响应数据进行解析。 提交 那么如果我们需要向服务器提交数据该怎么写呢比如如下的接口地址 POST http://example.com/data/create {id: 1, content: The description for this data.}使用POST请求来提交数据需要将数据放到HTTP请求的body部分这个功能在Retrofit中可以借助Body注解来完成 import retrofit2.Call; import retrofit2.http.Body; import retrofit2.http.POST; import okhttp3.ResponseBody; import java.util.List;public interface ExampleService {// 使用HTTP POST方法请求data/create路径// Body注解用来指定请求体POST(data/create)CallResponseBody createData(Body Data data); }可以看到这里我们在createData()方法中声明了一个Data类型的参数并给它加上了Body注解。这样当Retrofit发出POST请求时就会自动将Data对象中的数据转换成JSON格式的文本并放到HTTP请求的body部分服务器在收到请求之后只需要从body中将这部分数据解析出来即可。这种写法同样也可以用来给PUT、PATCH、DELETE类型的请求提交数据。 header中指定参数 最后有些服务器接口还可能会要求我们在HTTP请求的header中指定参数比如 GET http://example.com/get_data.json User-Agent: okhttp Cache-Control: max-age0这些header参数其实就是一个个的键值对我们可以在Retrofit中直接使用Headers注解来对它们进行声明。 import retrofit2.Call; import retrofit2.http.GET; import retrofit2.http.Headers; import okhttp3.ResponseBody;public interface ExampleService {// 使用HTTP GET方法请求get_data.json路径// Headers注解用来添加请求头Headers({User-Agent: okhttp,Cache-Control: max-age0})GET(get_data.json)CallData getData(); }但是这种写法只能进行静态header声明如果想要动态指定header的值则需要使用Header注解如下所示 import retrofit2.Call; import retrofit2.http.GET; import retrofit2.http.Header; import your.package.name.Data; // 确保替换为Data类的实际包路径public interface ExampleService {// 使用HTTP GET方法请求get_data.json路径// Header注解用来添加动态的请求头GET(get_data.json)CallData getData(Header(User-Agent) String userAgent, Header(Cache-Control) String cacheControl); }现在当发起网络请求的时候Retrofit就会自动将参数中传入的值设置到User-Agent和CacheControl这两个header当中从而实现了动态指定header值的功能。 Retrofit构建器的最佳写法 获取Service接口的动态代理对象 import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; import your.package.name.AppService; // 确保替换为AppService接口的实际包路径// 创建Retrofit实例 Retrofit retrofit new Retrofit.Builder().baseUrl(http://10.0.2.2/) // 注意这里的URL应该以斜杠(/)结尾.addConverterFactory(GsonConverterFactory.create()).build();// 使用Retrofit实例来创建AppService接口的实例 AppService appService retrofit.create(AppService.class);我们想要得到AppService的动态代理对象需要先使用Retrofit.Builder构建出一个Retrofit对象然后再调用Retrofit对象的create()方法创建动态代理对象 确实也没有每次都写一遍的必要因为构建出的Retrofit对象是全局通用的只需要在调用create()方法时针对不同的Service接口传入相应的Class类型即可。因此我们可以将通用的这部分功能封装起来从而简化获取Service接口动态代理对象的过程。 新建一个ServiceCreator单例类代码如下所示 import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory;public class ServiceCreator {// 定义基础URLprivate static final String BASE_URL http://10.0.2.2/;// 静态内部类单例用于创建Retrofit实例private static class Holder {private static final Retrofit RETROFIT_INSTANCE new Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory(GsonConverterFactory.create()).build();}// 私有构造函数防止外部实例化private ServiceCreator() {}// 泛型方法用于创建服务接口的实例public static T T create(ClassT serviceClass) {return Holder.RETROFIT_INSTANCE.create(serviceClass);} }这里我们使用object关键字让ServiceCreator成为了一个单例类并在它的内部定义了一个BASE_URL常量用于指定Retrofit的根路径。 然后同样是在内部使用Retrofit.Builder构建一个Retrofit对象注意这些都是用private修饰符来声明的相当于对于外部而言它们都是不可见的。 最后我们提供了一个外部可见的create()方法并接收一个Class类型的参数。当在外部调用这个方法时实际上就是调用了Retrofit对象的create()方法从而创建出相应Service接口的动态代理对象。 经过这样的封装之后Retrofit的用法将会变得异常简单比如我们想获取一个AppService接口的动态代理对象只需要使用如下写法即可 import your.package.name.AppService; // 确保替换为AppService接口的实际包路径// 创建AppService接口的实例 AppService appService ServiceCreator.create(AppService.class);之后就可以随意调用AppService接口中定义的任何方法了。 Retrofit的使用封装 在经过上面我们对retrofit的一次封装之后我们现在调用retrofit发送网络请求时只需要AppService appService ServiceCreator.create(AppService.class);取得了AppService这个构建器之后使用这个构建器直接调用方法即可 不过我们也可以将一个常用的请求处理进行封装在封装的帮助类中进行处理这样在外部使用时只需要我们new出该类调用方法就可以直接获取我们请求返回的数据所封装成的类这个时候就可以直接使用这个类虽然这一步显得有点鸡肋不过这一步在我们使用的多的请求中可以比较方便。 首先写一个回调接口 public interface AppDataCallback {void onSuccess(App AppData);void onError(Throwable error); }接下来封装一个类 首先通过构造方法获取一个AppService实例 之后封装一下获取请求过程获得一个Call对象 接下来进入主要的部分我们在这里调用内部方法getAppData获取Call对象再调用enqueue方法进行使用enqueue方法允许异步地执行这个请求如果成功获取我们可以在这里对数据进行处理比如清理无用数据扩展数据等等这里我们就不进行处理直接返回我们调用AppDataCallback接口的onsuccess将数据返回。 public class AppServiceHelper {private AppService service;public AppServiceHelper() {this.service ServiceCreator.create(AppService.class);}//获取AppService实例public AppServiceHelper(AppService service) {this.service service;}//获取AppService实例// 发送请求并返回 CallApp 对象public CallApp getAppData(String apiKey, String cityCode, String extensions) {return service.getAppData(apiKey, cityCode, extensions);}// 异步执行请求并处理结果public void getAppDataAsync(String apiKey, String cityCode, String extensions, final AppDataCallback callback) {CallApp call getAppData(apiKey, cityCode, extensions);call.enqueue(new CallbackApp() {Overridepublic void onResponse(CallApp call1, ResponseRoot response) {if (response.isSuccessful()) {App AppData response.body();if (response.isSuccessful()) {callback.onSuccess(AppData);} else {callback.onError(new Throwable(Failed with status code: response.code()));}}}Overridepublic void onFailure(CallApp call1, Throwable t) {callback.onError(t);}});} }之后我们就可以使用这个辣 AppServiceHelper helper new AppServiceHelper(); helper.getWeatherDataAsync(....){ Overridepublic void onSuccess(Root weatherData) {// 这里仍然是在子线程中// 切换到主线程来更新UIrunOnUiThread(new Runnable() {Overridepublic void run() {// 在这里更新UI}});}Overridepublic void onError(Throwable t) {// 错误处理} }使用的时候我们获取这个帮助类实例然后直接调用方法即可获得数据对象之后开始使用即可。
http://www.hkea.cn/news/14474693/

相关文章:

  • 网站搜索功能微信如何制作网页
  • 网站开发员工资wordpress攻击教程
  • 长春网站建设哪家公司好wordpress 送女友
  • 遵义酷虎网站开发有没有代做模型的网站
  • 海洋公园网站建设方案wordpress页面排版插件
  • 正规的企业建站公司来宾住房和建设局网站
  • 网站采集来源无锡网页建站
  • 内蒙古自治区建设厅网站论文中网站数据则呢做文献参考
  • 网站建设公司成都四川广汇建设有限公司网站
  • 局域网做网站 内网穿透珠海中企网站建设公司
  • 泗阳网站定制.net网站
  • 试述网站开发的流程郑州设计网站的公司
  • j2ee网站开发参考文献wordpress 批量图片
  • 淮北公司做网站东莞品牌网站建设服务
  • 沈阳做网站建设wordpress搬家500错误
  • 自己做游戏网站wordpress动态页面
  • 广州 seo的网站网站顶部导航
  • 网站开发技术包括网站优秀网站地址
  • 网站建设怎么分好坏杨邦胜酒店设计公司官网
  • 网站建设基础书本上海企业网站制作哪家好
  • 服务器上的网站不能访问建公司网站要提供哪些素材
  • 制作微网站的平台有哪些西安建设和住房保障局网站
  • 搜狗站长平台验证不了自助建站自己要做网站的来看下
  • 深圳设计网站公司网站长沙企业网站建设分公司
  • 南京网站备案wordpress站关注别人
  • 网站备案号链接wordpress直接发送密码
  • 厦门建设网站中国菲律宾足球历史战绩
  • 做网站多少钱啊在门户网站建设上的讲话
  • 网站内容seo宿迁建设局网站a类证查询
  • 纯英文网站建设aspx网站配置服务器