安卓:网络框架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来对请求进行修改、添加请求头、记录日志等操作。

常用方法: 

  1. Response intercept(Chain chain)拦截并处理请求和响应。该方法接收一个Chain对象作为参数,可以通过该对象获取请求信息并执行下一个拦截器或者发起实际的网络请求。

  2. 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'

运行结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/92586.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用蓝牙外设却不小心把台式机电脑蓝牙关了

起因 今天犯了一个贼SB的错误&#xff0c;起因是蓝牙键盘突然就不能输入了&#xff08;虽然是连接状态&#xff0c;但是按什么键都没有反应&#xff09; 原来我的解决方法就是重启一下电脑&#xff0c;但是那会电脑开了贼多的软件。我就想重启也太麻烦了&#xff0c;既然重启…

Docker 基本管理(一)

目录 一、虚拟化简介 1.1.虚拟化概述 1.2.cpu的时间分片&#xff08;cpu虚拟化&#xff09; 1.3.cpu虚拟化性性能瓶颈 1.4.虚拟化工作原理 1.5 虚拟化类型 1.6 虚拟化功能 ​二、Docker容器概述 2.1 docker是什么&#xff1f; 2.2 使用docker有什么意义&#xff…

支持https访问

文章目录 1. 打开自己的云服务器的 80 和 443 端口2. 安装 nginx3. 安装 snapd4. 安装 certbot5. 生成证书6. 拷贝生成的证书到项目工作目录7. 修改 main.go 程序如下8. 编译程序9. 启动程序10. 使用 https 和端口 8081 访问页面成功11. 下面修改程序&#xff0c;支持 https 和…

读书笔记 |【项目思维与管理】➾ 顺势而动

读书笔记 |【项目思维与管理】➾ 顺势而动 一、企业步入“终结者时代”二、过去成功的经验也许是最可怕的三、做好非重复性的事四、适应客户是出发点五、向知识型企业转变六、速度是决胜条件 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; …

MySQL 函数

mysql 函数语法 create function 函数名&#xff08;参数名 参数类型&#xff0c;。。。&#xff09; returns type —返回值类型 ----returns 有个 s [characteristics…] begin 函数体 ### 函数体中肯定有 return 语句 end 参数列表 指定参数为 IN | out | INOUT 只对存储过程…

【Linux操作系统】举例解释Linux系统编程中文件io常用的函数

在Linux系统编程中&#xff0c;文件IO操作是非常常见和重要的操作之一。通过文件IO操作&#xff0c;我们可以打开、读取、写入和关闭文件&#xff0c;对文件进行定位、复制、删除和重命名等操作。本篇博客将介绍一些常用的文件IO操作函数。 文章目录 1. open()1.1 原型、参数及…

Android:自定义沿着曲线轨迹移动

前言 前几天&#xff0c;后台有老铁留言&#xff0c;说有个需求&#xff0c;画两条曲线&#xff0c;中间是一个小球&#xff0c;沿着两条线中间的轨迹从左往右移动&#xff0c;让提供个思路&#xff0c;做为一个极度宠粉的博主&#xff0c;思路不仅要提供&#xff0c;实现方案也…

八大排序超详解(动图+源码)

&#x1f493;博主个人主页:不是笨小孩&#x1f440; ⏩专栏分类:数据结构与算法&#x1f440; 刷题专栏&#x1f440; C语言&#x1f440; &#x1f69a;代码仓库:笨小孩的代码库&#x1f440; ⏩社区&#xff1a;不是笨小孩&#x1f440; &#x1f339;欢迎大家三连关注&…

【Linux】IO多路转接——select接口

目录 I/O多路转接之select select初识 select函数 socket就绪条件 select基本工作流程 select服务器 select的优点 select的缺点 select的适用场景 I/O多路转接之select select初识 select是系统提供的一个多路转接接口。 select系统调用可以让我们的程序同时监视多…

拦截器和过滤器的区别

&#x1f600;前言 本篇博文是关于拦截器VS 过滤器的分享&#xff0c;希望你能够喜欢&#x1f60a; &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章可以帮助到大家&#xff0c;您的满意是我…

【机器学习4】构建良好的训练数据集——数据预处理(一)处理缺失值及异常值

