日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android开发中无处不在的设计模式——动态代理模式

發(fā)布時間:2023/12/19 Android 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android开发中无处不在的设计模式——动态代理模式 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

繼續(xù)更新設計模式系列。寫這個模式的主要原因是近期看到了動態(tài)代理的代碼。
先來回想一下前5個模式:
- Android開發(fā)中無處不在的設計模式——單例模式
- Android開發(fā)中無處不在的設計模式——Builder模式
- Android開發(fā)中無處不在的設計模式——觀察者模式
- Android開發(fā)中無處不在的設計模式——原型模式
- Android開發(fā)中無處不在的設計模式——策略模式

動態(tài)代理模式在Java WEB中的應用簡直是隨處可見。尤其在Spring框架中大量的用到了動態(tài)代理;算是最重要的一個設計模式。也是最難理解的設計模式之中的一個。

那么什么叫動態(tài)代理呢

代理類在程序執(zhí)行前不存在、執(zhí)行時由程序動態(tài)生成的代理方式稱為動態(tài)代理。

當前的網(wǎng)絡請求庫多種多樣。當中Square公司的OkHttp簡直是完美的一個網(wǎng)絡請求庫,而在其上又封裝了一層的Retrofit庫,為方便快捷的調(diào)用Restful Api提供了一種捷徑。假設你用過Retrofit。一定不會忘記有會有這么一個過程:

  • 首先定義一個接口。接口中定義網(wǎng)絡請求的詳細方法。在方法上通過注解配置host,header。params等信息。

  • 然后新建一個Retrofit對象,通過該對象產(chǎn)生一個你定義的接口對象。

  • 通過接口對象調(diào)用詳細的方法完畢請求。

就像這樣子:

public interface GitHubService {@GET("users/{user}/repos")Call<List<Repo>> listRepos(@Path("user") String user);} Retrofit retrofit = new Retrofit.Builder().baseUrl("https://api.github.com").build();GitHubService service = retrofit.create(GitHubService.class); Call<List<Repo>> repos = service.listRepos("octocat");

那么你有沒有想過一個問題,接口是不能夠直接new出來的。GitHubService接口的實例是怎樣產(chǎn)生的呢。retrofit.create方法內(nèi)部究竟做了什么呢。沒錯。答案就是動態(tài)代理。該對象是程序執(zhí)行期生成的代理對象。

動態(tài)代理盡管在Java WEB中大量的用到,可是在client,因為考慮到性能的問題,所以用動態(tài)代理都會謹慎考慮,可是,一旦動態(tài)代理用的好,就會產(chǎn)生不一樣的效果,就比方這個Retrofit庫。以下,我們實現(xiàn)一個Retrofit的最最簡易的版本號。過一下動態(tài)代理的原理。因為是簡易版,所以非常多東西和Retrofit還是有差距的,自然也沒有Retrofit那么方便,這點無視就好了。我們就以實現(xiàn)上面那個樣例為例:

首先說明一點,我們的請求是異步的,所以返回值我們使用void,添加一個回調(diào)的參數(shù),約定最后一個參數(shù)是回調(diào)。

public interface Callback<T> {void onSuccess(Object t);void onFailed(Exception e);}

終于的接口定義會是這個樣子。

public interface GithubService {@GET("users/{user}/repos")void listRepos(@Path("user") String user,Callback<List<Repo>> callback);/*** 約定最后一個參數(shù)是callback*/}

用到了兩個注解。一個是方法注解,一個是參數(shù)注解

@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.METHOD})public @interface GET {String value() default "";} @Retention(RetentionPolicy.RUNTIME)@Target(ElementType.PARAMETER)public @interface Path {String value();}

Repo實體類是使用GsonFormat依據(jù)json自己主動生成的。

然后我們編寫Retrofit類,這個類應該是一個builder模式。里面能夠設置baseUrl,姑且忽略其它全部參數(shù)。另一個create方法。則原型例如以下:

