安卓:网络框架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() {
    @Override
    public void onFailure(Call call, IOException e) {
        // 请求失败处理
    }

    @Override
    public 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;
    @Override
    protected 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() {
            @Override
            public void onClick(View v) {
                if (currentPage==CURRENT_PAGE_COUNTY){
                    queryCities();
                }else if(currentPage == CURRENT_PAGE_CITY){
                    queryProvinces();
                }
            }
        });
        mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public 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() {
            @Override
            public void onFailure(Call call, IOException e) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        closeProgressDialog();
                        Toast.makeText(MainActivity.this,"加载失败!!!",Toast.LENGTH_LONG).show();
                    }
                });
            }

            @Override
            public 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() {
                        @Override
                        public 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"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:background="#7283DD"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/teal_200">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/title_text"
            android:layout_centerInParent="true"
            android:textColor="#fff"
            android:textSize="20sp"/>
        <Button
            android: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>
    <ListView
        android: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"/>

    <application
        android: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">
        <activity
            android: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'

运行结果:

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Three.js 设置模型材质纹理贴图和修改材质颜色,材质透明度,材质网格

相关API的使用&#xff1a; 1 traverse &#xff08;模型循环遍历方法&#xff09; 2. THREE.TextureLoader&#xff08;用于加载和处理图片纹理&#xff09; 3. THREE.MeshLambertMaterial&#xff08;用于创建材质&#xff09; 4. getObjectByProperty&#xff08;通过材…

机器学习理论笔记(一):初识机器学习

文章目录 1 前言&#xff1a;蓝色是天的机器学习笔记专栏1.1 专栏初衷与定位1.2 本文主要内容 2 机器学习的定义2.1 机器学习的本质2.2 机器学习的分类 3 机器学习的基本术语4 探索"没有免费的午餐"定理&#xff08;NFL&#xff09;5 结语 1 前言&#xff1a;蓝色是天…

实例038 设置窗体在屏幕中的位置

实例说明 在窗体中可以设置窗体居中显示&#xff0c;本例通过设置窗体的Left属性和Top属性可以准确设置窗体的位置。运行本例&#xff0c;效果如图1.38所示。 技术要点 设置窗体在屏幕中的位置&#xff0c;可以通过设置窗体的属性来实现。窗体的Left属性表示窗体距屏幕左侧的…

android wifi扫描 framework层修改扫描间隔

frameworks/opt/net/wifi/service/java/com/android/server/wifi/ScanRequestProxy.java 这个也就是说前台应用可以在120s(2分钟) 扫描 4 次 * a) Each foreground app can request a max of* {link #SCAN_REQUEST_THROTTLE_MAX_IN_TIME_WINDOW_FG_APPS} scan every* {l…

高并发数据抓取实战:使用HTTP爬虫ip提升抓取速度

又到每天一期学习爬虫的时间了&#xff0c;作为一名专业的爬虫程序员&#xff0c;今天要跟你们分享一个超实用的技巧&#xff0c;就是利用HTTP爬虫ip来提升高并发数据抓取的速度。听起来有点高大上&#xff1f;别担心&#xff0c;我会用通俗易懂的话来和你们说&#xff0c;让你…

【论文阅读】基于深度学习的时序预测——Non-stationary Transformers

系列文章链接 论文一&#xff1a;2020 Informer&#xff1a;长时序数据预测 论文二&#xff1a;2021 Autoformer&#xff1a;长序列数据预测 论文三&#xff1a;2022 FEDformer&#xff1a;长序列数据预测 论文四&#xff1a;2022 Non-Stationary Transformers&#xff1a;非平…

git命令使用

君子拙于不知己,而信于知己。——司马迁 清屏&#xff1a;clear 查看当前面板的路径&#xff1a;pwd 查看当前面板的文件&#xff1a;ls 创建文件夹&#xff1a;mkdir 文件夹名 创建文件&#xff1a;touch 文件名 删除文件夹&#xff1a;rm -rf 文件夹名 删除文件&#xff1a;r…

Vue Baidu Map--自定义点图标bm-marker

自定义点图标 将准备好的图标放到项目中 使用import引入&#xff0c; 并在data中进行声明 <script> import mapIconRed from ./vue-baidu-map/img/marker_red_sprite.png export default {data() {return {mapIconRed,}}, } </script>在<bm-marker>中加入参…

考公-判断推理-逻辑判断-削弱类

否定论点&#xff0c;根本排除 例题 例题 例题 例题 例题 例题 变化小&#xff0c;胖了瘦了 例题 例题 拆桥 例题 例题 例题 例题 例题 例题 例题 例题 例题 A类比非常弱 D削弱了论据 例题 因果倒置例题 例题 例题

从零开始学习 Java:简单易懂的入门指南之MAth、System(十二)

常见API&#xff0c;MAth、System 1 Math类1.1 概述1.2 常见方法1.3 算法小题(质数)1.4 算法小题(自幂数) 2 System类2.1 概述2.2 常见方法 1 Math类 1.1 概述 tips&#xff1a;了解内容 查看API文档&#xff0c;我们可以看到API文档中关于Math类的定义如下&#xff1a; Math类…

平板选择什么电容笔比较好?ipad手写笔推荐品牌

在现在的生活上&#xff0c;有了iPad平板&#xff0c;一切都变得简单了许多&#xff0c;也让我们的学习以及工作都更加的便利。这其中&#xff0c;电容笔就起到了很大的作用&#xff0c;很多人都不知道&#xff0c;到底要买什么牌子的电容笔&#xff1f;哪些电容笔的性价比比较…

设计HTML5文本

网页文本内容丰富、形式多样&#xff0c;通过不同的版式显示在页面中&#xff0c;为用户提供最直接、最丰富的信息。HTML5新增了很多文本标签&#xff0c;它们都有特殊的语义&#xff0c;正确使用这些标签&#xff0c;可以让网页文本更严谨、更符合语义。 1、通用文本 1.1、标…

GPT内功心法:搜索思维到GPT思维的转换

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…

想要自学华为HCIA/HCIP/HCIE认证,并顺利通过考试,不用报班

1、了解认证考试的要求&#xff1a;在开始自学之前&#xff0c;你需要详细了解华为HCIA/HCIP/HCIE认证的考试要求&#xff0c;包括考试科目、考试时间、考试费用等信息。你可以访问华为官方网站或者咨询华为认证中心&#xff0c;获取相关信息。 2、确定考试科目和学习路线&…

SpringBoot系列之基于Jersey实现RESTFul风格文件上传API

前言 JAX-RS&#xff1a;JAX-RS是可以用可以用于实现RESTFul应用程序的JAVA API&#xff0c;给开发者提供了一系列的RESTFul注解Jersey&#xff1a;是基于JAX-RX API的实现框架&#xff0c;用于实现RESTful Web 服务的开源框架。 JAX-RX常用的注解&#xff1a; javax.ws.rs.Pa…

硬件产品经理:从入门到精通(新书发布)

目录 简介 新书 框架内容 相关课程 简介 在完成多款硬件产品从设计到推向市场的过程后。 笔者于2020年开始在产品领域平台输出硬件相关的内容。 在这个过程中经常会收到很多读者的留言&#xff0c;希望能推荐一些硬件相关的书籍或资料。 其实&#xff0c;笔者刚开始做硬…

腾讯云轻量服务器测评:2核 2G 4M

腾讯云轻量2核2G4M服务器&#xff0c;4M带宽下载速度可达512KB/秒&#xff0c;系统盘为50GB SSD盘&#xff0c;300GB月流量&#xff0c;地域节点可选上海、广州和北京&#xff0c;腾讯云百科分享腾讯云2核2G4M轻量应用服务器配置性能表&#xff1a; 目录 腾讯云轻量2核2G4M服…

Steam 灵感的游戏卡悬停效果

先看效果&#xff1a; 再看代码&#xff08;查看更多&#xff09;&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Steam 灵感的游戏卡悬停效果</title><style>* {margin: …

Maven 基础学习及使用

Maven1 Maven简介1.1 Maven模型1.2 仓库 2 Maven安装配置3 Maven基本使用3.1 Maven 常用命令3.2 Maven 生命周期 4 IDEA使用Maven4.1 IDEA配置Maven环境4.2 Maven 坐标详解4.3 IDEA 创建 Maven项目4.4 IDEA 导入 Maven项目 5 依赖管理5.1 使用坐标引入jar包5.2 依赖范围 Maven …

LeetCode--HOT100题(31)

目录 题目描述&#xff1a;25. K 个一组翻转链表&#xff08;困难&#xff09;题目接口解题思路代码 PS: 题目描述&#xff1a;25. K 个一组翻转链表&#xff08;困难&#xff09; 给你链表的头节点 head &#xff0c;每 k 个节点一组进行翻转&#xff0c;请你返回修改后的链表…