主要是討論兩個方面的問題俩块,一是攔截器的作用和寫法吏奸;二是為什么登錄失效要監(jiān)聽HTTP的請求欢揖,如有不足,萬望指出奋蔚。
OKHttp的攔截器
- 可以監(jiān)聽請求和響應(yīng)應(yīng)答她混,chain.proceed(request)是每個攔截器實現(xiàn)的關(guān)鍵部分烈钞。這個看似簡單的方法是所有HTTP 工作發(fā)生的地方, 在這里產(chǎn)生一個響應(yīng)應(yīng)答請求.
我們先過一下攔截器的基本寫法:
OKHttpClient client = new OKHttpClient();
client.interceptors().add(new MyInterceptor());
實現(xiàn)okhttp的interceptor, chain可以獲取http所以請求發(fā)生的地方坤按。
public class CityBaseInterceptor implements Interceptor{
private static final Charset UTF8 = Charset.forName("UTF-8");
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
long t1 = System.nanoTime();
logger.info(String.format("sending request : %s on %s%n%s",
request.url(),chain.connection(),request.headers()));
RequestBody requestBody = request.body();
Charset charset1 = UTF8;
MediaType contentType1 = requestBody.contentType();
if (contentType1 != null) {
charset1 = contentType1.charset(UTF8);
}
String questString = requestBody.toString();
/************/
Log.v("yjq", String.format("sending request : %s on %s%n%s%n%s",
request.url(),chain.connection(),request.headers(),questString));
Response response = chain.proceed(request);
long t2 = System.nanoTime();
logger.info(String.format("receive request for %s in %.1fms%n%s",
response.request().url(),(t2 - t1)/1e6d,response.headers()));
ResponseBody responseBody = response.body();
BufferedSource source = responseBody.source();
source.request(Long.MAX_VALUE); // Buffer the entire body.
Buffer buffer = source.buffer();
Charset charset = UTF8;
MediaType contentType = responseBody.contentType();
if (contentType != null) {
charset = contentType.charset(UTF8);
}
String bodyString = buffer.clone().readString(charset);
Log.v("yjq","body---------->" + bodyString);
//TODO 這里可以處理自己的業(yè)務(wù)請求毯欣,包括重新請求新的Token,獲取驗證信息等等臭脓。
//showDialog();
Log.v("yjq", String.format("receive request for %s in %.1fms%n%s",
response.request().url(),(t2 - t1)/1e6d,response.headers()));
return response;
}
}
其他的應(yīng)用場景為:
- 重寫請求
通過攔截器可以添加酗钞,移除,替換請求頭来累。也可以改變請求的請求體砚作。例如,在知道連接的web服務(wù)器是否支持壓縮格式的情況下嘹锁,可以使用應(yīng)用攔截器添加請求體壓縮類型葫录。 - 重寫響應(yīng)
相對應(yīng)地,攔截器可以重寫響應(yīng)頭和改變響應(yīng)體领猾。這一點比重寫寫請求頭要危險米同,因為可能違反web服務(wù)器的期望。
如果你處于一種比較糾結(jié)的狀態(tài)摔竿,并且準備處理結(jié)果窍霞,那么重寫響應(yīng)頭是解決問題的有效方法。例如拯坟,可以修復(fù)服務(wù)器配置錯誤的Cache-Control響應(yīng)頭是緩存更高效但金。
登錄失效的處理
APP的用戶登錄如果失效,或者在其他設(shè)備上登錄郁季,我們一般通過服務(wù)器推送失效通知給設(shè)備冷溃,提醒用戶保障賬戶安全,重新登錄梦裂。
如果我們需要在請求過程中通過服務(wù)器反饋的協(xié)商好的字段來判定用戶登錄信息是否失效似枕,則可以通過攔截器,并用全局的dialog提示年柠。
- 實現(xiàn)全局的dialog有幾種方式凿歼,一是通過WindowManager定義寬高,并inflate自定義的view冗恨。
final WindowManager wm = (WindowManager) MyApplication.getContext().getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams para = new WindowManager.LayoutParams();
para.height = -1;
para.width = -1;
para.format = 1;
para.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
para.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
final View mView = LayoutInflater.from(MyApplication.getContext()).inflate(
R.layout.test3, null);
wm.addView(mView, para);
二是通過一個后臺Service啟動一個dialog答憔,這個dialog需要添加一個窗口句柄:
mWindow.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
例子:
public class NewAlertDialog extends Dialog{
private Window mWindow;
private CloseSystemDialogsReceiver mCloseSystemDialogsReceiver;
protected NewAlertDialog(Context context) {
super(context);
}
protected NewAlertDialog(Context context, boolean cancelable, OnCancelListener cancelListener) {
super(context, cancelable, cancelListener);
}
protected NewAlertDialog(Context context, int themeResId) {
super(context, themeResId);
setContentView(R.layout.token_invalid);
mWindow = this.getWindow();
if(mWindow != null) {
WindowManager.LayoutParams attributes = mWindow.getAttributes();
// attributes.width = mWindow.getWindowManager().getDefaultDisplay()
// .getWidth();
attributes.width = WindowManager.LayoutParams.WRAP_CONTENT;
attributes.height = WindowManager.LayoutParams.WRAP_CONTENT;
mWindow.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
IntentFilter filter = new IntentFilter(
Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
mCloseSystemDialogsReceiver = new CloseSystemDialogsReceiver();
mWindow.getContext().registerReceiver(mCloseSystemDialogsReceiver,
filter);
}
}
private class CloseSystemDialogsReceiver extends BroadcastReceiver {
final String SYSTEM_DIALOG_REASON_KEY = "reason";
final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
@Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
String reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY);
if (SYSTEM_DIALOG_REASON_HOME_KEY.equals(reason)) {
NewAlertDialog.this.dismiss();
mWindow.getContext().unregisterReceiver(mCloseSystemDialogsReceiver);
getContext().stopService(new Intent(getContext(),WindowDialogService.class));
}
}
}
}
}
其中CloseSystemDialogsReceiver是處理SYSTEM.ALERT的dialog點擊Home鍵無法消失的問題。