public class Retrofit {private String baseUrl;private Retrofit(Builder builder) {this.baseUrl = builder.baseUrl;}public <T> T create(Class<T> clazz) {return null}static class Builder {private String baseUrl;Builder baseUrl(String host) {this.baseUrl = host;return this;}Retrofit build() {return new Retrofit(this);}} }

最最關鍵的內(nèi)容就是create方法的實現(xiàn)了。原理就是先拿到最后一個參數(shù),也就是回調(diào)。再拿到方法上的注解,獲得詳細的值。然后拿到除了回調(diào)之外的其它參數(shù),獲得參數(shù)上的注解,然后依據(jù)注解取得相應的值。還有原來的參數(shù)值。將方法上的注解的值中進行替換。使用OkHttp構造請求,請求完畢后依據(jù)將結果解析為回調(diào)中的類型。整個步驟例如以下

public <T> T create(Class<T> clazz) {/*** 緩存中去*/Object o = serviceMap.get(clazz);/*** 取不到則取構造代理對象*/if (o == null) {o = (T) Proxy.newProxyInstance(Retrofit.class.getClassLoader(), new Class[]{clazz}, new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {final Callback<?> callback = (Callback<?

>) args[args.length - 1]; final GET get = method.getAnnotation(GET.class); if (get != null) { /** * 獲得GET注解的值 */ String getValue = get.value(); System.out.println(getValue); /** * 獲得全部參數(shù)上的注解 */ Annotation[][] methodParameterAnnotationArrays = method.getParameterAnnotations(); if (methodParameterAnnotationArrays != null) { int count = methodParameterAnnotationArrays.length; for (int i = 0; i < count; i++) { /** * 獲得單個參數(shù)上的注解 */ Annotation[] methodParameterAnnotations = methodParameterAnnotationArrays[i]; if (methodParameterAnnotations != null) { for (Annotation methodParameterAnnotation : methodParameterAnnotations) { /** * 假設是Path注解 */ if (methodParameterAnnotation instanceof Path) { /** * 取得path注解上的值 */ Path path = (Path) methodParameterAnnotation; String pathValue = path.value(); System.out.println(pathValue); /** * 這是相應的參數(shù)的值 */ System.out.println(args[i]); Request.Builder builder = new Request.Builder(); /** * 使用path注解替換get注解中的值為參數(shù)值 */ String result = getValue.replaceAll("\\{" + pathValue + "\\}", (String) args[i]); System.out.println(result); /** * 開始構造請求 */ Request request = builder.get() .url(baseUrl + "/" + result) .build(); okHttpClient.newCall(request).enqueue(new okhttp3.Callback() { @Override public void onFailure(Call call, IOException e) { /** * 失敗則回調(diào)失敗的方法 */ callback.onFailed(e); } @Override public void onResponse(Call call, Response response) throws IOException { if (response.isSuccessful()) { /** * 請求成功 */ String body = response.body().string(); /** * 使用fastjson進行zhuan轉(zhuǎn)換 */ Type type = callback.getClass().getGenericInterfaces()[0]; Object o1 = JSON.parse(body); /** * 回調(diào)成功 */ callback.onSuccess(o1); } } }); } } } } } } return null; } }); /** * 扔到緩存中 */ serviceMap.put(clazz, o); } return (T) o; }

然后我們就能夠依據(jù)Retrofit那樣進行調(diào)用了

Retrofit retrofit = new Retrofit.Builder().baseUrl("https://api.github.com").build();GithubService githubService = retrofit.create(GithubService.class);githubService.listRepos("lizhangqu", new Callback<List<Repo>>() {@Overridepublic void onSuccess(Object t) {System.out.println(t);}@Overridepublic void onFailed(Exception e) {} });

這僅僅是Retrofit中最簡單的一個模塊實現(xiàn),假設對其它內(nèi)容感興趣,能夠閱讀retrofit的源代碼。

總結

以上是生活随笔為你收集整理的Android开发中无处不在的设计模式——动态代理模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。