安卓:网络框架okhttp
目录
一、okhttp介绍
1. OkHttpClient类:
常用方法:
2. Request类:
常用方法:
3. Response类:
常用方法:
4. Call类:
常用方法:
5. Interceptor接口:
常用方法:
6. FormBody类:
常用方法:
7. MultipartBody类:
常用方法:
8. WebSocket类:
常用方法:
二、okhttp使用方法
1、添加依赖:
2、创建OkHttpClient对象:
3、创建Request对象:
4、发送同步请求:
5、发送异步请求
三、okhttp例子
省的json数据格式:
市的json数据格式:
县的json数据格式:
MainActivity:
Utility :
HttpTool :
Province :
City:
County :
activity_main:
litepal.xml:
AndroidManifest:
依赖:
运行结果:
一、okhttp介绍
OkHttp是一个开源的HTTP客户端库,常用于Android应用程序中进行网络请求。以下是OkHttp的一些常用类和方法:
1. OkHttpClient类:
OkHttpClient是OkHttp库的核心类,用于创建和配置HTTP请求的客户端。它提供了各种设置和配置选项,如连接超时、读写超时、拦截器等。
常用方法:
-
newBuilder()
:创建一个新的OkHttpClient.Builder实例,用于配置和构建OkHttpClient对象。 -
addInterceptor(Interceptor interceptor)
:添加一个Interceptor拦截器,用于在发送请求和接收响应时对其进行处理。例如,可以使用拦截器对请求进行身份验证、日志记录或数据转换等操作。 -
connectTimeout(long timeout, TimeUnit unit)
:设置连接超时时间。可以指定一个时间值和时间单位来限制与服务器建立连接的最长时间。 -
readTimeout(long timeout, TimeUnit unit)
:设置读取超时时间。可以指定一个时间值和时间单位来限制从服务器读取数据的最长时间。 -
writeTimeout(long timeout, TimeUnit unit)
:设置写入超时时间。可以指定一个时间值和时间单位来限制向服务器写入数据的最长时间。 -
retryOnConnectionFailure(boolean retry)
:设置是否重试连接失败的请求。默认情况下,OkHttpClient会自动重试请求,但可以通过该方法禁用重试。 -
followRedirects(boolean followRedirects)
:设置是否自动遵循重定向。默认情况下,OkHttpClient会自动遵循重定向,但可以通过该方法禁用自动重定向。 -
cache(Cache cache)
:设置缓存。可以传入一个Cache对象,用于缓存网络请求的响应数据。 -
dispatcher(Dispatcher dispatcher)
:设置Dispatcher调度器。可以传入一个自定义的Dispatcher对象,用于控制并发请求数量和线程池的行为。 -
proxy(Proxy proxy)
:设置代理服务器。可以指定一个Proxy对象,用于将请求通过代理发送到目标服务器。
2. Request类:
Request类用于构建HTTP请求。可以通过Request.Builder来创建一个Request对象,并设置URL、请求方法(GET、POST等)、请求头、请求体等。
常用方法:
-
newBuilder()
:创建一个新的Request.Builder实例,用于构建和配置Request对象。 -
url(String url)
:设置请求的URL地址。可以传入一个字符串类型的URL地址作为参数。 -
method(String method, RequestBody body)
:设置请求的HTTP方法和请求体。可以指定请求的HTTP方法(如GET、POST、PUT等)和请求体RequestBody对象。 -
header(String name, String value)
:添加请求头。可以通过该方法添加自定义的请求头参数,需要提供参数名和参数值。 -
headers(Headers headers)
:设置请求头集合。可以通过该方法一次性设置多个请求头,需要传入Headers对象。 -
cacheControl(CacheControl cacheControl)
:设置缓存控制策略。可以传入一个CacheControl对象,用于控制请求的缓存行为。 -
tag(Object tag)
:设置请求的标签。可以传入一个Object类型的标签,用于在后续操作中标识和识别该请求。 -
build()
:构建Request对象。在配置完成后,使用该方法来构建最终的Request对象。
3. Response类:
Response类表示HTTP响应。当发送HTTP请求后,可以通过Response对象获取服务器返回的响应信息,包括状态码、响应头、响应体等。
常用方法:
-
code()
:获取HTTP响应的状态码。返回一个整型值,表示HTTP响应的状态码。 -
message()
:获取HTTP响应的状态消息。返回一个字符串,表示HTTP响应的状态消息。 -
body()
:获取HTTP响应的响应体。返回一个ResponseBody对象,用于获取和处理响应的具体数据。 -
headers()
:获取HTTP响应的响应头。返回一个Headers对象,用于获取和处理响应的头部信息。 -
isSuccessful()
:判断HTTP响应是否成功。返回一个布尔值,表示HTTP响应是否成功(状态码在200-299之间)。 -
cacheResponse()
:获取缓存的HTTP响应。如果请求使用了缓存,并且有对应的缓存响应,则返回一个Response对象,否则返回null。 -
networkResponse()
:获取网络的HTTP响应。如果请求是通过网络发送的,并且有对应的网络响应,则返回一个Response对象,否则返回null。 -
priorResponse()
:获取前一个HTTP响应。如果请求有关联的前一个HTTP响应,则返回一个Response对象,否则返回null。 -
request()
:获取与该HTTP响应相关联的请求。返回一个Request对象,表示与该响应相关联的请求。
4. Call类:
Call类表示一个异步的HTTP请求任务。通过OkHttpClient的newCall方法创建一个Call对象,然后可以使用enqueue方法发送异步请求,并通过回调函数处理响应结果。
常用方法:
-
execute()
:同步执行HTTP请求并返回Response对象。该方法会阻塞当前线程,直到获取到完整的响应结果。 -
enqueue(Callback callback)
:异步执行HTTP请求并通过回调函数接收结果。该方法将请求放入请求队列中,并在后台线程执行,执行完成后通过Callback接口回调返回结果。 -
cancel()
:取消HTTP请求。如果HTTP请求尚未执行完毕,可以调用该方法取消正在进行的请求。 -
isExecuted()
:判断HTTP请求是否已经执行。返回一个布尔值,表示HTTP请求是否已经执行。 -
isCanceled()
:判断HTTP请求是否已经取消。返回一个布尔值,表示HTTP请求是否已经取消。 -
timeout()
:获取超时设置。返回一个Timeout对象,用于获取和设置连接、读取和写入的超时时间。 -
request()
:获取与该Call相关联的请求。返回一个Request对象,表示与该Call相关联的HTTP请求。 -
clone()
:创建Call对象的副本。返回一个新的Call对象,与原始的Call对象共享相同的配置和请求信息。
5. Interceptor接口:
Interceptor接口可以用于对HTTP请求和响应进行拦截和处理。可以实现自定义的Interceptor来对请求进行修改、添加请求头、记录日志等操作。
常用方法:
-
Response intercept(Chain chain)
:拦截并处理请求和响应。该方法接收一个Chain对象作为参数,可以通过该对象获取请求信息并执行下一个拦截器或者发起实际的网络请求。 -
interface Chain
:表示拦截器链中的一环,用于传递请求和响应以及控制拦截器的执行流程。Chain接口拥有以下方法:
Connection connection()
:获取当前拦截器链的连接对象。Request request()
:获取当前拦截器链的请求对象。Response proceed(Request request)
:执行下一个拦截器,并返回最终的响应结果。
6. FormBody类:
FormBody类是OkHttp库中用于构建表单形式的请求体的类。它提供了一些方法来添加表单字段和值,并生成最终的请求体数据。
常用方法:
-
add(String name, String value)
:添加表单字段和值。可以多次调用该方法,以添加多个表单字段和对应的值。 -
encodedName(int index)
:获取编码后的表单字段名。传入索引值,返回对应位置的编码后的表单字段名。 -
encodedValue(int index)
:获取编码后的表单字段值。传入索引值,返回对应位置的编码后的表单字段值。 -
name(int index)
:获取未编码的表单字段名。传入索引值,返回对应位置的未编码的表单字段名。 -
value(int index)
:获取未编码的表单字段值。传入索引值,返回对应位置的未编码的表单字段值。 -
size()
:获取表单字段的数量。返回一个整型值,表示表单字段的数量。 -
contentType()
:获取请求体的媒体类型。返回一个MediaType对象,表示请求体的媒体类型,默认为"application/x-www-form-urlencoded"。 -
contentLength()
:获取请求体的长度。返回一个长整型值,表示请求体的字节长度。 -
toString()
:将FormBody转换为字符串。返回一个字符串,表示FormBody的内容。
7. MultipartBody类:
MultipartBody类是OkHttp库中用于构建多部分(multipart)请求体的类。它允许在单个请求中包含多个不同类型的数据,如文本、文件等。
常用方法:
-
create(MediaType type, RequestBody... parts)
:创建一个MultipartBody对象。需要传入媒体类型和多个RequestBody实例。 -
type()
:获取请求体的媒体类型。返回一个MediaType对象,表示请求体的媒体类型,默认为"multipart/form-data"。 -
boundary()
:获取边界字符串。返回一个字符串,表示请求体的边界字符串。 -
contentType()
:获取请求体的完整媒体类型。返回一个字符串,表示请求体的完整媒体类型,包括媒体类型和边界字符串。 -
parts()
:获取请求体的各个部分。返回一个List<RequestBody>,表示请求体中的所有部分。 -
writeTo(BufferedSink sink)
:将MultipartBody写入到缓冲区。需要传入一个BufferedSink对象,用于写入请求体的数据。 -
contentLength()
:获取请求体的长度。返回一个长整型值,表示请求体的字节长度。 -
addPart(Headers headers, RequestBody body)
:添加一个部分到请求体中。可以传入自定义的请求头Headers对象和对应的RequestBody实例。 -
addFormDataPart(String name, @Nullable String filename, RequestBody body)
:添加一个表单数据部分到请求体中。需要传入字段名name、可选的文件名filename和RequestBody实例。 -
addFormDataPart(String name, @Nullable String filename, MediaType contentType, ByteString content)
:添加一个表单数据部分到请求体中。需要传入字段名name、可选的文件名filename、媒体类型contentType和内容content。
8. WebSocket类:
WebSocket类用于进行WebSocket通信。可以建立与服务器的WebSocket连接,并进行双向通信。
常用方法:
-
request()
:获取与该WebSocket相关联的请求。返回一个Request对象,表示与该WebSocket相关联的HTTP请求。 -
queueSize()
:获取待发送的消息队列大小。返回一个整型值,表示待发送的消息队列中的消息数量。 -
send(String text)
:发送文本消息。可以传入一个字符串类型的消息内容,将其作为文本消息发送给服务器。 -
send(ByteString bytes)
:发送二进制消息。可以传入一个ByteString对象,将其作为二进制消息发送给服务器。 -
close(int code, String reason)
:关闭WebSocket连接。可以传入一个整型的关闭码(如1000表示正常关闭)、一个字符串的关闭原因,以便向服务器发送关闭帧,并关闭WebSocket连接。 -
cancel()
:取消WebSocket连接。如果WebSocket连接尚未关闭,可以调用该方法取消连接。 -
send(Request request, WebSocketListener listener)
:发送指定请求的WebSocket消息。可以传入一个Request对象和一个WebSocketListener对象,将该请求发送给服务器,并通过WebSocketListener监听回调处理结果。 -
addListener(WebSocketListener listener)
:添加WebSocket事件监听器。可以传入一个WebSocketListener对象,用于监听WebSocket连接状态、收到消息等事件。 -
removeListener(WebSocketListener listener)
:移除WebSocket事件监听器。可以传入一个WebSocketListener对象,将其从WebSocket的监听器列表中移除。
二、okhttp使用方法
1、添加依赖:
在项目的build.gradle文件中添加OkHttp的依赖项。
implementation 'com.squareup.okhttp3:okhttp:3.12.0'
2、创建OkHttpClient对象:
通过new OkHttpClient()
创建一个OkHttpClient实例,用于发送HTTP请求。
OkHttpClient client = new OkHttpClient();
3、创建Request对象:
使用Request.Builder
构建一个请求对象,并指定URL地址、请求头、请求体等相关信息。
Request request = new Request.Builder().url("https://example.com/api").header("Content-Type", "application/json").post(RequestBody.create(MediaType.parse("application/json"), jsonBody)).build();
4、发送同步请求:
使用client.newCall(request).execute()
发送同步请求,并获得Response对象。
try (Response response = client.newCall(request).execute()) {// 处理响应结果if (response.isSuccessful()) {String responseBody = response.body().string();// ...} else {// 请求失败处理}
} catch (IOException e) {// IO异常处理
}
5、发送异步请求
使用client.newCall(request).enqueue(Callback)
发送异步请求,并通过Callback回调处理响应结果。
client.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {// 请求失败处理}@Overridepublic void onResponse(Call call, Response response) throws IOException {// 处理响应结果if (response.isSuccessful()) {String responseBody = response.body().string();// ...} else {// 请求失败处理}}
});
在以上示例中,我们首先创建了一个OkHttpClient对象,并使用Request.Builder构建了一个请求对象。然后,可以选择性地发送同步或异步请求。对于同步请求,直接调用execute()
方法并处理响应结果;对于异步请求,使用enqueue(Callback)
方法并通过Callback回调处理响应结果。
当处理完请求后,需要注意关闭Response对象的资源,以避免内存泄漏。
三、okhttp例子
下面例子是郭霖大神的第一行代码中的酷欧天气网络请求地名的代码。
省的json数据格式:
http://guolin.tech/api/china
市的json数据格式:
http://guolin.tech/api/china/16
县的json数据格式:
MainActivity:
package com.example.okhttpdemo;import androidx.appcompat.app.AppCompatActivity;import android.app.ProgressDialog;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;import com.example.okhttpdemo.Bean.City;
import com.example.okhttpdemo.Bean.County;
import com.example.okhttpdemo.Bean.Province;import org.litepal.LitePal;import java.io.IOException;
import java.util.ArrayList;
import java.util.List;import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;
import okhttp3.internal.Util;public class MainActivity extends AppCompatActivity {public static final int CURRENT_PAGE_PROVINCE = 0;public static final int CURRENT_PAGE_CITY = 1;public static final int CURRENT_PAGE_COUNTY = 2;private List<Province> mProvinces;private List<City> mCities;private List<County> mCounties;private TextView titleTV;private Button backBtn;private ListView mListView;private List<String> mListData = new ArrayList<>();private ArrayAdapter<String> mAdapter;private ProgressDialog progressDialog;private int currentPage;private Province mCurrentProvince;private City mCurrentCity;private County mCurrentCounty;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);LitePal.initialize(this);initView();}private void initView() {mListView = findViewById(R.id.list_view);backBtn = findViewById(R.id.back_button);titleTV= findViewById(R.id.title_text);backBtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {if (currentPage==CURRENT_PAGE_COUNTY){queryCities();}else if(currentPage == CURRENT_PAGE_CITY){queryProvinces();}}});mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {switch (currentPage){case CURRENT_PAGE_PROVINCE:mCurrentProvince = mProvinces.get(position);queryCities();break;case CURRENT_PAGE_CITY:mCurrentCity = mCities.get(position);queryCounty();break;case CURRENT_PAGE_COUNTY:mCurrentCounty = mCounties.get(position);Toast.makeText(MainActivity.this,"点击了"+mCurrentProvince.getProvinceName()+mCurrentCity.getCityName()+mCurrentCounty.getCountyName(),Toast.LENGTH_LONG).show();break;}}});mAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, mListData);queryProvinces();mListView.setAdapter(mAdapter);}private void queryProvinces(){titleTV.setText("中国");backBtn.setVisibility(View.GONE);// 从数据库中找mProvinces = LitePal.findAll(Province.class);if (mProvinces.size()>0){mListData.clear();for (Province province:mProvinces){mListData.add(province.getProvinceName());}mAdapter.notifyDataSetChanged();currentPage = CURRENT_PAGE_PROVINCE;}else {String url = "http://guolin.tech/api/china";queryFromServer(url,CURRENT_PAGE_PROVINCE);}}private void queryFromServer(String url, int type) {showProgressDialog();HttpTool.sendOkhttpRequest(url, new Callback() {@Overridepublic void onFailure(Call call, IOException e) {runOnUiThread(new Runnable() {@Overridepublic void run() {closeProgressDialog();Toast.makeText(MainActivity.this,"加载失败!!!",Toast.LENGTH_LONG).show();}});}@Overridepublic void onResponse(Call call, Response response) throws IOException {boolean result = false;switch (type){case CURRENT_PAGE_PROVINCE:result = Utility.handleProvinceResponse(response.body().string());break;case CURRENT_PAGE_CITY:result = Utility.handleCitiesResponse(response.body().string(),mCurrentProvince.getId());break;case CURRENT_PAGE_COUNTY:result = Utility.handleCountyResponse(response.body().string(),mCurrentCity.getId());break;}if (result){runOnUiThread(new Runnable() {@Overridepublic void run() {closeProgressDialog();switch (type){case CURRENT_PAGE_PROVINCE:queryProvinces();break;case CURRENT_PAGE_CITY:queryCities();break;case CURRENT_PAGE_COUNTY:queryCounty();break;}}});}}});}private void queryCounty() {titleTV.setText(mCurrentCity.getCityName());backBtn.setVisibility(View.VISIBLE);// 从数据库中找mCounties = LitePal.where("cityid=?",String.valueOf(mCurrentCity.getId())).find(County.class);if (mCounties.size()!=0){mListData.clear();for (County county:mCounties){mListData.add(county.getCountyName());}mAdapter.notifyDataSetChanged();currentPage = CURRENT_PAGE_COUNTY;}else {int provinceCode = mCurrentProvince.getProvinceCode();int citiCode = mCurrentCity.getCityCode();String url = "http://guolin.tech/api/china/" + provinceCode+"/"+citiCode;queryFromServer(url,CURRENT_PAGE_COUNTY);}}private void queryCities() {titleTV.setText(mCurrentProvince.getProvinceName());backBtn.setVisibility(View.VISIBLE);// 从数据库中找mCities = LitePal.where("provinceid=?",String.valueOf(mCurrentProvince.getId())).find(City.class);if (mCities.size()!=0){mListData.clear();for (City city:mCities){mListData.add(city.getCityName());}mAdapter.notifyDataSetChanged();currentPage = CURRENT_PAGE_CITY;}else {int provinceCode = mCurrentProvince.getProvinceCode();String url = "http://guolin.tech/api/china/" + provinceCode;queryFromServer(url,CURRENT_PAGE_CITY);}}/*** 显示进度对话框*/private void showProgressDialog() {if (progressDialog == null) {progressDialog = new ProgressDialog(this);progressDialog.setMessage("正在加载...");progressDialog.setCanceledOnTouchOutside(false);}progressDialog.show();}/*** 关闭进度对话框*/private void closeProgressDialog() {if (progressDialog != null) {progressDialog.dismiss();}}
}
Utility :
package com.example.okhttpdemo;import android.text.TextUtils;import com.example.okhttpdemo.Bean.City;
import com.example.okhttpdemo.Bean.County;
import com.example.okhttpdemo.Bean.Province;
import com.google.gson.Gson;import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;public class Utility {
/*** 解析和处理服务器返回的省级的数据*/
public static boolean handleProvinceResponse(String response) {if (!TextUtils.isEmpty(response)) {try {JSONArray allProvinces = new JSONArray(response);for (int i = 0; i < allProvinces.length(); i++) {JSONObject provinceObject = allProvinces.getJSONObject(i);Province province = new Province();province.setProvinceName(provinceObject.getString("name"));province.setProvinceCode(provinceObject.getInt("id"));province.save();}return true;} catch (JSONException e) {e.printStackTrace();}}return false;
}/*** 解析和处理服务器返回的市级的数据*/public static boolean handleCitiesResponse(String response,int provinceId){if (!TextUtils.isEmpty(response)){try {JSONArray allCities = new JSONArray(response);for (int i = 0; i < allCities.length() ; i++) {JSONObject cityObject = allCities.getJSONObject(i);City city = new City();city.setCityName(cityObject.getString("name"));city.setCityCode(cityObject.getInt("id"));city.setProvinceId(provinceId);city.save();}return true;} catch (JSONException e) {e.printStackTrace();}}return false;}/*** 解析和处理服务器返回的县级的数据*/public static boolean handleCountyResponse(String response,int cityId){if (!TextUtils.isEmpty(response)){try {JSONArray allCounties = new JSONArray(response);for (int i = 0; i < allCounties.length() ; i++) {JSONObject countryObject = allCounties.getJSONObject(i);County country = new County();country.setCountyName(countryObject.getString("name"));country.setWeatherId(countryObject.getString("weather_id"));country.setCityId(cityId);country .save();}return true;} catch (JSONException e) {e.printStackTrace();}}return false;}}
HttpTool :
package com.example.okhttpdemo;import okhttp3.OkHttpClient;
import okhttp3.Request;public class HttpTool {/**** @param address 接口地址URL* @param callback*/public static void sendOkhttpRequest(String address,okhttp3.Callback callback){// 1、创建OkHttpClient对象OkHttpClient client = new OkHttpClient();// 2、创建Request对象Request request = new Request.Builder().url(address).build();// 3、发送异步请求client.newCall(request).enqueue(callback);}
}
Province :
package com.example.okhttpdemo.Bean;import org.litepal.crud.LitePalSupport;public class Province extends LitePalSupport {private int id;private String provinceName;private int provinceCode;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getProvinceName() {return provinceName;}public void setProvinceName(String provinceName) {this.provinceName = provinceName;}public int getProvinceCode() {return provinceCode;}public void setProvinceCode(int provinceCode) {this.provinceCode = provinceCode;}
}
City:
package com.example.okhttpdemo.Bean;import org.litepal.crud.LitePalSupport;public class City extends LitePalSupport {private int id;private String cityName;private int cityCode;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getCityName() {return cityName;}public void setCityName(String cityName) {this.cityName = cityName;}public int getCityCode() {return cityCode;}public void setCityCode(int cityCode) {this.cityCode = cityCode;}public int getProvinceId() {return provinceId;}public void setProvinceId(int provinceId) {this.provinceId = provinceId;}private int provinceId;}
County :
package com.example.okhttpdemo.Bean;import org.litepal.crud.LitePalSupport;public class County extends LitePalSupport {private int id;private String countyName;private String weatherId;private int cityId;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getCountyName() {return countyName;}public void setCountyName(String countyName) {this.countyName = countyName;}public String getWeatherId() {return weatherId;}public void setWeatherId(String weatherId) {this.weatherId = weatherId;}public int getCityId() {return cityId;}public void setCityId(int cityId) {this.cityId = cityId;}
}
activity_main:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:background="#7283DD"android:layout_width="match_parent"android:layout_height="match_parent"><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="?attr/actionBarSize"android:background="@color/teal_200"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/title_text"android:layout_centerInParent="true"android:textColor="#fff"android:textSize="20sp"/><Buttonandroid:id="@+id/back_button"android:layout_width="25dp"android:layout_height="25dp"android:layout_marginLeft="10dp"android:layout_alignParentLeft="true"android:layout_centerVertical="true"android:background="@drawable/back"/></RelativeLayout><ListViewandroid:id="@+id/list_view"android:layout_width="match_parent"android:layout_height="match_parent"/></LinearLayout>
litepal.xml:
<?xml version="1.0" encoding="utf-8"?>
<litepal><dbname value = "okhttpdemo"/><version value = "1"/><list><mapping class = "com.example.okhttpdemo.Bean.Province"/><mapping class = "com.example.okhttpdemo.Bean.City"/><mapping class = "com.example.okhttpdemo.Bean.County"/></list>
</litepal>
AndroidManifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.okhttpdemo">
<uses-permission android:name="android.permission.INTERNET"/><applicationandroid:networkSecurityConfig="@xml/network_security_config"android:name = "org.litepal.LitePalApplication"android:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.AppCompat.NoActionBar"><activityandroid:name=".MainActivity"android:exported="true"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity></application></manifest>
依赖:
implementation("com.squareup.okhttp3:okhttp:3.4.1")implementation 'org.litepal.guolindev:core:3.2.3'implementation 'com.google.code.gson:gson:2.7'
运行结果:
相关文章:

安卓:网络框架okhttp
目录 一、okhttp介绍 1. OkHttpClient类: 常用方法: 2. Request类: 常用方法: 3. Response类: 常用方法: 4. Call类: 常用方法: 5. Interceptor接口: 常用方法&…...

Python爬虫 爬取图片
在我们日常上网浏览网页的时候,经常会看到一些好看的图片,我们就希望把这些图片保存下载,或者用户用来做桌面壁纸,或者用来做设计的素材。 我们最常规的做法就是通过鼠标右键,选择另存为。但有些图片鼠标右键的时候并没…...
【云原生】Pod详讲
目录 一、Pod基础概念1.1//在Kubrenetes集群中Pod有如下两种使用方式:1.2pause容器使得Pod中的所有容器可以共享两种资源:网络和存储。1.3kubernetes中的pause容器主要为每个容器提供以下功能:1.4Kubernetes设计这样的Pod概念和特殊组成结构有…...
先进先出的队
文章目录 队列特点队列实现 队列特点 先进先出,后进后出 队列实现 queue.c#define _CRT_SECURE_NO_WARNINGS 1 #include"Queue.h" //初始化 void QueInit(Queue* pq) {assert(pq);pq->head NULL;pq->tail NULL;pq->size 0; } //入队&#…...

怎样学会单片机
0、学单片机首先要明白,一个单片机啥也干不了,学单片机的目的是学习怎么用单片机驱动外部设备,比如数码管,电机,液晶屏等,这个需要外围电路的配合,所以学习单片机在这个层面上可以等同为学习单片…...
数据结构笔记--常见二叉树分类及判断实现
目录 1--搜索二叉树 2--完全二叉树 3--平衡二叉树 4--满二叉树 1--搜索二叉树 搜索二叉树的性质:左子树的节点值都比根节点小,右子树的节点值都比根节点大; 如何判断一颗二叉树是搜索二叉树? 主要思路: 递归自底向…...

docker小白第二天
centos上安装docker docker官网,docker官网,找到下图中的doc文档。 进入如下页面 选中manuals,安装docker引擎。 最终centos下的docker安装文档链接:安装文档链接. 具体安装步骤: 1、打开Centos,输入命…...

【变形金刚03】使用 Pytorch 开始构建transformer
一、说明 在本教程中,我们将使用 PyTorch 从头开始构建一个基本的转换器模型。Vaswani等人在论文“注意力是你所需要的一切”中引入的Transformer模型是一种深度学习架构,专为序列到序列任务而设计,例如机器翻译和文本摘要。它基于自我注意机…...

「Web3大厂」价值70亿美元的核心竞争力
经过近 5 年的研发和酝酿,Linea 团队在 7 月的巴黎 ETHCC 大会期间宣布了主网 Alpha 的上线,引起了社区的广泛关注。截止 8 月 4 日,据 Dune 数据信息显示,其主网在一周内就涌入了 100 多个生态项目,跨入了超 2 万枚 E…...
前端发送请求和后端springboot接受参数
0.xhr、 ajax、axios、promise和async/await 和http基本方法 xhr、 ajax、axios、promise和async/await都是异步编程和网络请求相关的概念和技术! xhr:XMLHttpRequest是浏览器提供的js对象(API),用于请求服务器资源。…...
程序一直在阿里云服务器运行
保持阿里云服务器开机程序保持运行. 1.下载Screen CentOS 系列系统: yum install screen Ubuntu 系列系统: sudo apt-get install screen 2、运行screen,创建一个screen screen -S name:name是标记进程, 给进程备注…...
Linux 文件与目录管理
nvLinux 文件与目录管理 我们知道 Linux 的目录结构为树状结构,最顶级的目录为根目录 /。 其他目录通过挂载可以将它们添加到树中,通过解除挂载可以移除它们。 在开始本教程前我们需要先知道什么是绝对路径与相对路径。 绝对路径: 路径的写…...

【CSS】CSS 布局——弹性盒子
Flexbox 是一种强大的布局系统,旨在更轻松地使用 CSS 创建复杂的布局。 它特别适用于构建响应式设计和在容器内分配空间,即使项目的大小是未知的或动态的。Flexbox 通常用于将元素排列成一行或一列,并提供一组属性来控制 flex 容器内的项目行…...
“华为杯”研究生数学建模竞赛2018年-【华为杯】B题:光传送网建模与价值评估(附优秀论文及matlab代码实现)
目录 摘要: 1.问题重述 1.1 问题背景 1.2 问题提出 2.问题假设 3.符号说明...

群晖 nas 自建 ntfy 通知服务(梦寐以求)
目录 一、什么是 ntfy ? 二、在群晖nas上部署ntfy 1. 在Docker中安装ntfy 2. 设置ntfy工作文件夹 3. 启动部署在 docker 中的 ntfy(binwiederhier/ntfy) 三、启动配置好后,如何使用ntfy 1. 添加订阅主题( Subscribe to topic…...
Java基础练习九(方法)
求和 设计一个方法,用于计算整数的和 public class Work1101 {public static void main(String[] args) {// 设计一个方法,用于计算整数的和System.out.println(sum(7, 6));}public static int sum(int a, int b) {return a b;} }阶乘 编写一个方法&…...

Python-OpenCV中的图像处理-图像轮廓
Python-OpenCV中的图像处理-图像轮廓 轮廓什么是轮廓查找轮廓绘制轮廓轮廓特征图像的矩轮廓面积轮廓周长(弧长)轮廓近似凸包凸性检测边界矩形直边界矩形旋转边界矩形(最小面积矩形)最小外接圆最小外接三角椭圆拟合直线拟合 轮廓的…...
@Cacheable缓存相关使用总结
本篇文章主要讲解Spring当中Cacheable缓存相关使用 在实际项目开发中,有些数据是变更频率比较低,但是查询频率比较高的,此时为了提升系统性能,可以使用缓存的机制实现,避免每次从数据库获取 第一步:使用E…...

c++ static
static 成员 声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用 static修饰的成员函数,称之为静态成员函数。静态成员变量一定要在类外进行初始化。 看看下面代码体会一下: //其他类 class …...

【数据结构】——栈、队列的相关习题
目录 题型一(栈与队列的基本概念)题型二(栈与队列的综合)题型三(循环队列的判空与判满)题型四(循环链表表示队列)题型五(循环队列的存储)题型六(循…...
Python|GIF 解析与构建(5):手搓截屏和帧率控制
目录 Python|GIF 解析与构建(5):手搓截屏和帧率控制 一、引言 二、技术实现:手搓截屏模块 2.1 核心原理 2.2 代码解析:ScreenshotData类 2.2.1 截图函数:capture_screen 三、技术实现&…...
Cesium1.95中高性能加载1500个点
一、基本方式: 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...