第一步,添加依赖库'com.;
自动下载两个库,OkHttp和Okio,后者是前者的通信基础
第二步,具体用法
创建OkHttpClient实例
实现一个默认的客户端,没有连接时间限制
OkHttpClient client=new OkHttpClient();
实现一个对连接时间读取时间有限制的客户端,超过时间限制,强制失败
OkHttpClient client=new OkH().connectTimeout(8000, TimeUnit.MILLISECONDS).readTimeout(8000,TimeUnit.MILLISECONDS).build();
发起Http请求(GET)
有同步和异步两种
同步需要自己开一个线程,执行网络连接
创建request请求,并在build()方法前连缀属性;
调用client的newCall()方法创建Call对象;
调用Call对象的excute()方法获取服务器返回的数据response;
返回结果数据格式依赖服务器实现
- new Thread(new Runnable() {
- @Override
- public void run() {
- OkHttpClient client=new OkH().connectTimeout(8000, TimeUnit.MILLISECONDS).readTimeout(8000,TimeUnit.MILLISECONDS).build();
- Request request= new Reque().url(address).build();
- try {
- Response response=client.newCall(request).execute();
- if () != null) {
- String strResponse = re().string();
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }).start();
异步get请求,因为onResponse和onFailure()默认开启子线程,需要更新UI时,需要跳转主UI线程
- OkHttpClient client=new OkH().connectTimeout(8000, TimeUnit.MILLISECONDS).readTimeout(8000,TimeUnit.MILLISECONDS).build();
- Request request= new Reque().url(address).build();
- client.newCall(request).enqueue(new callback() {
- @Override
- public void onFailure(Call call, IOException e) {
- // do something
- Log.d("http connect","失败");
- Log.d("http connect","e"+e.toString());
- }
- @Override
- public void onResponse(Call call, Response response) throws IOException {
- if ()){
- // do something
- Log.d("http connect","获取数据");
- Log.d("http connect","re()=="+re());
- Log.d("http connect","re().string()=="+re().string());
- }
- }
- });
发起POST请求
创建RequestBody对象来存放待提交数据;
新建request请求,在build()前调用post()方法,并把body对象传入;
后续操作与get并没有区别
- OkHttpClient client=new OkH().connectTimeout(8000, TimeUnit.MILLISECONDS).readTimeout(8000,TimeUnit.MILLISECONDS).build();
- RequestBody body=new FormBody.Builder().add("account",account).add("password",password).build();
- Request request= new Reque().url(address).post(body).build();
- client.newCall(request).enqueue(new Callback() {
- @Override
- public void onFailure(Call call, IOException e) {
- // do something
- Log.d("http connect","失败");
- Log.d("http connect","e"+e.toString());
- }
- @Override
- public void onResponse(Call call, Response response) throws IOException {
- if ()){
- // do something
- Log.d("http connect","获取数据");
- Log.d("http connect","re()=="+re());
- Log.d("http connect","re().string()=="+re().string());
- }
- }
- });
re(),这个是http协议自带的,200表示连接成功
re().string()要放在子线程,且只执行一次
做一个小小的封装
- public class OkHttpUtils {
- private static OkHttpClient client ;
- private static final String TAG = "OkHttpUtils";
- private static ConcurrentHashMap<String, List<Cookie>> cookiestore = new ConcurrentHashMap<>();
- //单例模式返回一个实例
- public static OkHttpClient getInstance(){
- if (client==null)
- synchronized ){
- if (client==null){
- //添加cookieJar,自动化管理cookie,获得一致的sessions值
- //添加连接超时和读取超时,在网络状况不好的时候可以做出提示.
- client=new OkH().cookieJar(new CookieJar() {
- @Override
- public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
- Log.i(TAG, "saveFromResponse: cookies="+cookies);
- Log.i(TAG, "saveFromResponse: cookieStore="+cookieS());
- cookieS(), cookies);
- }
- @Override
- public List<Cookie> loadForRequest(HttpUrl url) {
- List<Cookie> cookies = cookieS());
- Log.i(TAG, "loadForRequest: cookies="+cookies);
- return cookies != null ? cookies : new ArrayList<Cookie>();
- }
- }).connectTimeout(8000, TimeUnit.MILLISECONDS).readTimeout(8000,TimeUnit.MILLISECONDS).build();
- }
- }
- return client;
- }
- //封装了一个静态方法.用来实现登录,url是你要访问的网址或者接口.在使用时可以通过匿名类,根据实际情况实现一个callback,在callback方法中,分别对成功和失败做处理
- public static void sendHttpLoginRequest( String account, String password, Callback callback) {
- OkHttpClient client=OkH();
- RequestBody body=new FormBody.Builder().add("account",account).add("password",password).build();
- Request request= new Reque().url("url").post(body).build();
- client.newCall(request).enqueue(callback);
- }
- }
下面实际使用下,demo,点击获取按钮,会把获取到的信息设置到TextView中
- public class Main2Activity extends AppCompatActivity implements View.OnClickListener{
- private TextView mContent;
- private Button bInsquire;
- private Button bInfor;
- private Button bModifyPhone;
- private static final String TAG = "Main2Activity";
- //定义常量
- public static final int GET_CONTACT=1;
- public static final int GET_INFOR=2;
- public static final int MODIFY_PHONE=3;
- //定义一个内部Handler,用来获取callback发送的消息,重写内部方法,并处理消息
- private Handler handler=new Handler(){
- @Override
- public void handleMessage(Message msg) {
- if (msg!=null){
- switch ){
- case GET_CONTACT:
- mCon((String);
- case GET_INFOR:
- mCon((String);
- case MODIFY_PHONE:
- mCon((String);
- }
- }else{
- Log.i(TAG, "hanlderNews: msg null");
- }
- }
- });
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- (savedInstanceState);
- setContentView);
- mContent=findViewById);
- bInsquire=findViewById);
- bInfor=findViewById);
- bModifyPhone=findViewById);
- bIn(this);
- bIn(this);
- bModi(this);
- }
- @Override
- public void onClick(View view) {
- switch ()){
- case R.id.b_inquire_contacts:
- Log.i(TAG, "onClick: bInsquire");
- //匿名类,重写了失败和成功的处理,成功的时候,给Handler发送消息,消息内容为获得的相应体Response的内容
- OkH(new Callback() {
- @Override
- public void onFailure(Call call, IOException e) {
- Log.i(TAG, "onFailure: connect failed");
- }
- @Override
- public void onResponse(Call call, Response response) throws IOException {
- if (response!=null){
- String strResponse=re().string();
- Log.d("http connect","re()=="+re());
- Log.d("http connect","re().toString()=="+strResponse);
- Message msg=Me();
- m;
- m;
- mHanlderU(msg);
- }else {
- Log.i(TAG, "onResponse: response failed");
- }
- }
- });
- break;
- case R.id.b_Information:
- case R.id.b_modify_phone:
- }
- }
- }
注意,在新建Handler的时候,AS3.0版本以后会出现告警信息
This Handler class should be static or leaks might occur (anonymous android.os.Handler)
这是由于handler获取到activity的引用,可能由于消息处理的不及时,延时任务会导致activity不能被成功finish(),出现内存泄漏的风险,这里参考
对hanlder进行封装,持有当前活动的弱引用,由于封装的hanlder会处理不同的message,所以在封装Handler的handlerMessage()方法中回调接口方法,在不同的活动里根据情况实现这个接口即可
接口方法
- public interface HandlerNewsInterface {
- void hanlderNews(Message msg);
- }
封装handler
- public class HandlerUtils extends Handler {
- private WeakReference<Activity> mActivityReference;
- private HandlerNewsInterface mHanlderNews;
- HandlerUtils(Activity mActivity,HandlerNewsInterface mHanlderNews) {
- = new WeakReference<>(mActivity);
- ;
- }
- @Override
- public void handleMessage(Message msg) {
- mHanlderNews.hanlderNews(msg);
- (msg);
- }
- }
所以上面的Demo中的Handler就可以这样实现
- private HandlerUtils mHanlderUtils=new HandlerUtils(this, new HandlerNewsInterface() {
- @Override
- public void hanlderNews(Message msg) {
- if (msg!=null){
- switch ){
- case GET_CONTACT:
- mCon((String);
- case GET_INFOR:
- mCon((String);
- case MODIFY_PHONE:
- mCon((String);
- }
- }else{
- Log.i(TAG, "hanlderNews: msg null");
- }
- }
- });
记得要在活动消失前,移除hanlder中添加的消息
- @Override
- protected void onDestroy() {
- mHandlerU(GET_CONTACT);
- mHandlerU(GET_INFOR);
- mHandlerU(MODIFY_PHONE);
- ();
- }
注意,
A.网络请求,需要在配置文件中声明权限
记得在AndroidMani中配置网络权限。
<uses-permission android:name="android.;></uses-permission>
B.对okhttp进行底层封装
对okHttp的更多用法,参考
1.单例模式,获取客户端实例保证
这个唯一的实例,可以在初始化时就设置连接超时,读取超时和写入超时,cookieJar自动管理cookie,可以设置缓存大小和目录
2 对网络连接超时和读取超时的处理
首先,在设置客户端的时候,我们在build()方法中添加了connectTimOut()和ReadTimeOut()方法,添加了超时属性
接下来,在callBack中返回失败的接口中分情况处理
- @Override
- public void onFailure(Call call, IOException e) {
- // do something
- Log.d("http connect","失败");
- //连接失败,一般是没有网络或者服务器问题
- if (e instanceof ConnectException){
- Log.d("http connect","ConnectException e="+e.toString());
- }
- //超时异常,一般是网络不好,可以设置重连以及重连次数
- if (e instanceof SocketTimeoutException){
- Log.d("http connect","SocketTimeoutException e="+e.toString());
- }
- }
3 psot数据的类型
表单数据(键值对)
RequestBody body=new FormBody.Builder().add("pwd",pwd).add("newPwd1",new1).add("newPwd2",new2).build();
json数组
- //设置媒体类型。application/json表示传递的是一个json格式的对象
- MediaType mediaType = MediaTy("application/json");
- //使用JSONObject封装参数
- JSONObject jsonObject = new JSONObject();
- try {
- j("参数名","参数值");
- } catch (JSONException e) {
- e.printStackTrace();
- }
- //创建RequestBody对象,将参数按照指定的MediaType封装
- RequestBody requestBody = Reque(mediaType,j());
更多的媒体类型(MediaType)信息
图片格式 参考
- private void sendMessage(String fileName,File file) {
- RequestBody requestBody = new Mul()
- .setType)
- .addFormDataPart("headPic", fileName,
- Reque(MediaTy("image/jpg"), file))
- .build();
- OkHttpClient client=OkH();
- Request request=new Reque().url).post(requestBody).build();
- client.newCall(request).enqueue(new Callback() {
- @Override
- public void onFailure(Call call, IOException e) {
- Log.i(TAG, "onFailure: failed");
- }
- @Override
- public void onResponse(Call call, Response response) throws IOException {
- if ()){
- String result=re().string();
- Log.i(TAG, "onResponse: result="+result);
- }
- }
- });
关于FileName和File的获取
需要知道路径信息imagePath;
- String fileName=imagePa(imagePath.lastIndexOf("/")+1);
- File file=new File(imagePath);
表单数据提交能完成大部分的网络请求,毕竟一般发送少,下载多
如果需要发送大量的数据,或者需要接受不同格式的数据,就需要包装成json数组
4.添加拦截器
squareup公司自己提供了一个okhttp拦截器方便我们观察网络请求中的数据
使用方法
添加依赖 版本号 与okhttp一致
implementation 'com.;
新建一个实例并配置参数
- HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
- logging.setLevel);
setlevel用来设置日志打印的级别,共包括了四个级别:NONE,BASIC,HEADER,BODY
BASEIC:请求/响应行
HEADER:请求/响应行 + 头
BODY:请求/响应航 + 头 + 体
给ok添加拦截器
- client=new OkH()
- .addInterceptor(logging)
- .build();
5 cookie的持久化
移动端和服务端连接的过程中,为了保证安全,
在ok以后,新增了专门的CookieJar类来保存Cookie
- new CookieJar() {
- private HashMap<String, List<Cookie>> cookieStore = new HashMap<>();
- @Override
- public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
- cookieS(), cookies);
- }
- @Override
- public List<Cookie> loadForRequest(HttpUrl url) {
- List<Cookie> cookies = cookieS());
- return cookies != null ? cookies : new ArrayList<Cookie>();
- }
- }
主要原理:
Url的不变的一部分,比如Url.host()作为key,服务器返回的cookie作为value
saveFromResponse()中建立一个Map,并保存
loadForRequest()中根据url.host()来取出保存的cookie