安卓:网络框架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.mzph.cn/news/34205.shtml

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

相关文章

在生产环境中部署Elasticsearch:最佳实践和故障排除技巧———索引与数据上传(二)

前言 「作者主页」&#xff1a;雪碧有白泡泡 「个人网站」&#xff1a;雪碧的个人网站 「推荐专栏」&#xff1a; ★java一站式服务 ★ ★ React从入门到精通★ ★前端炫酷代码分享 ★ ★ 从0到英雄&#xff0c;vue成神之路★ ★ uniapp-从构建到提升★ ★ 从0到英雄&#xff…

MySQL语句总和之MySQL数据库与表结构操作

目录 1、启动MySQL服务 2、进入MySQL数据库 3、退出数据库 4、查看MySQL数据库所有库 5、创建、删除、使用、查看所处库操作 6、创建表 7、查看表结构 8、表结构操作 1&#xff09;修改表名 2&#xff09;自增长操作 3)添加一个address字段放在Phone字段后面 4)添加…

python爬虫3:requests库-案例1

python爬虫3&#xff1a;requests库-案例1 前言 ​ python实现网络爬虫非常简单&#xff0c;只需要掌握一定的基础知识和一定的库使用技巧即可。本系列目标旨在梳理相关知识点&#xff0c;方便以后复习。 申明 ​ 本系列所涉及的代码仅用于个人研究与讨论&#xff0c;并不会对网…

分布式系统监控zabbix安装部署及使用

目录 一.zabbix监控 1.什么是zabbix 2.zabbix功能 3.zabbix的构成 4.zabbix的3种架构 4.1 C/S架构 4.2 分布式架构&#xff1a;zabbix-proxy-client架构 4.3 master-node-client架构 6.zabbix监控模式 二.zabbix部署及图形化页面显示设置(192.168.158.25) 1.zabbix安装…

uniapp 用 hbuilderx下载 uview

uView2.0重磅发布&#xff0c;利剑出鞘&#xff0c;一统江湖 - DCloud 插件市场 1.uniapp官网下载资源 2按下载 3.官网安装文档 要按 这个红色圈错了 然后看他的配置步骤 第四easycom 就可以 不用配了

第二课-一键安装SD-Stable Diffusion 教程

前言 看完这篇文章并跟着操作,就可以在本地开始 SD 绘图了。 理论上来说,这篇课程结束,想要画什么图都可以画了。 启动器介绍 SD 是开源的,可以在 github 上找到。但直接下载源码安装,非常费劲,而且因为国内外差异,就是我这样的秃头程序员也难以应对。 所以,我们改…

SQL SERVER 异地备份到远程共享文件夹异常处理

SQL SERVER 异地备份到远程共享文件夹异常处理 SQL Server 异地备份到远程共享文件夹异常处理 - 灰信网&#xff08;软件开发博客聚合&#xff09; -- 允许配置高级选项 EXEC sp_configure show advanced options, 1 GO -- 重新配置 RECONFIGURE GO -- 启用xp_cmdshell EXEC sp…

闭环控制方法及其应用:优缺点、场景和未来发展

闭环控制是一种基本的控制方法&#xff0c;它通过对系统输出与期望值之间的误差进行反馈&#xff0c;从而调整系统输入&#xff0c;使系统输出更加接近期望值。闭环控制的主要目标是提高系统的稳定性、精确性和鲁棒性。在实际应用中&#xff0c;闭环控制有多种方法&#xff0c;…

HCIP的BGP基础实验

一、实验需求 除R5的5.5.5.0环回外&#xff0c;其他所有的环回均可互相一访问。 二、实验步骤 1.配置ip 2.建立邻居关系 2.1 R1和R2建立直连的EBGP邻居关系 [r1]bgp 1 [r1-bgp]router-id 1.1.1.1 [r1-bgp]peer 12.1.1.2 as-number 2 要建的话双方都要建下面配置R2 [r2]bgp…