数据预处理 &#x1f4ab;数据预处理的重要性&#x1f4ab;处理缺失值⭐️识别表格中的数据⭐️计算每列缺失值的数量⭐️删除含有缺失值的样本或特征⭐️填充缺失值 &#x1f4ab;处理异常值⭐️异常值的鉴别⭐️异常值的处理 &#x1f4ab;将数据集划分为训练数据集和测试数据…

Jmeter-压力测试工具

文章目录 Jmeter快速入门1.1.下载1.2.解压1.3.运行 2.快速入门2.1.设置中文语言2.2.基本用法 Jmeter快速入门 1s内发送大量请求&#xff0c;模拟高QPS&#xff0c;用以测试网站能承受的压力有多大 Jmeter依赖于JDK&#xff0c;所以必须确保当前计算机上已经安装了JDK&#xff0…

使用ip2region获取客户端地区

目录 从gitee拉取ip2region.xdb资源文件 写测试类 注意要写对资源路径 本地测试结果 ​编辑 远端测试结果 从gitee拉取ip2region.xdb资源文件 git clone https://gitee.com/lionsoul/ip2region.git 将xdb放入resources资源文件夹 引入依赖 <dependency><groupId&…

Vue响应式数据的原理

在 vue2 的响应式中&#xff0c;存在着添加属性、删除属性、以及通过下标修改数组&#xff0c;但页面不会自动更新的问题。而这些问题在 vue3 中都得以解决。 vue3 采用了 proxy 代理&#xff0c;用于拦截对象中任意属性的变化&#xff0c;包括&#xff1a;属性的读写、属性的…

Pycharm社区版连接WSL2中的Mysql8.*

当前时间2023.08.13&#xff0c;Windows11中默认的WSL版本已经是2了&#xff0c;在WSL2中默认的Ubuntu版本已经是22.04&#xff0c;而Ubuntu22.04中默认的Mysql版本已经是8.*。 Wsl 2 中安装mysql WSL2中安装Mysql的方法参考自微软官方文档【开始使用适用于 Linux 的 Windows …

《论文阅读12》RandLA-Net: Efficient Semantic Segmentation of Large-Scale Point Clouds

一、论文 研究领域&#xff1a;全监督3D语义分割&#xff08;室内&#xff0c;室外RGB&#xff0c;kitti&#xff09;论文&#xff1a;RandLA-Net: Efficient Semantic Segmentation of Large-Scale Point Clouds CVPR 2020 牛津大学、中山大学、国防科技大学 论文链接论文gi…

C++储备

一、类的 三大特性 封装&#xff0c;继承&#xff0c;多态 二、虚函数 为啥要用到虚函数 C虚函数详解_Whitesad_的博客-CSDN博客 三、函数重载 四、封装的保护权限 1.public 成员类内&#xff0c;内外都可以访问 2.protected 成员&#xff0c;类内可以访问&#xff0c…

两只小企鹅(Python实现)

目录 1 和她浪漫的昨天 2 未来的旖旎风景 3 Python完整代码 1 和她浪漫的昨天 是的,春天需要你。经常会有一颗星等着你抬头去看&#xff1b; 和她一起吹晚风吗﹖在春天的柏油路夏日的桥头秋季的公园寒冬的阳台&#xff1b; 这世界不停开花&#xff0c;我想放进你心里一朵&am…

【软件工程】软件测试

软件测试的对象 软件程序文档 测试对象&#xff1a;各个阶段产生的源程序和文档。 软件测试的目的 基于不同的立场&#xff0c;对软件测试的目的存在着两种完全对立的观点。 &#xff08;1&#xff09;一种观点是通过测试暴露出软件中所包含的故障和缺陷(从用户的角度)&#xf…

语聚AI公测发布,大语言模型时代下新的生产力工具

语聚AI 公测发布 距离语聚AI内测上线已经过去近1个月。 这期间&#xff0c;我们共邀请了近百位资深用户与行业专家加入语聚AI产品体验。通过大家的热情参与积极反馈&#xff0c;我们不断优化并完善了语聚AI的功能与使用体验。 经过研发团队不懈的努力&#xff0c;今天语聚AI终…