Token 失效退出至登录页面

目录 前端设置&#xff1a; 1. 在登录页面&#xff0c;调用登录的接口后&#xff0c;直接获取当前时间并保存在本地&#xff0c;类似保存token。 2. 在路由守卫 获取本机存储的时间戳&#xff0c;加15分钟与当前时间进行对比&#xff0c;如果大于当前时间说明token失效&…

系统架构设计专业技能 · 系统安全分析与设计(四)【加解密、数字信封、信息摘要、数字签名、数字书证、网络安全、信息安全】

系列文章目录 系统架构设计专业技能 网络规划与设计&#xff08;三&#xff09;【系统架构设计师】 系统架构设计专业技能 系统安全分析与设计&#xff08;四&#xff09;【系统架构设计师】 系统架构设计高级技能 软件架构设计&#xff08;一&#xff09;【系统架构设计师…

【移动机器人运动规划】04 ——轨迹生成

文章目录 前言相关代码整理: 介绍Minimum Snap OptimizationDifferential Flatness(微分平坦)Minimum-snapSmooth 1D TrajectorySmooth Multi-Segment TrajectoryOptimization-based Trajectory Generation Convex Optimization&#xff08;凸优化&#xff09;凸函数和凸集凸优…

【C++】开源:CGAL计算几何库配置使用

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍CGAL计算几何库配置使用。 无专精则不能成&#xff0c;无涉猎则不能通。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#xff0c;…

React 组件防止冒泡方法

背景 在使用 antd 组件库开发时&#xff0c;发现点击一个子组件&#xff0c;却触发了父组件的点击事件&#xff0c;比如&#xff0c;我在一个折叠面板里面放入一个下拉框或者对下拉框列表渲染做定制&#xff0c;每个下拉框候选项都有一个子组件… 解决 其实这就是 Javascri…

前端一键升级 package.json里面的依赖包管理

升级需谨慎 前端一键升级 package.json里面的依赖包管理 安装&#xff1a;npm-check-updates npm i npm-check-updates -g缩写 ncu 在项目根目录里面执行 ncu 如图&#xff1a;

C++ 循环

有的时候&#xff0c;可能需要多次执行同一块代码。一般情况下&#xff0c;语句是顺序执行的&#xff1a;函数中的第一个语句先执行&#xff0c;接着是第二个语句&#xff0c;依此类推。 编程语言提供了允许更为复杂的执行路径的多种控制结构。 循环语句允许我们多次执行一个…

3个月快速入门LoRa物联网传感器开发

在这里插入图片描述 快速入门LoRa物联网传感器开发 LoRa作为一种LPWAN(低功耗广域网络)无线通信技术,非常适合物联网传感器和行业应用。要快速掌握LoRa开发,需要系统学习理论知识,并通过实际项目积累经验。 摘要: 先学习LoRa基础知识:原理、网络架构、协议等,大概需要2周时间…

windows环境下打印机无法打印的解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

以http_proxy和ajp_proxy方式整合apache和tomcat(动静分离)

注意&#xff1a;http_proxy和ajp_proxy的稳定性不如mod_jk 一.http_proxy方式 1.下载mod_proxy_html.x86_64 2.在apache下创建http_proxy.conf文件&#xff08;或者直接写到conf/httpd.conf文件最后&#xff09; 3.查看server.xml文件 到tomcat的安装目录下的conf/serve…

SpringMVC的架构有什么优势?——控制器(三)

前言 「作者主页」&#xff1a;雪碧有白泡泡 「个人网站」&#xff1a;雪碧的个人网站 「推荐专栏」&#xff1a; ★java一站式服务 ★ ★ React从入门到精通★ ★前端炫酷代码分享 ★ ★ 从0到英雄&#xff0c;vue成神之路★ ★ uniapp-从构建到提升★ ★ 从0到英雄&#xff…